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()); } }
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()); } }
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 })); }); }
public override Token Parse(ExtendedStringReader reader) { var context = reader.GetContext(); var buffer = AccumulateWord(reader); return(!string.IsNullOrEmpty(buffer) ? Token.BlockParams(buffer, context) : null); }
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); }
//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); } }
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); }
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); });
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); }
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); }
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); }
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); }
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(); } } } }
private static bool IsComment(ExtendedStringReader reader) { var peek = (char)reader.Peek(); return(peek == '!'); }
public abstract Token Parse(ExtendedStringReader reader);
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)); }
private static bool IsClosed(ExtendedStringReader reader, StringBuilder buffer, bool isEscaped) { return(isEscaped && CheckIfEscaped(reader, buffer) && CheckIfStatementClosed(reader) || !isEscaped && CheckIfStatementClosed(reader)); }
private static bool CheckIfStatementClosed(ExtendedStringReader reader) { return((char)reader.Peek() == '}'); }
private static bool IsDelimitedLiteral(ExtendedStringReader reader) { var peek = (char)reader.Peek(); return(peek == '\'' || peek == '"'); }