Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
 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));
     }
 }
Beispiel #5
0
        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));
            }
        }
Beispiel #6
0
        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);
            }
        }
Beispiel #7
0
        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++;
            }
        }