public LiquidString Render( RenderingVisitor renderingVisitor, MacroBlockTag macroBlocktag, ITemplateContext templateContext, IList <Option <ILiquidValue> > args) { var macroScope = new SymbolTable(); var i = 0; foreach (var varName in macroBlocktag.Args.Take(args.Count)) { macroScope.DefineLocalVariable(varName, args[i]); i++; } templateContext.SymbolTableStack.Push(macroScope); String hiddenText = ""; renderingVisitor.PushTextAccumulator(str => hiddenText += str); renderingVisitor.StartWalking(macroBlocktag.LiquidBlock); renderingVisitor.PopTextAccumulator(); templateContext.SymbolTableStack.Pop(); return(LiquidString.Create(hiddenText)); }
private static String EvalLiquidBlock(RenderingVisitor renderingVisitor, TreeNode <IASTNode> liquidBlock) { String result = ""; Action <String> accumulator = str => result += str; renderingVisitor.PushTextAccumulator(accumulator); renderingVisitor.StartWalking(liquidBlock); renderingVisitor.PopTextAccumulator(); return(result); }
private string CaptureHiddenText(TreeNode <IASTNode> liquidBlock) { String hiddenText = ""; _renderingVisitor.PushTextAccumulator(str => hiddenText += str); _renderingVisitor.StartWalking(liquidBlock); _renderingVisitor.PopTextAccumulator(); return(hiddenText); }
private LiquidString IterateBlock( RenderingVisitor renderingVisitor, String varname, ITemplateContext templateContext, List <ILiquidValue> iterable, TreeNode <IASTNode> liquidBlock) { String result = ""; renderingVisitor.PushTextAccumulator(str => result += str); foreach (var item in iterable) { templateContext.SymbolTableStack.Define(varname, item.ToOption()); renderingVisitor.StartWalking(liquidBlock); } renderingVisitor.PopTextAccumulator(); return(LiquidString.Create(result)); }
public void It_Should_Render_An_Error_When_Include_Contains_Parsing_Errors() { // Arrange var ctx = CreateContext(new Dictionary <String, String> { { "test", "problem: {% unterminated" } }).WithAllFilters(); const String template = "{% include 'test' %}"; // Act var ast = new LiquidASTGenerator().Generate(template); var renderingVisitor = new RenderingVisitor(ctx); String result = ""; renderingVisitor.StartWalking(ast.LiquidAST.RootNode, x => result += x); //Console.WriteLine("RESULT: " + result); Assert.Contains("missing TAGEND", result); }
private static string Render(ITemplateContext templateContext, LiquidAST liquidAst, Action <LiquidError> onError = null) { if (onError == null) { onError = error => { }; } String result = ""; var renderingVisitor = new RenderingVisitor(templateContext); renderingVisitor.StartWalking(liquidAst.RootNode, str => result += str); if (renderingVisitor.HasErrors) { foreach (var error in renderingVisitor.RenderingErrors) { onError(error); } //throw new LiquidRendererException(renderingVisitor.RenderingErrors); } return(result); }
public void It_Should_Accumulate_Errors_When_Include_Contains_Rendering_Errors() { // Arrange var ctx = CreateContext(new Dictionary <String, String> { { "test", "problem: {{ 1 | divided_by: 0 }}" } }).WithAllFilters(); //var defaultAstGenerator = ctx.ASTGenerator; //ctx.WithASTGenerator(str => { called = true; return defaultAstGenerator(str); }); const String template = "{% include 'test' %}"; // Act var ast = new LiquidASTGenerator().Generate(template); var renderingVisitor = new RenderingVisitor(ctx); String result = ""; renderingVisitor.StartWalking(ast.LiquidAST.RootNode, x => result += x); //Console.WriteLine(result); Assert.True(renderingVisitor.HasErrors); }
public void It_Should_Accumulate_Errors_When_Include_Contains_Parsing_Errors() { // Arrange var ctx = CreateContext(new Dictionary <String, String> { { "test", "problem: {% unterminated" } }).WithAllFilters(); const String template = "{% include 'test' %}"; // Act var liquidParsingResult = new LiquidASTGenerator().Generate(template); Assert.False(liquidParsingResult.HasParsingErrors); var renderingVisitor = new RenderingVisitor(ctx); String result = ""; renderingVisitor.StartWalking(liquidParsingResult.LiquidAST.RootNode, x => result += x); //Console.WriteLine(result); Assert.True(renderingVisitor.HasErrors); }
public StringValue Render( RenderingVisitor renderingVisitor, MacroBlockTag macroBlocktag, ITemplateContext templateContext, IList<Option<IExpressionConstant>> args) { var macroScope = new SymbolTable(); var i = 0; foreach (var varName in macroBlocktag.Args.Take(args.Count)) { macroScope.DefineLocalVariable(varName, args[i].HasValue? args[i].Value : null); i++; } templateContext.SymbolTableStack.Push(macroScope); //String result = ""; //var subRenderer = new RenderingVisitor(evaluator, templateContext, str => result += str); //evaluator.StartVisiting(subRenderer, macroBlocktag.LiquidBlock); String hiddenText = ""; renderingVisitor.PushTextAccumulator(str => hiddenText += str); renderingVisitor.StartWalking(macroBlocktag.LiquidBlock); renderingVisitor.PopTextAccumulator(); templateContext.SymbolTableStack.Pop(); // foreach (var error in subRenderer.Errors) // { // errorAccumulator.Add(error); // } return new StringValue(hiddenText); }
public void Render(TableRowBlockTag tableRowBlockTag, ITemplateContext templateContext, Action <String> appender) { var offset = LiquidNumeric.Create(0); var limit = LiquidNumeric.Create(50); var cols = LiquidNumeric.Create(5); // TODO: What is the default? https://github.com/Shopify/liquid/blob/master/lib/liquid/tags/table_row.rb if (tableRowBlockTag.Offset != null) { var result = LiquidExpressionEvaluator.Eval(tableRowBlockTag.Offset, templateContext); if (result.IsSuccess) { offset = result.SuccessValue <LiquidNumeric>(); } } if (tableRowBlockTag.Limit != null) { var result = LiquidExpressionEvaluator.Eval(tableRowBlockTag.Limit, templateContext); if (result.IsSuccess) { limit = result.SuccessValue <LiquidNumeric>(); } } if (tableRowBlockTag.Cols != null) { var result = LiquidExpressionEvaluator.Eval(tableRowBlockTag.Cols, templateContext); if (result.IsSuccess) { cols = result.SuccessValue <LiquidNumeric>(); } } var localBlockScope = new SymbolTable(); templateContext.SymbolTableStack.Push(localBlockScope); try { var iterableFactory = tableRowBlockTag.IterableCreator; // TODO: the Eval may result in an LiquidCollection with no Array // (i.e. it's undefined). THe ToList therefore fails.... // this should use Bind var iterable = iterableFactory.Eval(templateContext).ToList(); int length = iterable.Skip(offset.IntValue).Take(limit.IntValue).Count(); if (length == 0) { appender(" <tr class=\"row1\">\r\n</tr>"); // this is what ruby liquid does. return; } int currentrow = 0; int currentcol = 0; bool needsEndOfRow = false; int iter = 0; foreach (var item in iterable.Skip(offset.IntValue).Take(limit.IntValue)) { templateContext.DefineLocalVariable(tableRowBlockTag.LocalVariable, Option <ILiquidValue> .Create(item)); String typename = item == null ? "null" : item.LiquidTypeName; templateContext.DefineLocalVariable("tablerowloop", CreateForLoopDescriptor( tableRowBlockTag.LocalVariable + "-" + typename, // ReSharper disable RedundantArgumentName iter: iter, length: length, col: currentcol, maxcol: cols.IntValue, row: currentrow, stack: templateContext.SymbolTableStack)); // ReSharper restore RedundantArgumentName int rowFromOne = currentrow + 1; int colFromOne = currentcol + 1; if (currentcol == 0) { needsEndOfRow = true; appender(@"<tr class=""row" + rowFromOne + "\">"); if (currentrow == 0) // ruby liquid prints end-of-line on first row. { appender("\r\n"); } } appender("<td class=\"col" + colFromOne + @""">"); _renderingVisitor.StartWalking(tableRowBlockTag.LiquidBlock); appender(@"</td>"); currentcol++; if (currentcol >= cols.IntValue) { needsEndOfRow = false; appender("</tr>\r\n"); currentcol = 0; currentrow++; } iter++; } if (needsEndOfRow) { appender("</tr>\r\n"); } //IterateBlock(forBlockTag, symbolTableStack, iterable); } finally { templateContext.SymbolTableStack.Pop(); } }
private StringValue IterateBlock( RenderingVisitor renderingVisitor, String varname, ITemplateContext templateContext, List<IExpressionConstant> iterable, TreeNode<IASTNode> liquidBlock) { String result = ""; renderingVisitor.PushTextAccumulator(str => result += str); foreach (var item in iterable) { templateContext.SymbolTableStack.Define(varname, item); renderingVisitor.StartWalking(liquidBlock); } renderingVisitor.PopTextAccumulator(); return new StringValue(result); }
private static String EvalLiquidBlock(RenderingVisitor renderingVisitor, TreeNode<IASTNode> liquidBlock) { String result = ""; Action<String> accumulator = str => result += str; renderingVisitor.PushTextAccumulator(accumulator); renderingVisitor.StartWalking(liquidBlock); renderingVisitor.PopTextAccumulator(); return result; }
private static string Render(ITemplateContext templateContext, LiquidAST liquidAst) { String result = ""; var renderingVisitor = new RenderingVisitor(templateContext); renderingVisitor.StartWalking(liquidAst.RootNode, str => result += str); if (renderingVisitor.HasErrors) { throw new LiquidRendererException(renderingVisitor.Errors); } return result; }
private void IterateBlock(ForBlockTag forBlockTag, ITemplateContext templateContext, List <ILiquidValue> iterable) { var offset = LiquidNumeric.Create(0); LiquidNumeric limit = null; if (!templateContext.Options.NoForLimit) { limit = LiquidNumeric.Create(50); // see: https://docs.shopify.com/themes/liquid-documentation/tags/iteration-tags#for } if (forBlockTag.Offset != null) { var result = LiquidExpressionEvaluator.Eval(forBlockTag.Offset, templateContext); if (result.IsSuccess) { offset = result.SuccessValue <LiquidNumeric>(); } } if (forBlockTag.Limit != null) { var result = LiquidExpressionEvaluator.Eval(forBlockTag.Limit, templateContext); if (result.IsSuccess) { limit = result.SuccessValue <LiquidNumeric>(); } } var subset = iterable.Skip(offset.IntValue); if (limit != null) { subset = subset.Take(limit.IntValue); } var subsetList = subset.ToList(); var length = subsetList.Count; if (length <= 0) { _renderingVisitor.StartWalking(forBlockTag.ElseBlock); return; } int iter = 0; //foreach (var item in iterable.Skip(offset.IntValue).Take(limit.IntValue)) foreach (var item in subsetList) { String typename = item == null ? "null" : item.LiquidTypeName; templateContext.SymbolTableStack.Define("forloop", CreateForLoopDescriptor( forBlockTag.LocalVariable + "-" + typename, iter, length, templateContext.SymbolTableStack)); templateContext.SymbolTableStack.Define(forBlockTag.LocalVariable, Option <ILiquidValue> .Create(item)); try { _renderingVisitor.StartWalking(forBlockTag.LiquidBlock); } catch (ContinueException) { continue; } catch (BreakException) { break; } iter++; } }
// public static LiquidAST GenerateSnippetAst(string snippet) // { // return new CachingLiquidASTGenerator(new LiquidASTGenerator()).Generate(snippet); // //return new LiquidASTGenerator().Generate(snippet); // } private void RenderWithLocalScope(ITemplateContext templateContext, SymbolTable localBlockScope, TreeNode <IASTNode> rootNode) { templateContext.SymbolTableStack.Push(localBlockScope); _renderingVisitor.StartWalking(rootNode); templateContext.SymbolTableStack.Pop(); }