Example #1
0
        private static string AccumulateLiteral(ExtendedStringReader reader, bool captureDelimiter, params char[] delimiters)
        {
            using (var container = StringBuilderPool.Shared.Use())
            {
                var buffer = container.Value;
                while (true)
                {
                    var node = reader.Peek();
                    if (node == -1)
                    {
                        throw new HandlebarsParserException("Reached end of template before the expression was closed.", reader.GetContext());
                    }

                    if (delimiters.Contains((char)node))
                    {
                        if (captureDelimiter)
                        {
                            reader.Read();
                        }
                        break;
                    }

                    if (!captureDelimiter && (char)node == '}')
                    {
                        break;
                    }

                    buffer.Append((char)reader.Read());
                }

                return(buffer.ToString());
            }
        }
Example #2
0
        private static string AccumulateComment(ExtendedStringReader reader)
        {
            reader.Read();
            bool?escaped = null;

            using (var container = StringBuilderPool.Shared.Use())
            {
                var buffer = container.Value;
                while (true)
                {
                    if (escaped == null)
                    {
                        escaped = CheckIfEscaped(reader, buffer);
                    }
                    if (IsClosed(reader, buffer, escaped.Value))
                    {
                        break;
                    }
                    var node = reader.Read();
                    if (node == -1)
                    {
                        throw new HandlebarsParserException("Reached end of template in the middle of a comment", reader.GetContext());
                    }
                    else
                    {
                        buffer.Append((char)node);
                    }
                }

                return(buffer.ToString());
            }
        }
Example #3
0
        private static string AccumulateWord(ExtendedStringReader reader)
        {
            using (var container = StringBuilderPool.Shared.Use())
            {
                var buffer = container.Value;

                if (reader.Peek() != '|')
                {
                    return(null);
                }

                reader.Read();

                while (reader.Peek() != '|')
                {
                    buffer.Append((char)reader.Read());
                }

                reader.Read();

                var accumulateWord = buffer.ToString().Trim();
                if (string.IsNullOrEmpty(accumulateWord))
                {
                    throw new HandlebarsParserException($"BlockParams expression is not valid", reader.GetContext());
                }

                return(accumulateWord);
            }
        }
        private static string AccumulateBlockWord(ExtendedStringReader reader)
        {
            using (var container = StringBuilderPool.Shared.Use())
            {
                var buffer = container.Value;
                buffer.Append((char)reader.Read());
                while (char.IsWhiteSpace((char)reader.Peek()))
                {
                    reader.Read();
                }

                while (true)
                {
                    var peek = (char)reader.Peek();
                    if (peek == '}' || peek == '~' || char.IsWhiteSpace(peek))
                    {
                        break;
                    }
                    var node = reader.Read();
                    if (node == -1)
                    {
                        throw new HandlebarsParserException("Reached end of template before the expression was closed.", reader.GetContext());
                    }
                    else
                    {
                        buffer.Append((char)node);
                    }
                }

                return(buffer.ToString());
            }
        }
        internal static TemplateDelegate CompileView(ViewReaderFactory readerFactoryFactory, string templatePath, CompilationContext compilationContext)
        {
            var configuration = compilationContext.Configuration;
            IEnumerable <object> tokens;

            using (var sr = readerFactoryFactory(configuration, templatePath))
            {
                using (var reader = new ExtendedStringReader(sr))
                {
                    tokens = Tokenizer.Tokenize(reader).ToArray();
                }
            }

            var layoutToken = tokens.OfType <LayoutToken>().SingleOrDefault();

            var expressions  = ExpressionBuilder.ConvertTokensToExpressions(tokens, configuration);
            var compiledView = FunctionBuilder.Compile(expressions, compilationContext);

            if (layoutToken == null)
            {
                return(compiledView);
            }

            var fs         = configuration.FileSystem;
            var layoutPath = fs.Closest(templatePath, layoutToken.Value + ".hbs");

            if (layoutPath == null)
            {
                throw new InvalidOperationException($"Cannot find layout '{layoutToken.Value}' for template '{templatePath}'");
            }

            var compiledLayout = CompileView(readerFactoryFactory, layoutPath, new CompilationContext(compilationContext));

            return((in EncodedTextWriter writer, BindingContext context) =>
            {
                var config = context.Configuration;
                using var bindingContext = BindingContext.Create(config, null);
                foreach (var pair in context.ContextDataObject)
                {
                    switch (pair.Key.WellKnownVariable)
                    {
                    case WellKnownVariable.Parent:
                    case WellKnownVariable.Root:
                        continue;
                    }

                    bindingContext.ContextDataObject[pair.Key] = pair.Value;
                }

                using var innerWriter = ReusableStringWriter.Get(config.FormatProvider);
                using var textWriter = new EncodedTextWriter(innerWriter, config.TextEncoder, FormatterProvider.Current, true);
                compiledView(textWriter, context);
                var inner = innerWriter.ToString();

                var viewModel = new LayoutViewModel(inner, context.Value);
                bindingContext.Value = viewModel;

                compiledLayout(writer, bindingContext);
            });
        internal Action <TextWriter, object> CompileView(string templatePath,
                                                         InternalHandlebarsConfiguration configuration)
        {
            var fs = _configuration.FileSystem;

            if (fs == null)
            {
                throw new InvalidOperationException("Cannot compile view when configuration.FileSystem is not set");
            }
            var template = fs.GetFileContent(templatePath);

            if (template == null)
            {
                throw new InvalidOperationException("Cannot find template at '" + templatePath + "'");
            }
            IEnumerable <object> tokens;

            using (var sr = new StringReader(template))
            {
                using (var reader = new ExtendedStringReader(sr))
                {
                    tokens = Tokenizer.Tokenize(reader).ToList();
                }
            }

            var layoutToken = tokens.OfType <LayoutToken>().SingleOrDefault();

            var expressionBuilder = new ExpressionBuilder(configuration);
            var expressions       = expressionBuilder.ConvertTokensToExpressions(tokens);
            var compiledView      = FunctionBuilder.Compile(expressions, configuration, templatePath);

            if (layoutToken == null)
            {
                return(compiledView);
            }

            var layoutPath = fs.Closest(templatePath, layoutToken.Value + ".hbs");

            if (layoutPath == null)
            {
                throw new InvalidOperationException("Cannot find layout '" + layoutPath + "' for template '" +
                                                    templatePath + "'");
            }

            var compiledLayout = CompileView(layoutPath, configuration);

            return((tw, vm) =>
            {
                string inner;
                using (var innerWriter = new PolledStringWriter(configuration.FormatProvider))
                {
                    compiledView(innerWriter, vm);
                    inner = innerWriter.ToString();
                }

                compiledLayout(tw, new DynamicViewModel(new[] { new { body = inner }, vm }));
            });
        }
Example #7
0
        public override Token Parse(ExtendedStringReader reader)
        {
            var context = reader.GetContext();
            var buffer  = AccumulateWord(reader);

            return(!string.IsNullOrEmpty(buffer)
                ? Token.BlockParams(buffer, context)
                : null);
        }
Example #8
0
        private static string AccumulateWord(ExtendedStringReader reader)
        {
            using var container = StringBuilderPool.Shared.Use();
            var buffer = container.Value;

            var inString  = false;
            var isEscaped = false;

            while (true)
            {
                if (isEscaped)
                {
                    var c = (char)reader.Read();
                    if (c == ']')
                    {
                        isEscaped = false;
                    }

                    buffer.Append(c);
                    continue;
                }

                if (!inString)
                {
                    var peek = (char)reader.Peek();

                    if (peek == '}' || peek == '~' || peek == ')' || peek == '=' || char.IsWhiteSpace(peek))
                    {
                        break;
                    }
                }

                var node = reader.Read();

                if (node == -1)
                {
                    throw new HandlebarsParserException("Reached end of template before the expression was closed.", reader.GetContext());
                }

                if (node == '[' && !inString)
                {
                    isEscaped = true;
                    buffer.Append((char)node);
                    continue;
                }

                if (node == '\'' || node == '"')
                {
                    inString = !inString;
                }

                buffer.Append((char)node);
            }

            return(buffer.Trim().ToString());
        }
        public override Token Parse(ExtendedStringReader reader)
        {
            PartialToken token = null;

            if ((char)reader.Peek() == '>')
            {
                token = Token.Partial(reader.GetContext());
            }
            return(token);
        }
Example #10
0
        //TODO: structure parser

        public static IEnumerable <Token> Tokenize(ExtendedStringReader source)
        {
            try
            {
                return(Parse(source));
            }
            catch (Exception ex)
            {
                throw new HandlebarsParserException("An unhandled exception occurred while trying to compile the template", ex);
            }
        }
Example #11
0
        public override Token Parse(ExtendedStringReader reader)
        {
            var context = reader.GetContext();

            if (IsWord(reader))
            {
                var buffer = AccumulateWord(reader);

                return(Token.Word(buffer, context));
            }
            return(null);
        }
        public override Token Parse(ExtendedStringReader reader)
        {
            if (!IsBlockWord(reader))
            {
                return(null);
            }

            var context = reader.GetContext();
            var buffer  = AccumulateBlockWord(reader);
            var token   = Token.Word(buffer, context);

            return(token);
        }
Example #13
0
        internal static TemplateDelegate CompileView(ViewReaderFactory readerFactoryFactory, string templatePath, CompilationContext compilationContext)
        {
            var configuration = compilationContext.Configuration;
            IEnumerable <object> tokens;

            using (var sr = readerFactoryFactory(configuration, templatePath))
            {
                using (var reader = new ExtendedStringReader(sr))
                {
                    tokens = Tokenizer.Tokenize(reader).ToArray();
                }
            }

            var layoutToken = tokens.OfType <LayoutToken>().SingleOrDefault();

            var expressions  = ExpressionBuilder.ConvertTokensToExpressions(tokens, configuration);
            var compiledView = FunctionBuilder.Compile(expressions, compilationContext);

            if (layoutToken == null)
            {
                return(compiledView);
            }

            var fs         = configuration.FileSystem;
            var layoutPath = fs.Closest(templatePath, layoutToken.Value + ".hbs");

            if (layoutPath == null)
            {
                throw new InvalidOperationException($"Cannot find layout '{layoutToken.Value}' for template '{templatePath}'");
            }

            var compiledLayout = CompileView(readerFactoryFactory, layoutPath, new CompilationContext(compilationContext));

            return((in EncodedTextWriter writer, BindingContext context) =>
            {
                var config = context.Configuration;
                using var innerWriter = ReusableStringWriter.Get(config.FormatProvider);
                using var textWriter = new EncodedTextWriter(innerWriter, config.TextEncoder, config.UnresolvedBindingFormatter, true);
                compiledView(textWriter, context);
                var inner = innerWriter.ToString();

                var vmContext = new [] { new { body = inner }, context.Value };
                var viewModel = new DynamicViewModel(vmContext);
                using var bindingContext = BindingContext.Create(config, viewModel);

                compiledLayout(writer, bindingContext);
            });
Example #14
0
        public override Token Parse(ExtendedStringReader reader)
        {
            if (!IsComment(reader))
            {
                return(null);
            }

            Token token  = null;
            var   buffer = AccumulateComment(reader).Trim();

            if (buffer.StartsWith("<")) //syntax for layout is {{<! layoutname }} - i.e. its inside a comment block
            {
                token = Token.Layout(buffer.Substring(1).Trim());
            }

            token = token ?? Token.Comment(buffer);
            return(token);
        }
Example #15
0
        public override Token Parse(ExtendedStringReader reader)
        {
            var context = reader.GetContext();

            if (IsDelimitedLiteral(reader))
            {
                var delimiter = (char)reader.Read();
                var buffer    = AccumulateLiteral(reader, true, delimiter);
                return(Token.Literal(buffer, delimiter.ToString(), context));
            }

            if (IsNonDelimitedLiteral(reader))
            {
                var buffer = AccumulateLiteral(reader, false, ' ', ')');
                return(Token.Literal(buffer, context: context));
            }

            return(null);
        }
Example #16
0
        public static TemplateDelegate Compile(ExtendedStringReader source, CompilationContext compilationContext)
        {
            var configuration   = compilationContext.Configuration;
            var createdFeatures = configuration.Features;

            for (var index = 0; index < createdFeatures.Count; index++)
            {
                createdFeatures[index].OnCompiling(configuration);
            }

            var tokens      = Tokenizer.Tokenize(source).ToArray();
            var expressions = ExpressionBuilder.ConvertTokensToExpressions(tokens, configuration);
            var action      = FunctionBuilder.Compile(expressions, compilationContext);

            for (var index = 0; index < createdFeatures.Count; index++)
            {
                createdFeatures[index].CompilationCompleted();
            }

            return(action);
        }
        public static TemplateDelegate Compile(ExtendedStringReader source, ICompiledHandlebarsConfiguration configuration)
        {
            var createdFeatures = configuration.Features;

            for (var index = 0; index < createdFeatures.Count; index++)
            {
                createdFeatures[index].OnCompiling(configuration);
            }

            var expressionBuilder = new ExpressionBuilder(configuration);
            var tokens            = Tokenizer.Tokenize(source).ToList();
            var expressions       = expressionBuilder.ConvertTokensToExpressions(tokens);
            var action            = FunctionBuilder.Compile(expressions, configuration);

            for (var index = 0; index < createdFeatures.Count; index++)
            {
                createdFeatures[index].CompilationCompleted();
            }

            return(action);
        }
        public Action <TextWriter, object> Compile(ExtendedStringReader source)
        {
            var configuration   = new InternalHandlebarsConfiguration(_configuration);
            var createdFeatures = configuration.Features;

            for (var index = 0; index < createdFeatures.Count; index++)
            {
                createdFeatures[index].OnCompiling(configuration);
            }

            var expressionBuilder = new ExpressionBuilder(configuration);
            var tokens            = Tokenizer.Tokenize(source).ToList();
            var expressions       = expressionBuilder.ConvertTokensToExpressions(tokens);
            var action            = FunctionBuilder.Compile(expressions, configuration);

            for (var index = 0; index < createdFeatures.Count; index++)
            {
                createdFeatures[index].CompilationCompleted();
            }

            return(action);
        }
Example #19
0
        private static bool CheckIfEscaped(ExtendedStringReader reader, StringBuilder buffer)
        {
            if ((char)reader.Peek() != '-')
            {
                return(false);
            }

            var escaped = false;
            var first   = reader.Read();

            if ((char)reader.Peek() == '-')
            {
                reader.Read();
                escaped = true;
            }
            else
            {
                buffer.Append(first);
            }

            return(escaped);
        }
Example #20
0
        private static IEnumerable <Token> Parse(ExtendedStringReader source)
        {
            bool inExpression   = false;
            bool trimWhitespace = false;

            using var container = StringBuilderPool.Shared.Use();
            var buffer = container.Value;

            var node = source.Read();

            while (true)
            {
                if (node == -1)
                {
                    if (buffer.Length > 0)
                    {
                        if (inExpression)
                        {
                            throw new InvalidOperationException("Reached end of template before expression was closed");
                        }
                        else
                        {
                            yield return(Token.Static(buffer.ToString(), source.GetContext()));
                        }
                    }
                    break;
                }
                if (inExpression)
                {
                    if ((char)node == '(')
                    {
                        yield return(Token.StartSubExpression());
                    }

                    var token = WordParser.Parse(source);
                    token ??= LiteralParser.Parse(source);
                    token ??= CommentParser.Parse(source);
                    token ??= PartialParser.Parse(source);
                    token ??= BlockWordParser.Parse(source);
                    token ??= BlockParamsParser.Parse(source);

                    if (token != null)
                    {
                        yield return(token);

                        if ((char)source.Peek() == '=')
                        {
                            source.Read();
                            yield return(Token.Assignment(source.GetContext()));

                            continue;
                        }
                    }
                    if ((char)node == '}' && (char)source.Read() == '}')
                    {
                        bool escaped = true;
                        bool raw     = false;
                        if ((char)source.Peek() == '}')
                        {
                            source.Read();
                            escaped = false;
                        }
                        if ((char)source.Peek() == '}')
                        {
                            source.Read();
                            raw = true;
                        }
                        node = source.Read();
                        yield return(Token.EndExpression(escaped, trimWhitespace, raw, source.GetContext()));

                        inExpression = false;
                    }
                    else if ((char)node == ')')
                    {
                        node = source.Read();
                        yield return(Token.EndSubExpression(source.GetContext()));
                    }
                    else if (char.IsWhiteSpace((char)node) || char.IsWhiteSpace((char)source.Peek()))
                    {
                        node = source.Read();
                    }
                    else if ((char)node == '~')
                    {
                        node           = source.Read();
                        trimWhitespace = true;
                    }
                    else
                    {
                        if (token == null)
                        {
                            throw new HandlebarsParserException("Reached unparseable token in expression: " + source.ReadLine(), source.GetContext());
                        }
                        node = source.Read();
                    }
                }
                else
                {
                    if ((char)node == '\\' && (char)source.Peek() == '\\')
                    {
                        source.Read();
                        buffer.Append('\\');
                        node = source.Read();
                    }
                    else if ((char)node == '\\' && (char)source.Peek() == '{')
                    {
                        source.Read();
                        if ((char)source.Peek() == '{')
                        {
                            source.Read();
                            buffer.Append('{', 2);
                        }
                        else
                        {
                            buffer.Append("\\{");
                        }
                        node = source.Read();
                    }
                    else if ((char)node == '{' && (char)source.Peek() == '{')
                    {
                        bool escaped = true;
                        bool raw     = false;
                        trimWhitespace = false;
                        node           = source.Read();
                        if ((char)source.Peek() == '{')
                        {
                            node    = source.Read();
                            escaped = false;
                        }
                        if ((char)source.Peek() == '{')
                        {
                            node = source.Read();
                            raw  = true;
                        }
                        if ((char)source.Peek() == '~')
                        {
                            source.Read();
                            node           = source.Peek();
                            trimWhitespace = true;
                        }
                        yield return(Token.Static(buffer.ToString(), source.GetContext()));

                        yield return(Token.StartExpression(escaped, trimWhitespace, raw, source.GetContext()));

                        trimWhitespace = false;
                        buffer.Clear();
                        inExpression = true;
                    }
                    else
                    {
                        buffer.Append((char)node);
                        node = source.Read();
                    }
                }
            }
        }
Example #21
0
        private static bool IsComment(ExtendedStringReader reader)
        {
            var peek = (char)reader.Peek();

            return(peek == '!');
        }
Example #22
0
 public abstract Token Parse(ExtendedStringReader reader);
Example #23
0
        private static bool IsNonDelimitedLiteral(ExtendedStringReader reader)
        {
            var peek = (char)reader.Peek();

            return(char.IsDigit(peek) || peek == '-');
        }
        private static bool IsBlockWord(ExtendedStringReader reader)
        {
            var peek = (char)reader.Peek();

            return(ValidBlockWordStartCharacters.Contains(peek));
        }
Example #25
0
 private static bool IsClosed(ExtendedStringReader reader, StringBuilder buffer, bool isEscaped)
 {
     return(isEscaped && CheckIfEscaped(reader, buffer) && CheckIfStatementClosed(reader) || !isEscaped && CheckIfStatementClosed(reader));
 }
Example #26
0
 private static bool CheckIfStatementClosed(ExtendedStringReader reader)
 {
     return((char)reader.Peek() == '}');
 }
Example #27
0
        private static bool IsDelimitedLiteral(ExtendedStringReader reader)
        {
            var peek = (char)reader.Peek();

            return(peek == '\'' || peek == '"');
        }