Esempio n. 1
0
        private static AsyncParserAction HandleSingleValue(TokenPair token, ParserOptions options,
                                                           ScopeData scopeData,
                                                           InferredTemplateModel scope)
        {
            scope = scope?.GetInferredModelForPath(token.Value, InferredTemplateModel.UsedAs.Scalar);

            return(async(builder, context) =>
            {
                //try to locate the value in the context, if it exists, append it.
                var c = context != null ? (await context.GetContextForPath(token.Value, scopeData)) : null;
                if (c?.Value != null)
                {
                    await c.EnsureValue();

                    if (token.Type == TokenType.EscapedSingleValue && !options.DisableContentEscaping)
                    {
                        HandleContent(HtmlEncodeString(await c.RenderToString()))(builder, c);
                    }
                    else
                    {
                        HandleContent(await c.RenderToString())(builder, c);
                    }
                }
            });
        }
Esempio n. 2
0
        private static AsyncParserAction ParseFormatting(TokenPair token, Queue <TokenPair> tokens,
                                                         ParserOptions options, ScopeData scopeData, InferredTemplateModel currentScope = null)
        {
            var buildArray = new ParserActions();

            buildArray.MakeAction(HandleFormattingValue(token, currentScope, scopeData));

            var nonPrintToken = false;

            while (tokens.Any() && !nonPrintToken)             //only take as few tokens we need for formatting.
            {
                var currentToken = tokens.Peek();
                switch (currentToken.Type)
                {
                case TokenType.Format:
                    //this will invoke the formatter and copy the scope.
                    //we must copy the scope as the formatting action might break our chain and we are no longer able to
                    //construct a valid path up
                    //after that there is always a PrintFormatted type that will print the "current" scope and
                    //reset it to the origial scope before we have entered the scope
                    buildArray.MakeAction(HandleFormattingValue(tokens.Dequeue(), currentScope, scopeData));
                    break;

                case TokenType.PrintFormatted:
                    tokens.Dequeue();                             //this must be the flow token type that has no real value execpt for a dot
                    buildArray.MakeAction(PrintFormattedValues());
                    break;

                case TokenType.CollectionOpen:                         //in this case we are in a formatting expression followed by a #each.
                    //after this we need to reset the context so handle the open here
                    buildArray.MakeAction(HandleCollectionOpen(tokens.Dequeue(), tokens, options, scopeData, currentScope));
                    break;

                case TokenType.ElementOpen:                         //in this case we are in a formatting expression followed by a #.
                    //after this we need to reset the context so handle the open here
                    buildArray.MakeAction(HandleElementOpen(tokens.Dequeue(), tokens, options, scopeData, currentScope));
                    break;

                case TokenType.InvertedElementOpen:                         //in this case we are in a formatting expression followed by a ^.
                    //after this we need to reset the context so handle the open here
                    buildArray.MakeAction(HandleElementOpen(tokens.Dequeue(), tokens, options, scopeData, currentScope));
                    break;

                default:
                    //The following cannot be formatted and the result of the formatting operation has used.
                    //continue with the original Context
                    nonPrintToken = true;
                    break;
                }
            }

            return(async(builder, context) =>
            {
                //the formatting will may change the object. Clone the current Context to leave the root one untouched
                var contextClone = context.Clone();
                await buildArray.ExecuteWith(builder, contextClone);
            });
        }
Esempio n. 3
0
        private static AsyncParserAction HandleCollectionOpen(TokenPair token,
                                                              Queue <TokenPair> remainder,
                                                              ParserOptions options,
                                                              ScopeData scopeData,
                                                              InferredTemplateModel scope)
        {
            scope = scope?.GetInferredModelForPath(token.Value, InferredTemplateModel.UsedAs.Collection);

            var innerTemplate = Parse(remainder, options, scopeData, scope);

            return(async(builder, context) =>
            {
                //if we're in the same scope, just negating, then we want to use the same object
                var c = await context.GetContextForPath(token.Value, scopeData);

                //"falsey" values by Javascript standards...
                if (!await c.Exists())
                {
                    return;
                }

                var value = c.Value as IEnumerable;
                if (value != null && !(value is string) && !(value is IDictionary <string, object>))
                {
                    //Use this "lookahead" enumeration to allow the $last keyword
                    var index = 0;
                    var enumumerator = value.GetEnumerator();
                    if (!enumumerator.MoveNext())
                    {
                        return;
                    }

                    var current = enumumerator.Current;
                    do
                    {
                        var next = enumumerator.MoveNext() ? enumumerator.Current : null;
                        var innerContext = new ContextCollection(index, next == null, options, $"[{index}]")
                        {
                            Value = current,
                            Parent = c
                        };
                        await innerTemplate(builder, innerContext);

                        index++;
                        current = next;
                    } while (current != null && StopOrAbortBuilding(builder, context));
                }
                else
                {
                    throw new IndexedParseException(
                        "'{0}' is used like an array by the template, but is a scalar value or object in your model.",
                        token.Value);
                }
            });
        }
Esempio n. 4
0
        private static AsyncParserAction HandlePartialDeclaration(TokenPair currentToken,
                                                                  Queue <TokenPair> tokens,
                                                                  ParserOptions options,
                                                                  ScopeData scopeData,
                                                                  InferredTemplateModel currentScope)
        {
            var partialTokens = new Queue <TokenPair>();
            var token         = currentToken;

            while (tokens.Any() &&
                   (token.Type != TokenType.PartialDeclarationClose || token.Value != currentToken.Value))                 //just look for the closing tag and buffer it seperate
            {
                token = tokens.Dequeue();
                partialTokens.Enqueue(token);
            }
            return(Parse(partialTokens, options, scopeData, currentScope));            //we have taken everything from the partial and created a executable function for it
        }
Esempio n. 5
0
        private static AsyncParserAction HandleFormattingValue(TokenPair currentToken, InferredTemplateModel scope,
                                                               ScopeData scopeData)
        {
            return(async(builder, context) =>
            {
                scope = scope?.GetInferredModelForPath(currentToken.Value, InferredTemplateModel.UsedAs.Scalar);

                if (context == null)
                {
                    return;
                }
                var c = await context.GetContextForPath(currentToken.Value, scopeData);

                if (currentToken.FormatString != null && currentToken.FormatString.Any())
                {
                    var argList = new List <KeyValuePair <string, object> >();

                    foreach (var formatterArgument in currentToken.FormatString)
                    {
                        //if pre and suffixed by a $ its a reference to another field.
                        //walk the path in the $ and use the value in the formatter
                        var trimmedArg = formatterArgument.Argument.Trim();
                        if (trimmedArg.StartsWith("$") &&
                            trimmedArg.EndsWith("$"))
                        {
                            var formatContext = await context.GetContextForPath(trimmedArg.Trim('$'), scopeData);

                            await formatContext.EnsureValue();

                            argList.Add(new KeyValuePair <string, object>(formatterArgument.Name, formatContext.Value));
                        }
                        else
                        {
                            argList.Add(new KeyValuePair <string, object>(formatterArgument.Name, formatterArgument.Argument));
                        }
                    }
                    //we do NOT await the task here. We await the task only if we need the value
                    context.Value = c.Format(argList.ToArray());
                }
                else
                {
                    context.Value = c.Format(new KeyValuePair <string, object> [0]);
                }
            });
        }
Esempio n. 6
0
        private static AsyncParserAction HandleElementOpen(TokenPair token,
                                                           Queue <TokenPair> remainder,
                                                           ParserOptions options,
                                                           ScopeData scopeData,
                                                           InferredTemplateModel scope)
        {
            scope = scope?.GetInferredModelForPath(token.Value, InferredTemplateModel.UsedAs.ConditionalValue);

            var innerTemplate = Parse(remainder, options, scopeData, scope);

            return(async(builder, context) =>
            {
                var c = await context.GetContextForPath(token.Value, scopeData);

                //"falsey" values by Javascript standards...
                if (await c.Exists())
                {
                    await innerTemplate(builder, c);
                }
            });
        }
Esempio n. 7
0
        private static Action <ByteCounterStreamWriter, ContextObject> HandleElementOpen(TokenPair token,
                                                                                         Queue <TokenPair> remainder,
                                                                                         ParserOptions options, InferredTemplateModel scope)
        {
            scope = scope?.GetInferredModelForPath(token.Value, InferredTemplateModel.UsedAs.ConditionalValue);

            var innerTemplate = Parse(remainder, options, scope);

            return((builder, context) =>
            {
                var c = context.GetContextForPath(token.Value);
                //"falsey" values by Javascript standards...
                if (c.Exists())
                {
                    innerTemplate(builder, c);
                }
            });
        }
Esempio n. 8
0
        private static Action <ByteCounterStreamWriter, ContextObject> HandleSingleValue(TokenPair token, ParserOptions options,
                                                                                         InferredTemplateModel scope)
        {
            scope = scope?.GetInferredModelForPath(token.Value, InferredTemplateModel.UsedAs.Scalar);

            return((builder, context) =>
            {
                //try to locate the value in the context, if it exists, append it.
                var c = context?.GetContextForPath(token.Value);
                if (c?.Value != null)
                {
                    if (token.Type == TokenType.EscapedSingleValue && !options.DisableContentEscaping)
                    {
                        HandleContent(HtmlEncodeString(c.ToString()))(builder, c);
                    }
                    else
                    {
                        HandleContent(c.ToString())(builder, c);
                    }
                }
            });
        }
Esempio n. 9
0
        private static Action <ByteCounterStreamWriter, ContextObject> HandleFormattingValue(TokenPair currentToken,
                                                                                             ParserOptions options, InferredTemplateModel scope)
        {
            return((builder, context) =>
            {
                scope = scope?.GetInferredModelForPath(currentToken.Value, InferredTemplateModel.UsedAs.Scalar);

                if (context == null)
                {
                    return;
                }
                var c = context.GetContextForPath(currentToken.Value);

                if (currentToken.FormatString != null && currentToken.FormatString.Any())
                {
                    var argList = new List <KeyValuePair <string, object> >();

                    foreach (var formatterArgument in currentToken.FormatString)
                    {
                        object value = null;
                        //if pre and suffixed by a $ its a reference to another field.
                        //walk the path in the $ and use the value in the formatter
                        var trimmedArg = formatterArgument.Argument.Trim();
                        if (trimmedArg.StartsWith("$") &&
                            trimmedArg.EndsWith("$"))
                        {
                            var formatContext = context.GetContextForPath(trimmedArg.Trim('$'));
                            argList.Add(new KeyValuePair <string, object>(formatterArgument.Name, formatContext.Value));
                        }
                        else
                        {
                            argList.Add(new KeyValuePair <string, object>(formatterArgument.Name, formatterArgument.Argument));
                        }
                    }
                    context.Value = c.Format(argList.ToArray());
                }
                else
                {
                    context.Value = c.Format(new KeyValuePair <string, object> [0]);
                }
            });
        }
Esempio n. 10
0
        private static Action <ByteCounterStreamWriter, ContextObject> PrintFormattedValues(TokenPair currentToken,
                                                                                            ParserOptions options,
                                                                                            InferredTemplateModel currentScope)
        {
            return((builder, context) =>
            {
                if (context == null)
                {
                    return;
                }

                string value = null;
                if (context.Value != null)
                {
                    value = context.ToString();
                }

                HandleContent(value)(builder, context);
            });
        }
Esempio n. 11
0
        private static Action <ByteCounterStreamWriter, ContextObject> ParseFormatting(TokenPair token, Queue <TokenPair> tokens,
                                                                                       ParserOptions options, InferredTemplateModel currentScope = null)
        {
            var buildArray = new List <Action <ByteCounterStreamWriter, ContextObject> >();

            buildArray.Add(HandleFormattingValue(token, options, currentScope));
            var nonPrintToken = false;

            while (tokens.Any() && !nonPrintToken)
            {
                var currentToken = tokens.Peek();
                switch (currentToken.Type)
                {
                case TokenType.Format:
                    buildArray.Add(HandleFormattingValue(tokens.Dequeue(), options, currentScope));
                    break;

                case TokenType.PrintFormatted:
                    buildArray.Add(PrintFormattedValues(tokens.Dequeue(), options, currentScope));
                    break;

                case TokenType.CollectionOpen:
                    buildArray.Add(HandleCollectionOpen(tokens.Dequeue(), tokens, options, currentScope));
                    break;

                default:
                    //The folloring cannot be formatted and the result of the formatting operation has used.
                    //continue with the original Context
                    nonPrintToken = true;
                    break;
                }
            }

            return((builder, context) =>
            {
                //the formatting will may change the object. Clone the current Context to leave the root one untouched
                var contextClone = context.Clone();
                foreach (var a in buildArray.TakeWhile(e => StopOrAbortBuilding(builder, context)))
                {
                    a(builder, contextClone);
                }
            });
        }
Esempio n. 12
0
        private static Tuple <Tokenizer.HeaderTokenMatch, IValueDocumentItem>[] ParseArgumentHeader(TokenPair currentToken)
        {
            var argumentMap = new List <Tuple <Tokenizer.HeaderTokenMatch, IValueDocumentItem> >();

            foreach (var formatterPart in currentToken.Format?.FormatString ?? new Tokenizer.HeaderTokenMatch[0])
            {
                argumentMap.Add(new Tuple <Tokenizer.HeaderTokenMatch, IValueDocumentItem>(formatterPart,
                                                                                           ParseAsPath(formatterPart)));
            }

            return(argumentMap.ToArray());
        }