Example #1
0
 public static ReadOnlyMemory<char> ChopNewLine(this ReadOnlyMemory<char> literal)
 {
     var lastChar = literal.SafeGetChar(literal.Length - 1);
     if (lastChar == '\r' || lastChar == '\n')
     {
         return literal.Span.SafeCharEquals(literal.Length - 2, '\r')
             ? literal.Slice(0, literal.Length - 2)
             : literal.Slice(0, literal.Length - 1);
     }
     return literal;
 }
        // {{#name}}  {{else if a=b}}  {{else}}  {{/name}}
        //          ^
        // returns    ^                         ^
        static ReadOnlyMemory <char> ParseStatementBody(this ReadOnlyMemory <char> literal, ReadOnlyMemory <char> blockName, out List <PageFragment> body)
        {
            var inStatements = 0;
            var pos          = 0;

            while (true)
            {
                pos = literal.IndexOf("{{", pos);
                if (pos == -1)
                {
                    throw new SyntaxErrorException($"End block for '{blockName}' not found.");
                }

                var c = literal.SafeGetChar(pos + 2);

                if (c == '#')
                {
                    inStatements++;
                    pos = literal.IndexOf("}}", pos) + 2; //end of expression
                    continue;
                }

                if (c == '/')
                {
                    if (inStatements == 0)
                    {
                        literal.Slice(pos + 2 + 1).ParseVarName(out var name);
                        if (name.EqualsOrdinal(blockName))
                        {
                            body = ParseTemplatePage(literal.Slice(0, pos).TrimFirstNewLine());
                            return(literal.Slice(pos));
                        }
                    }

                    inStatements--;
                }
                else if (literal.Slice(pos + 2).StartsWith("else"))
                {
                    if (inStatements == 0)
                    {
                        body = ParseTemplatePage(literal.Slice(0, pos).TrimFirstNewLine());
                        return(literal.Slice(pos));
                    }
                }

                pos += 2;
            }
        }
        //   {{else if a=b}}  {{else}}  {{/name}}
        //  ^
        // returns           ^         ^
        static ReadOnlyMemory <char> ParseElseStatement(this ReadOnlyMemory <char> literal, string blockName, out PageElseBlock statement)
        {
            var inStatements = 0;
            var pos          = 0;

            statement = null;
            var statementPos = -1;
            var elseExpr     = default(ReadOnlyMemory <char>);

            while (true)
            {
                pos = literal.IndexOf("{{", pos);
                if (pos == -1)
                {
                    throw new SyntaxErrorException($"End block for 'else' not found.");
                }

                var c = literal.SafeGetChar(pos + 2);
                if (c == '#')
                {
                    inStatements++;
                    pos = literal.IndexOf("}}", pos) + 2; //end of expression
                }
                else if (c == '/')
                {
                    if (inStatements == 0)
                    {
                        literal.Slice(pos + 2 + 1).ParseVarName(out var name);
                        if (name.EqualsOrdinal(blockName))
                        {
                            var body = ParseTemplatePage(literal.Slice(statementPos, pos - statementPos).TrimFirstNewLine());
                            statement = new PageElseBlock(elseExpr, body);
                            return(literal.Slice(pos));
                        }
                    }

                    inStatements--;
                }
                else if (literal.Slice(pos + 2).StartsWith("else"))
                {
                    if (inStatements == 0)
                    {
                        if (statementPos >= 0)
                        {
                            var bodyText = literal.Slice(statementPos, pos - statementPos).TrimFirstNewLine();
                            var body     = ParseTemplatePage(bodyText);
                            statement = new PageElseBlock(elseExpr, body);
                            return(literal.Slice(pos));
                        }

                        var endExprPos = literal.IndexOf("}}", pos);
                        if (endExprPos == -1)
                        {
                            throw new SyntaxErrorException($"End expression for 'else' not found.");
                        }

                        var exprStartPos = pos + 2 + 4; //= {{else...

                        elseExpr     = literal.Slice(exprStartPos, endExprPos - exprStartPos).Trim();
                        statementPos = endExprPos + 2;
                    }
                }

                pos += 2;
            }
        }