public void Render(IncludeTag includeTag, ITemplateContext templateContext) { if (templateContext.FileSystem == null) { AddRenderingErrorToResult(new LiquidError { Message = " ERROR: FileSystem is not defined" }); return; } String virtualFileName = null; LiquidExpressionEvaluator.Eval(includeTag.VirtualFileExpression, templateContext) .WhenError(AddRenderingErrorToResult) .WhenSuccess(result => { virtualFileName = ValueCaster.RenderAsString(result); }); if (virtualFileName == null) { return; } //virtualFileName = ValueCaster.RenderAsString(virtualFilenameVar.SuccessResult.Value); String snippet = templateContext.FileSystem.Include(templateContext, virtualFileName); templateContext.SymbolTableStack.DefineLocalRegistry(LOCALREGISTRY_FILE_KEY, virtualFileName); RenderSnippet(includeTag, templateContext, snippet, virtualFileName); }
private void RenderFromLiquidHash(IncludeTag includeTag, ITemplateContext templateContext, String virtualFileName, LiquidAST snippetAst) { Action <SymbolTable> action = localBlockScope => localBlockScope.DefineLocalVariable( virtualFileName, LiquidExpressionEvaluator.Eval(includeTag.ForExpression, templateContext).SuccessResult); RenderBlock(includeTag, templateContext, snippetAst, action); }
private void RenderIncludeBlock(IncludeTag includeTag, ITemplateContext templateContext, String virtualFileName, LiquidAST snippetAst) { Action <SymbolTable> action = localBlockScope => { if (includeTag.WithExpression != null) { var withExpression = LiquidExpressionEvaluator.Eval(includeTag.WithExpression, templateContext); localBlockScope.DefineLocalVariable(virtualFileName, withExpression.SuccessResult); } }; RenderBlock(includeTag, templateContext, snippetAst, action); }
private static void DefineLocalVariables( ITemplateContext templateContext, SymbolTable localBlockScope, IDictionary <string, TreeNode <LiquidExpression> > definitions) { foreach (var def in definitions) { var def1 = def; LiquidExpressionEvaluator.Eval(def.Value, templateContext) //.WhenError( err => //TODO: Is this necessary? .WhenSuccess(result => localBlockScope.DefineLocalVariable(def1.Key, result)); } }
public IEnumerable <ILiquidValue> Eval(ITemplateContext templateContext) { var expressionConstant = LiquidExpressionEvaluator.Eval(_liquidCollectionExpression, templateContext); if (expressionConstant.IsError || !expressionConstant.SuccessResult.HasValue) { return(new List <ILiquidValue>()); } var castResult = ValueCaster.Cast <ILiquidValue, LiquidCollection>(expressionConstant.SuccessResult.Value); if (castResult.IsError) { // ?? return(new List <ILiquidValue>()); } else { return(castResult.SuccessValue <LiquidCollection>().Select(x => x.HasValue? x.Value : null)); } }
private void RenderSnippet(IncludeTag includeTag, ITemplateContext templateContext, String snippet, String virtualFileName) { var snippetAstTry = CreateAstFromSnippet(templateContext, snippet, virtualFileName); if (snippetAstTry.IsLeft) { foreach (var err in snippetAstTry.Left) { AddParsingErrorToResult(err); } return; } var snippetAst = snippetAstTry.Right; //zzz if (includeTag.ForExpression != null) { LiquidExpressionEvaluator.Eval(includeTag.ForExpression, templateContext) .WhenError(AddRenderingErrorToResult) .WhenSuccess(result => { if (result.Value is LiquidHash) { // it seems to render as a single element if it's a dictionary. RenderFromLiquidHash(includeTag, templateContext, virtualFileName, snippetAst); } else { RenderFromLiquidExpression(includeTag, templateContext, virtualFileName, result, snippetAst); } }); } else { RenderIncludeBlock(includeTag, templateContext, virtualFileName, snippetAst); } }
private LiquidNumeric ValueAsNumeric(TreeNode <LiquidExpression> expr, ITemplateContext templateContext) { var liquidExpressionResult = LiquidExpressionEvaluator.Eval(expr, templateContext); if (liquidExpressionResult.IsError) { return(LiquidNumeric.Create(0)); } var valueAsNumeric = liquidExpressionResult.SuccessResult.Value as LiquidNumeric; if (valueAsNumeric == null) { var castedValue = ValueCaster.Cast <ILiquidValue, LiquidNumeric>(liquidExpressionResult.SuccessResult.Value); return(liquidExpressionResult.IsSuccess && liquidExpressionResult.SuccessResult.HasValue ? castedValue.SuccessValue <LiquidNumeric>() : LiquidNumeric.Create(0)); } else { return(valueAsNumeric); } }
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 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++; } }