Example #1
0
        // {{#if ...}}
        //    ^
        public static ReadOnlyMemory <char> ParseTemplateScriptBlock(this ReadOnlyMemory <char> literal, ScriptContext context, out PageBlockFragment blockFragment)
        {
            literal = literal.ParseVarName(out var blockNameSpan);

            PageBlockFragment statement;
            var blockName  = blockNameSpan.ToString();
            var endBlock   = "{{/" + blockName + "}}";
            var endExprPos = literal.IndexOf("}}");

            if (endExprPos == -1)
            {
                throw new SyntaxErrorException($"Unterminated '{blockName}' block expression, near '{literal.DebugLiteral()}'");
            }

            var argument = literal.Slice(0, endExprPos).Trim();

            literal = literal.Advance(endExprPos + 2);

            var language = context.ParseAsLanguage.TryGetValue(blockName, out var lang)
                ? lang
                : ScriptTemplate.Language;

            if (language.Name == ScriptVerbatim.Language.Name)
            {
                var endBlockPos = literal.IndexOf(endBlock);
                if (endBlockPos == -1)
                {
                    throw new SyntaxErrorException($"Unterminated end block '{endBlock}'");
                }

                var body = literal.Slice(0, endBlockPos);
                literal = literal.Advance(endBlockPos + endBlock.Length).TrimFirstNewLine();

                blockFragment = language.ParseVerbatimBlock(blockName, argument, body);
                return(literal);
            }

            literal = literal.ParseTemplateBody(blockNameSpan, out var bodyText);
            var bodyFragments = language.Parse(context, bodyText);

            var elseBlocks = new List <PageElseBlock>();

            while (literal.StartsWith("{{else"))
            {
                literal = literal.ParseTemplateElseBlock(blockName, out var elseArgument, out var elseBody);

                var elseBlock = new PageElseBlock(elseArgument, language.Parse(context, elseBody));
                elseBlocks.Add(elseBlock);
            }

            literal = literal.Advance(2 + 1 + blockName.Length + 2);

            //remove new line after partial block end tag
            literal = literal.TrimFirstNewLine();

            blockFragment = new PageBlockFragment(blockName, argument, bodyFragments, elseBlocks);

            return(literal);
        }
        // {{#if ...}}
        //    ^
        public static ReadOnlyMemory <char> ParseTemplateScriptBlock(this ReadOnlyMemory <char> literal, ScriptContext context, out PageBlockFragment blockFragment)
        {
            literal = literal.ParseVarName(out var blockNameSpan);

            PageBlockFragment statement;
            var blockName  = blockNameSpan.ToString();
            var endBlock   = "{{/" + blockName + "}}";
            var endExprPos = literal.IndexOf("}}");

            if (endExprPos == -1)
            {
                throw new SyntaxErrorException($"Unterminated '{blockName}' block expression, near '{literal.DebugLiteral()}'");
            }

            var blockExpr = literal.Slice(0, endExprPos).Trim();

            literal = literal.Advance(endExprPos + 2);

            if (context.ParseAsVerbatimBlock.Contains(blockName))
            {
                var endBlockPos = literal.IndexOf(endBlock);
                if (endBlockPos == -1)
                {
                    throw new SyntaxErrorException($"Unterminated end block '{endBlock}'");
                }

                var blockBody = literal.Slice(0, endBlockPos);
                literal = literal.Advance(endBlockPos + endBlock.Length).TrimFirstNewLine();

                var body = new List <PageFragment> {
                    new PageStringFragment(blockBody)
                };
                blockFragment = new PageBlockFragment(blockName, blockExpr, body);

                return(literal);
            }
            else
            {
                var parseAsCode = context.ParseAsCodeBlock.Contains(blockName);

                literal = literal.ParseTemplateBody(blockNameSpan, out var bodyText);
                List <PageFragment> bodyFragments  = null;
                JsBlockStatement    bodyStatements = null;

                if (!parseAsCode)
                {
                    bodyFragments = context.ParseTemplate(bodyText);
                }
                else
                {
                    bodyStatements = context.ParseCode(bodyText);
                }

                var elseBlocks = new List <PageElseBlock>();
                while (literal.StartsWith("{{else"))
                {
                    literal = literal.ParseTemplateElseBlock(blockName, out var elseArgument, out var elseBody);

                    var elseBlock = !parseAsCode
                        ? new PageElseBlock(elseArgument, context.ParseTemplate(elseBody))
                        : new PageElseBlock(elseArgument, context.ParseCode(elseBody));
                    elseBlocks.Add(elseBlock);
                }

                literal = literal.Advance(2 + 1 + blockName.Length + 2);

                //remove new line after partial block end tag
                literal = literal.TrimFirstNewLine();

                blockFragment = !parseAsCode
                    ? new PageBlockFragment(blockName, blockExpr, bodyFragments, elseBlocks)
                    : new PageBlockFragment(blockName, blockExpr, bodyStatements, elseBlocks);

                return(literal);
            }
        }