Пример #1
0
        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);
            }
Пример #3
0
        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));
            }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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);



        }
Пример #10
0
        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;
 }
Пример #14
0
        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++;
            }
        }
Пример #15
0
//        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();
        }