コード例 #1
0
ファイル: Parser.cs プロジェクト: wildbit/mustachio
        /// <summary>
        /// Parse the template, and capture paths used in the template to determine a suitable structure for the required model.
        /// </summary>
        /// <param name="templateSource">The template content to parse.</param>
        /// <param name="disableContentEscaping">In some cases, content should not be escaped (such as when rendering text bodies and subjects in emails). 
        /// By default, we use content escaping, but this parameter allows it to be disabled.</param>
        /// <returns></returns>
        public static ExtendedParseInformation ParseWithModelInference(string templateSource, bool disableContentEscaping = false)
        {
            var tokens = new Queue<TokenPair>(Tokenizer.Tokenize(templateSource));
            var options = new ParsingOptions { DisableContentSafety = disableContentEscaping };
            var inferredModel = new InferredTemplateModel();

            var internalTemplate = Parse(tokens, options, inferredModel);
            Func<IDictionary<String, object>, String> template = (model) =>
            {
                var retval = new StringBuilder();
                var context = new ContextObject()
                {
                    Value = model,
                    Key = ""
                };
                internalTemplate(retval, context);
                return retval.ToString();
            };

            var result = new ExtendedParseInformation()
            {
                InferredModel = inferredModel,
                ParsedTemplate = template
            };

            return result;
        }
コード例 #2
0
        private static Action <StringBuilder, ContextObject> HandleCollectionOpen(TokenPair token, Queue <TokenPair> remainder, ParsingOptions options, InferredTemplateModel scope)
        {
            if (scope != null)
            {
                scope = scope.GetInferredModelForPath(token.Value, InferredTemplateModel.UsedAs.Collection);
            }

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

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

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

                IEnumerable cVal = null;

                if (c.Value is IEnumerable && !(c.Value is String) && !(c.Value is IDictionary <string, object>))
                {
                    cVal = c.Value as IEnumerable;
                }
                else
                {
                    //Ok, this is a scalar value or an Object. So lets box it into an IEnumerable
                    cVal = new ArrayList()
                    {
                        c.Value
                    };
                }

                var index = 0;
                foreach (object i in cVal)
                {
                    var innerContext = new ContextObject()
                    {
                        Value = i,
                        Key = String.Format("[{0}]", index),
                        Parent = c
                    };
                    innerTemplate(builder, innerContext);
                    index++;
                }
            });
        }
コード例 #3
0
ファイル: Parser.cs プロジェクト: wildbit/mustachio
 /// <summary>
 /// Parse the template content, producing a function that can be used to apply variables to the template. 
 /// The provided function can be reused (i.e. no state will "leak" from one application of the function to the next).
 /// </summary>
 /// <param name="template">The content of the template to be parsed.</param>
 /// <param name="disableContentEscaping">In some cases, content should not be escaped (such as when rendering text bodies and subjects in emails). 
 /// By default, we use content escaping, but this parameter allows it to be disabled.</param>
 /// <returns></returns>
 public static Func<IDictionary<String, object>, String> Parse(string template, bool disableContentEscaping = false)
 {
     var tokens = new Queue<TokenPair>(Tokenizer.Tokenize(template));
     var internalTemplate = Parse(tokens, new ParsingOptions { DisableContentSafety = disableContentEscaping });
     return (model) =>
     {
         var retval = new StringBuilder();
         var context = new ContextObject()
         {
             Value = model,
             Key = ""
         };
         internalTemplate(retval, context);
         return retval.ToString();
     };
 }
コード例 #4
0
ファイル: Parser.cs プロジェクト: wuhanhan/mustachio
        /// <summary>
        /// Parse the template content, producing a function that can be used to apply variables to the template.
        /// The provided function can be reused (i.e. no state will "leak" from one application of the function to the next).
        /// </summary>
        /// <param name="template">The content of the template to be parsed.</param>
        /// <param name="options">Options for configuring/extending the parser.</param>
        /// <returns></returns>
        public static Func <IDictionary <String, object>, String> Parse(string template, ParsingOptions options)
        {
            var tokensQueue      = GetTokensQueue(template, options);
            var internalTemplate = Parse(tokensQueue, options);

            return((model) =>
            {
                var retval = new StringBuilder();
                var context = new ContextObject()
                {
                    Value = model,
                    Key = ""
                };
                internalTemplate(retval, context);
                return retval.ToString();
            });
        }
コード例 #5
0
        /// <summary>
        /// Parse the template content, producing a function that can be used to apply variables to the template.
        /// The provided function can be reused (i.e. no state will "leak" from one application of the function to the next).
        /// </summary>
        /// <param name="template">The content of the template to be parsed.</param>
        /// <param name="disableContentEscaping">In some cases, content should not be escaped (such as when rendering text bodies and subjects in emails).
        /// By default, we use content escaping, but this parameter allows it to be disabled.</param>
        /// <returns></returns>
        public static Func <IDictionary <String, object>, String> Parse(string template, bool disableContentEscaping = false)
        {
            var tokens           = new Queue <TokenPair> (Tokenizer.Tokenize(template));
            var internalTemplate = Parse(tokens, new ParsingOptions {
                DisableContentSafety = disableContentEscaping
            });

            return((model) =>
            {
                var retval = new StringBuilder();
                var context = new ContextObject()
                {
                    Value = model,
                    Key = ""
                };
                internalTemplate(retval, context);
                return retval.ToString();
            });
        }
コード例 #6
0
        private static Action <StringBuilder, ContextObject> HandleCollectionOpen(TokenPair token, Queue <TokenPair> remainder, ParsingOptions options, InferredTemplateModel scope)
        {
            if (scope != null)
            {
                scope = scope.GetInferredModelForPath(token.Value, InferredTemplateModel.UsedAs.Collection);
            }

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

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

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

                if (c.Value is IEnumerable && !(c.Value is String) && !(c.Value is IDictionary <string, object>))
                {
                    var index = 0;
                    foreach (object i in c.Value as IEnumerable)
                    {
                        var innerContext = new ContextObject()
                        {
                            Value = i,
                            Key = String.Format("[{0}]", index),
                            Parent = c
                        };
                        innerTemplate(builder, innerContext);
                        index++;
                    }
                }
                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);
                }
            });
        }
コード例 #7
0
        private ContextObject GetContextForPath(Queue <String> elements)
        {
            var retval = this;

            if (elements.Any())
            {
                var element = elements.Dequeue();
                if (element.StartsWith(".."))
                {
                    if (Parent != null)
                    {
                        retval = Parent.GetContextForPath(elements);
                    }
                    else
                    {
                        //calling "../" too much may be "ok" in that if we're at root,
                        //we may just stop recursion and traverse down the path.
                        retval = GetContextForPath(elements);
                    }
                }
                //TODO: handle array accessors and maybe "special" keys.
                else
                {
                    //ALWAYS return the context, even if the value is null.
                    var innerContext = new ContextObject();
                    innerContext.Key    = element;
                    innerContext.Parent = this;
                    var ctx = this.Value as IDictionary <string, object>;
                    if (ctx != null)
                    {
                        object o;
                        ctx.TryGetValue(element, out o);
                        innerContext.Value = o;
                    }
                    retval = innerContext.GetContextForPath(elements);
                }
            }
            return(retval);
        }
コード例 #8
0
ファイル: Parser.cs プロジェクト: wildbit/mustachio
        private static Action<StringBuilder, ContextObject> HandleCollectionOpen(TokenPair token, Queue<TokenPair> remainder, ParsingOptions options, InferredTemplateModel scope)
        {
            if (scope != null)
            {
                scope = scope.GetInferredModelForPath(token.Value, InferredTemplateModel.UsedAs.Collection);
            }

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

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

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

                if (c.Value is IEnumerable && !(c.Value is String) && !(c.Value is IDictionary<string, object>))
                {
                    var index = 0;
                    foreach (object i in c.Value as IEnumerable)
                    {
                        var innerContext = new ContextObject()
                        {
                            Value = i,
                            Key = String.Format("[{0}]", index),
                            Parent = c
                        };
                        innerTemplate(builder, innerContext);
                        index++;
                    }
                }
                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);
                }
            };
        }
コード例 #9
0
ファイル: ContextObject.cs プロジェクト: wildbit/mustachio
 private ContextObject GetContextForPath(Queue<String> elements)
 {
     var retval = this;
     if (elements.Any())
     {
         var element = elements.Dequeue();
         if (element.StartsWith(".."))
         {
             if (Parent != null)
             {
                 retval = Parent.GetContextForPath(elements);
             }
             else
             {
                 //calling "../" too much may be "ok" in that if we're at root,
                 //we may just stop recursion and traverse down the path.
                 retval = GetContextForPath(elements);
             }
         }
         //TODO: handle array accessors and maybe "special" keys.
         else
         {
             //ALWAYS return the context, even if the value is null.
             var innerContext = new ContextObject();
             innerContext.Key = element;
             innerContext.Parent = this;
             var ctx = this.Value as IDictionary<string, object>;
             if (ctx != null)
             {
                 object o;
                 ctx.TryGetValue(element, out o);
                 innerContext.Value = o;
             }
             retval = innerContext.GetContextForPath(elements);
         }
     }
     return retval;
 }