Exemplo n.º 1
0
        public static List <PageFragment> ParseTemplatePage(ReadOnlyMemory <char> text)
        {
            var to = new List <PageFragment>();

            if (text.IsNullOrWhiteSpace())
            {
                return(to);
            }

            int pos;
            var lastPos = 0;

            while ((pos = text.IndexOf("{{", lastPos)) != -1)
            {
                var block = text.Slice(lastPos, pos - lastPos);
                if (!block.IsNullOrEmpty())
                {
                    to.Add(new PageStringFragment(block));
                }

                var varStartPos = pos + 2;

                var firstChar = text.Span[varStartPos];
                if (firstChar == '*') //comment
                {
                    lastPos = text.IndexOf("*}}", varStartPos) + 3;
                }
                else if (firstChar == '#') //block statement
                {
                    var literal = text.Slice(varStartPos + 1);
                    literal = literal.ParseVarName(out var blockNameSpan);

                    var blockName  = blockNameSpan.ToString();
                    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 (!ScriptConfig.DontEvaluateBlocksNamed.Contains(blockName))
                    {
                        literal = literal.ParseStatementBody(blockNameSpan, out var body);
                        var elseStatements = new List <PageElseBlock>();

                        while (literal.StartsWith("{{else"))
                        {
                            literal = literal.ParseElseStatement(blockName, out var elseStatement);
                            elseStatements.Add(elseStatement);
                        }

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

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

                        var length       = text.Length - pos - literal.Length;
                        var originalText = text.Slice(pos, length);
                        lastPos = pos + length;

                        var statement = new PageBlockFragment(originalText, blockName, blockExpr, body, elseStatements);
                        to.Add(statement);
                    }
                    else
                    {
                        var endBlock    = "{{/" + blockName + "}}";
                        var endBlockPos = literal.IndexOf(endBlock);
                        if (endBlockPos == -1)
                        {
                            throw new SyntaxErrorException($"Unterminated end block '{endBlock}'");
                        }

                        var endBlockBody = literal.Slice(0, endBlockPos);
                        literal = literal.Advance(endBlockPos + endBlock.Length).TrimFirstNewLine();
                        var body = new List <PageFragment> {
                            new PageStringFragment(endBlockBody)
                        };

                        var length       = text.Length - pos - literal.Length;
                        var originalText = text.Slice(pos, length);
                        lastPos = pos + length;

                        var statement = new PageBlockFragment(originalText, blockName, blockExpr, body);
                        to.Add(statement);
                    }
                }
                else
                {
                    var literal = text.Slice(varStartPos).Span;
                    literal = literal.ParseJsExpression(out var expr, filterExpression: true);

                    var filters = new List <JsCallExpression>();

                    if (!literal.StartsWith("}}"))
                    {
                        literal = literal.AdvancePastWhitespace();
                        if (literal.FirstCharEquals(FilterSep))
                        {
                            literal = literal.Advance(1);

                            while (true)
                            {
                                literal = literal.ParseJsCallExpression(out var filter, filterExpression: true);

                                filters.Add(filter);

                                literal = literal.AdvancePastWhitespace();

                                if (literal.IsNullOrEmpty())
                                {
                                    throw new SyntaxErrorException("Unterminated filter expression");
                                }

                                if (literal.StartsWith("}}"))
                                {
                                    literal = literal.Advance(2);
                                    break;
                                }

                                if (!literal.FirstCharEquals(FilterSep))
                                {
                                    throw new SyntaxErrorException(
                                              $"Expected filter separator '|' but was {literal.DebugFirstChar()}");
                                }

                                literal = literal.Advance(1);
                            }
                        }
                        else
                        {
                            if (!literal.IsNullOrEmpty())
                            {
                                literal = literal.Advance(1);
                            }
                        }
                    }
                    else
                    {
                        literal = literal.Advance(2);
                    }

                    var length       = text.Length - pos - literal.Length;
                    var originalText = text.Slice(pos, length);
                    lastPos = pos + length;

                    var varFragment = new PageVariableFragment(originalText, expr, filters);
                    to.Add(varFragment);

                    var newLineLen = literal.StartsWith("\n")
                        ? 1
                        : literal.StartsWith("\r\n")
                            ? 2
                            : 0;

                    if (newLineLen > 0)
                    {
                        var lastExpr   = varFragment.FilterExpressions?.LastOrDefault();
                        var filterName = lastExpr?.Name ??
                                         varFragment?.InitialExpression?.Name ?? varFragment.Binding;
                        if (filterName != null && ScriptConfig.RemoveNewLineAfterFiltersNamed.Contains(filterName))
                        {
                            lastPos += newLineLen;
                        }
                    }
                }
            }

            if (lastPos != text.Length)
            {
                var lastBlock = lastPos == 0 ? text : text.Slice(lastPos);
                to.Add(new PageStringFragment(lastBlock));
            }

            return(to);
        }
Exemplo n.º 2
0
        public static List <PageFragment> ParseTemplatePage(StringSegment text)
        {
            var to = new List <PageFragment>();

            if (text.IsNullOrWhiteSpace())
            {
                return(to);
            }

            int pos;
            var lastPos = 0;

            while ((pos = text.IndexOf("{{", lastPos)) != -1)
            {
                var block = text.Subsegment(lastPos, pos - lastPos);
                if (!block.IsNullOrEmpty())
                {
                    to.Add(new PageStringFragment(block));
                }

                var varStartPos = pos + 2;

                var isComment = text.GetChar(varStartPos) == '*';
                if (!isComment)
                {
                    var literal = text.Subsegment(varStartPos).ParseNextToken(out object initialValue, out JsBinding initialBinding, allowWhitespaceSyntax: true);

                    List <JsExpression> filterCommands = null;

                    literal = literal.ParseNextToken(out _, out JsBinding filterOp);
                    if (filterOp == JsBitwiseOr.Operator)
                    {
                        var  varEndPos   = 0;
                        bool foundVarEnd = false;

                        filterCommands = literal.ParseExpression <JsExpression>(
                            separator: '|',
                            atEndIndex: (str, strPos) =>
                        {
                            while (str.Length > strPos && str.GetChar(strPos).IsWhiteSpace())
                            {
                                strPos++;
                            }

                            if (str.Length > strPos + 1 && str.GetChar(strPos) == '}' && str.GetChar(strPos + 1) == '}')
                            {
                                foundVarEnd = true;
                                varEndPos   = varEndPos + 1 + strPos + 1;
                                return(strPos);
                            }
                            return(null);
                        },
                            allowWhitespaceSensitiveSyntax: true);

                        if (!foundVarEnd)
                        {
                            throw new ArgumentException($"Invalid syntax near '{text.Subsegment(pos).SubstringWithElipsis(0, 50)}'");
                        }

                        literal = literal.Advance(varEndPos);
                    }
                    else
                    {
                        literal = literal.Advance(1);
                    }

                    var length       = text.Length - pos - literal.Length;
                    var originalText = text.Subsegment(pos, length);
                    lastPos = pos + length;

                    var varFragment = new PageVariableFragment(originalText, initialValue, initialBinding, filterCommands);
                    to.Add(varFragment);

                    var newLineLen = literal.StartsWith("\n")
                        ? 1
                        : literal.StartsWith("\r\n")
                            ? 2
                            : 0;
                    if (newLineLen > 0)
                    {
                        var lastExpr   = varFragment.FilterExpressions?.LastOrDefault();
                        var filterName = lastExpr?.NameString ?? varFragment?.InitialExpression?.NameString ?? varFragment.BindingString;
                        if (filterName != null && TemplateConfig.RemoveNewLineAfterFiltersNamed.Contains(filterName))
                        {
                            lastPos += newLineLen;
                        }
                    }
                }
                else
                {
                    lastPos = text.IndexOf("*}}", varStartPos) + 3;
                }
            }

            if (lastPos != text.Length)
            {
                var lastBlock = lastPos == 0 ? text : text.Subsegment(lastPos);
                to.Add(new PageStringFragment(lastBlock));
            }

            return(to);
        }
Exemplo n.º 3
0
        public static List <PageFragment> ParseTemplatePage(StringSegment text)
        {
            var to = new List <PageFragment>();

            if (text.IsNullOrWhiteSpace())
            {
                return(to);
            }

            int pos;
            var lastPos = 0;

            while ((pos = text.IndexOf("{{", lastPos)) != -1)
            {
                var block = text.Subsegment(lastPos, pos - lastPos);
                if (!block.IsNullOrEmpty())
                {
                    to.Add(new PageStringFragment(block));
                }

                var varStartPos = pos + 2;

                var isComment = text.GetChar(varStartPos) == '*';
                if (!isComment)
                {
                    var literal = text.Subsegment(varStartPos);
                    literal = literal.ParseJsExpression(out var expr, filterExpression: true);

                    var filters = new List <JsCallExpression>();

                    if (!literal.StartsWith("}}"))
                    {
                        literal = literal.ParseJsToken(out var filterOp);
                        if (filterOp == JsBitwiseOr.Operator)
                        {
                            while (true)
                            {
                                literal = literal.ParseJsCallExpression(out var filter, filterExpression: true);

                                filters.Add(filter);

                                literal = literal.AdvancePastWhitespace();

                                if (literal.IsNullOrEmpty())
                                {
                                    throw new SyntaxErrorException("Unterminated filter expression");
                                }

                                if (literal.StartsWith("}}"))
                                {
                                    literal = literal.Advance(2);
                                    break;
                                }

                                if (literal.GetChar(0) != '|')
                                {
                                    throw new SyntaxErrorException($"Expected filter separator '|' but was '{literal.GetChar(0)}'");
                                }

                                literal = literal.Advance(1);
                            }
                        }
                        else
                        {
                            if (!literal.IsNullOrEmpty())
                            {
                                literal = literal.Advance(1);
                            }
                        }
                    }
                    else
                    {
                        literal = literal.Advance(2);
                    }

                    var length       = text.Length - pos - literal.Length;
                    var originalText = text.Subsegment(pos, length);
                    lastPos = pos + length;

                    var varFragment = new PageVariableFragment(originalText, expr, filters);
                    to.Add(varFragment);

                    var newLineLen = literal.StartsWith("\n")
                        ? 1
                        : literal.StartsWith("\r\n")
                            ? 2
                            : 0;

                    if (newLineLen > 0)
                    {
                        var lastExpr   = varFragment.FilterExpressions?.LastOrDefault();
                        var filterName = lastExpr?.Name ?? varFragment?.InitialExpression?.Name ?? varFragment.BindingString;
                        if (filterName != null && TemplateConfig.RemoveNewLineAfterFiltersNamed.Contains(filterName))
                        {
                            lastPos += newLineLen;
                        }
                    }
                }
                else
                {
                    lastPos = text.IndexOf("*}}", varStartPos) + 3;
                }
            }

            if (lastPos != text.Length)
            {
                var lastBlock = lastPos == 0 ? text : text.Subsegment(lastPos);
                to.Add(new PageStringFragment(lastBlock));
            }

            return(to);
        }
Exemplo n.º 4
0
 /// <summary>
 /// Equalses the specified other.
 /// </summary>
 /// <param name="other">The other.</param>
 /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
 protected bool Equals(PageVariableFragment other)
 {
     return(OriginalText.Span.SequenceEqual(other.OriginalText.Span) &&
            Equals(Expression, other.Expression) &&
            FilterExpressions.EquivalentTo(other.FilterExpressions));
 }
Exemplo n.º 5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="JsFilterExpressionStatement"/> class.
 /// </summary>
 /// <param name="originalText">The original text.</param>
 /// <param name="expr">The expr.</param>
 /// <param name="filters">The filters.</param>
 public JsFilterExpressionStatement(string originalText, JsToken expr, params JsCallExpression[] filters)
 {
     FilterExpression = new PageVariableFragment(originalText.AsMemory(), expr, new List <JsCallExpression>(filters));
 }
Exemplo n.º 6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="JsFilterExpressionStatement"/> class.
 /// </summary>
 /// <param name="originalText">The original text.</param>
 /// <param name="expr">The expr.</param>
 /// <param name="filters">The filters.</param>
 public JsFilterExpressionStatement(ReadOnlyMemory <char> originalText, JsToken expr, List <JsCallExpression> filters)
 {
     FilterExpression = new PageVariableFragment(originalText, expr, filters);
 }