コード例 #1
0
        string RenderPartial(Token token, MustacheContext ctx, string indent)
        {
            string name = token.Name;

            if (Partials == null)
            {
                return(string.Empty);
            }

            var partial = string.Empty;

            if (!Partials.TryGetValue(name, out partial))
            {
                return(string.Empty);
            }

            var key = "# partial #" + name + "#" + indent;

            if (!Cache.ContainsKey(key))
            {
                if (string.IsNullOrEmpty(indent))
                {
                    Cache[key] = new MustacheParser().Parse(partial, Delimiter.Default());
                }
                else
                {
                    var replaced = Regex.Replace(partial, @"^(.+)$", indent + "$1", RegexOptions.Multiline);
                    Cache[key] = new MustacheParser().Parse(replaced, Delimiter.Default());
                }
            }

            return(RenderTokens(ctx, Cache[key]));
        }
コード例 #2
0
        string RenderName(Token token, MustacheContext ctx, bool escape)
        {
            var value = ctx.Lookup(token.Name);

            if (value == null && StrictMode)
            {
                throw new MustacheException(string.Format("lookup failed name:'{0}' around:\n...{1}...\n", token.Name, token.SurroundingTemplate));
            }

            if (value == null)
            {
                return(string.Empty);
            }

            if (value.IsLambda())
            {
                var template = value.InvokeNameLambda() as string;
                var tokens   = new MustacheParser().Parse(template, Delimiter.Default());
                value = RenderTokens(ctx, tokens);

                // Recheck for null
                if (value == null)
                {
                    return(string.Empty);
                }
            }

            var s = value.ToString();

            if (s == "{ }")
            {
                return(string.Empty);
            }

            if (escape)
            {
                return(System.Web.HttpUtility.HtmlEncode(s));
            }

            return(s);
        }
コード例 #3
0
        /// <summary>
        /// Parses and applies given template and returns rendered string.
        /// </summary>
        /// <param name="template">Mustache template string.</param>
        /// <param name="data">Data object.</param>
        /// <param name="partials">Partial templates.</param>
        /// <returns>Rendered string.</returns>
        public string Render(string template, object data, Dictionary <string, string> partials = null)
        {
            if (template == null)
            {
                throw new ArgumentNullException("template");
            }

            if (partials != null)
            {
                Partials = partials;
            }

            if (string.IsNullOrEmpty(template))
            {
                return(string.Empty);
            }

            if (!Cache.ContainsKey(template))
            {
                Cache[template] = new MustacheParser().Parse(template, Delimiter.Default());
            }

            return(RenderTokens(new MustacheContext(data, null), Cache[template]));
        }
コード例 #4
0
        /// <summary>
        /// Parses given template and returns the corresponding tokens.
        /// </summary>
        /// <param name="template">The mustache template string</param>
        /// <param name="delimiter">The delimiter.</param>
        /// <returns>Corresponding tokens.</returns>
        public List <Token> Parse(string template, Delimiter delimiter)
        {
            var scanner = new MustacheScanner(template);
            var tokens  = new List <Token>();
            var start   = scanner.Pos;
            var lastBol = 0;

            Action <int> pushText = (int end) =>
            {
                if (start < end && end <= template.Length)
                {
                    tokens.Add(new Token
                    {
                        Template         = template,
                        Type             = TokenType.Text,
                        StartIndex       = start,
                        TextLength       = end - start,
                        IsBol            = start == lastBol,
                        CurrentDelimiter = delimiter,
                    });
                }
            };

            for (var ok = true; ok;)
            {
                if (scanner.Pos == 0 || scanner.Peek(-1) == '\n')
                {
                    lastBol = scanner.Pos;
                }

                if (scanner.Peek() == '\n')
                {
                    pushText(scanner.Pos + 1);
                    start = scanner.Pos + 1;
                    ok    = scanner.Seek(1);
                }
                else if (scanner.StartsWith(delimiter.Open))
                {
                    if (start < scanner.Pos)
                    {
                        pushText(scanner.Pos);
                        start = scanner.Pos;
                    }

                    ok = scanner.Seek(delimiter.Open.Length); // discard begin tag

                    var tokenChar = scanner.Peek();
                    var tokenType = TokenInfo(tokenChar);
                    var value     = string.Empty;

                    if (tokenType != TokenType.Variable)
                    {
                        scanner.Seek(1); // discard token type character
                    }

                    if (tokenType == TokenType.DelimiterChange)
                    {
                        value = scanner.ReadUntilJustBefore("=").Trim();
                        scanner.Seek(1); // discard '='
                        scanner.SeekUntilJustBefore(delimiter.Close);
                    }
                    else if (tokenType == TokenType.UnescapedVariable && tokenChar == '{')
                    {
                        value = scanner.ReadUntilJustBefore("}" + delimiter.Close).Trim();
                        scanner.Seek(1); // discard '}'
                    }
                    else
                    {
                        value = scanner.ReadUntilJustBefore(delimiter.Close).Trim();
                    }

                    if (!scanner.StartsWith(delimiter.Close))
                    {
                        throw new MustacheException("Unclosed tag at " + scanner.Pos);
                    }

                    if (tokenType != TokenType.Comment && tokenType != TokenType.DelimiterChange)
                    {
                        if (string.IsNullOrEmpty(value))
                        {
                            throw new MustacheException("Empty token name at " + scanner.Pos);
                        }

                        foreach (var c in value)
                        {
                            if (!(char.IsLetterOrDigit(c) || c == '.' || c == '_'))
                            {
                                throw new MustacheException("Invalid token name '" + value + "' at " + scanner.Pos);
                            }
                        }

                        if (ProhibitedWords.Contains(value))
                        {
                            throw new MustacheException("Invalid token name '" + value + "' at " + scanner.Pos);
                        }
                    }

                    var token = new Token
                    {
                        Template         = template,
                        Type             = tokenType,
                        Name             = value,
                        StartIndex       = start,
                        IsBol            = start == lastBol,
                        CurrentDelimiter = delimiter,
                    };

                    start = scanner.Pos + delimiter.Close.Length;
                    ok    = scanner.Seek(delimiter.Close.Length); // discard end tag

                    token.SectionStartIndex = start;
                    tokens.Add(token);

                    if (tokenType == TokenType.DelimiterChange)
                    {
                        if (string.IsNullOrEmpty(value))
                        {
                            throw new MustacheException("Empty delimiter at " + scanner.Pos);
                        }

                        var sp = value.Split(null as string[], StringSplitOptions.RemoveEmptyEntries);
                        if (sp.Length != 2)
                        {
                            throw new MustacheException("Invalid delimiter format at " + scanner.Pos);
                        }

                        delimiter = new Delimiter {
                            Open = sp[0], Close = sp[1]
                        };
                    }
                }
                else
                {
                    ok = scanner.Seek(1);
                }
            }

            pushText(scanner.Pos + 1);

            SquashTokens(ref tokens);
            return(NestTokens(tokens));
        }