Пример #1
0
        public void ShouldParseFunctionCall()
        {
            var options = new FluidParserOptions {
                AllowFunctions = true
            };

#if COMPILED
            var _parser = new FluidParser(options).Compile();
#else
            var _parser = new FluidParser(options);
#endif

            _parser.TryParse("{{ a() }}", out var template, out var errors);
            var statements = ((FluidTemplate)template).Statements;

            Assert.Single(statements);

            var outputStatement = statements[0] as OutputStatement;
            Assert.NotNull(outputStatement);

            var memberExpression = outputStatement.Expression as MemberExpression;
            Assert.Equal(2, memberExpression.Segments.Count);
            Assert.IsType <IdentifierSegment>(memberExpression.Segments[0]);
            Assert.IsType <FunctionCallSegment>(memberExpression.Segments[1]);
        }
Пример #2
0
        public async Task ShouldNotBreakJObjectCustomizations()
        {
            var options = new TemplateOptions();

            // When a property of a JObject value is accessed, try to look into its properties
            options.MemberAccessStrategy.Register <JObject, object>((source, name) => source[name]);

            // Convert JToken to FluidValue
            options.ValueConverters.Add(x => x is JObject o ? new ObjectValue(o) : null);
            options.ValueConverters.Add(x => x is JValue v ? v.Value : null);

            var model = JObject.Parse("{\"Name\": \"Bill\",\"Company\":{\"Name\":\"Microsoft\"}}");

            _parser.TryParse("His name is {{ Name }}, Company : {{ Company.Name }}", out var template);
            var context = new TemplateContext(model, options);

            Assert.Equal("His name is Bill, Company : Microsoft", await template.RenderAsync(context));
        }
Пример #3
0
        private Dictionary <string, List <PatchSet> > RenderFilePatchTemplates(PatchRequest request, WingmanMod mod, Dictionary <string, string> modelVars)
        {
            var dict = mod.FilePatches.ToDictionary(k => k.Key, kvp =>
            {
                var finalPatches = kvp.Value.Where(psList =>
                {
                    // REMEMBER: this is to keep the step, so have to return false to skip it
                    if (mod.ModInfo.StepsEnabled.ContainsKey(psList.Name) &&
                        _parser.TryParse(mod.ModInfo.StepsEnabled[psList.Name], out var skipTemplate))
                    {
                        var rendered = skipTemplate.Render(GetInputContext(request, modelVars));
                        var result   = !bool.TryParse(rendered, out var skip) || skip;
                        // var result = bool.TryParse(rendered, out var skip) || skip;
                        // do NOT invert result: result *is* inverted
                        return(result);
                    }

                    return(true);
                }).Select(psList =>
                {
                    psList.Patches = psList.Patches.Select(p =>
                    {
                        if (_parser.TryParse(p.Substitution, out var subTemplate))
                        {
                            p.Substitution = subTemplate.Render(GetInputContext(request, modelVars));
                        }

                        if (_parser.TryParse(p.Template, out var template))
                        {
                            p.Template = template.Render(GetInputContext(request, modelVars));
                        }

                        if (p.Window != null)
                        {
                            p.Window.After  = SafeRender(request, p.Window.After, modelVars);
                            p.Window.Before = SafeRender(request, p.Window.Before, modelVars);
                        }

                        return(p);
                    }).ToList();
                    return(psList);
                }).ToList();
                return(finalPatches);
            });
Пример #4
0
        private static async Task <string> CreateIssueBody(IEnumerable <Regression> regressions, string template)
        {
            var report = new Report
            {
                Regressions = regressions.OrderBy(x => x.CurrentResult.Scenario).ThenBy(x => x.CurrentResult.DateTimeUtc).ToList()
            };

            // The base64 encoded MessagePack-serialized model
            var regressionBlock = CreateRegressionsBlock(regressions);

            if (!_fluidParser.TryParse(template, out var fluidTemplate, out var errors))
            {
                Console.WriteLine("Error parsing the template:");
                foreach (var error in errors)
                {
                    Console.WriteLine(error);
                }

                return("");
            }

            var context = new TemplateContext(report, _templateOptions);

            try
            {
                var body = await fluidTemplate.RenderAsync(context);

                body = AddOwners(body, regressions);

                body += regressionBlock;

                return(body);
            }
            catch (Exception e)
            {
                Console.WriteLine($"An error occurred while rendering an issue: {e}");
                Console.WriteLine("[DEBUG] Model used:");
                Console.WriteLine(regressionBlock);

                throw;
            }
        }
Пример #5
0
        private async Task CheckAsync(string source, string expected, Action <TemplateContext> init = null)
        {
            _parser.TryParse("{% if " + source + " %}true{% else %}false{% endif %}", out var template, out var messages);

            var context = new TemplateContext();

            init?.Invoke(context);

            var result = await template.RenderAsync(context);

            Assert.Equal(expected, result);
        }
Пример #6
0
        public void ShouldNotParseFunctionCall()
        {
            var options = new FluidParserOptions {
                AllowFunctions = false
            };

#if COMPILED
            var parser = new FluidParser(options).Compile();
#else
            var parser = new FluidParser(options);
#endif

            Assert.False(parser.TryParse("{{ a() }}", out var template, out var errors));
            Assert.Contains(ErrorMessages.FunctionsNotAllowed, errors);
        }
Пример #7
0
        public override async ValueTask <Completion> WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context)
        {
            context.IncrementSteps();

            var relativePath = (await Path.EvaluateAsync(context)).ToStringValue();

            if (!relativePath.EndsWith(ViewExtension, StringComparison.OrdinalIgnoreCase))
            {
                relativePath += ViewExtension;
            }

            var fileProvider = context.Options.FileProvider;

            var fileInfo = fileProvider.GetFileInfo(relativePath);

            if (fileInfo == null || !fileInfo.Exists)
            {
                throw new FileNotFoundException(relativePath);
            }

            using (var stream = fileInfo.CreateReadStream())
                using (var streamReader = new StreamReader(stream))
                {
                    context.EnterChildScope();

                    string partialTemplate = await streamReader.ReadToEndAsync();

                    if (_parser.TryParse(partialTemplate, out var result, out var errors))
                    {
                        if (With != null)
                        {
                            var identifier = System.IO.Path.GetFileNameWithoutExtension(relativePath);
                            var with       = await With.EvaluateAsync(context);

                            context.SetValue(identifier, with);
                        }

                        if (AssignStatements != null)
                        {
                            foreach (var assignStatement in AssignStatements)
                            {
                                await assignStatement.WriteToAsync(writer, encoder, context);
                            }
                        }

                        await result.RenderAsync(writer, encoder, context);
                    }
Пример #8
0
        public async Task FunctionCallsShouldDefaultToNil()
        {
            var source = @"
                {{- a() -}}
            ";

            _parser.TryParse(source, out var template, out var error);
            var context = new TemplateContext();
            var result  = await template.RenderAsync(context);

            Assert.Equal("", result);
        }
Пример #9
0
        public static CachedTemplate Parse(string input, bool bypass = false)
        {
            Guard.NotNull(input);

            CachedTemplate result;

            if (!bypass)
            {
                LockObject.EnterWriteLock();
                try
                {
                    if (Cache.TryGetValue(input, out result))
                    {
                        return(result);
                    }
                }
                finally
                {
                    LockObject.ExitWriteLock();
                }
            }

            Parser.TryParse(input, out var template, out var errorMessage);

            var error = TemplateError.Parse(errorMessage);

            result = new CachedTemplate(template, error);

            if (!bypass)
            {
                LockObject.EnterWriteLock();
                try
                {
                    Cache.Set(input, result);
                }
                finally
                {
                    LockObject.ExitWriteLock();
                }
            }

            return(result);
        }
Пример #10
0
        public void ScopeShouldFallbackToTemplateOptions()
        {
            var parser = new FluidParser();

            parser.TryParse("{{ p.NaMe }}", out var template, out var error);

            var options = new TemplateOptions();

            options.Scope.SetValue("o1", new StringValue("o1"));
            options.Scope.SetValue("o2", new StringValue("o2"));

            var context = new TemplateContext(options);

            context.SetValue("o2", "new o2");
            context.SetValue("o3", "o3");

            Assert.Equal("o1", context.GetValue("o1").ToStringValue());
            Assert.Equal("new o2", context.GetValue("o2").ToStringValue());
            Assert.Equal("o3", context.GetValue("o3").ToStringValue());
        }
Пример #11
0
        public async Task ShouldRenderReadmeSample()
        {
            var options = new TemplateOptions();

            // When a property of a JObject value is accessed, try to look into its properties
            options.MemberAccessStrategy.Register <JObject, object>((source, name) => source[name]);

            // Convert JToken to FluidValue
            options.ValueConverters.Add(x => x is JObject o ? new ObjectValue(o) : null);
            options.ValueConverters.Add(x => x is JValue v ? v.Value : null);

            var model = JObject.Parse("{\"Name\": \"Bill\"}");

            var parser = new FluidParser();

            parser.TryParse("His name is {{ Name }}", out var template);
            var context = new TemplateContext(model, options);

            Assert.Equal("His name is Bill", await template.RenderAsync(context));
        }
Пример #12
0
 public FluidBenchmarks()
 {
     _options.MemberAccessStrategy.Register <Product>();
     _options.MemberAccessStrategy.MemberNameStrategy = MemberNameStrategies.CamelCase;
     _parser.TryParse(ProductTemplate, out _fluidTemplate, out var _);
 }
Пример #13
0
 public void WrongTemplateShouldRenderErrorMessage(string source, string expected)
 {
     Assert.False(_parser.TryParse(source, out var _, out var error));
     Assert.StartsWith(expected, error); // e.g., message then 'at (1:15)'
 }
Пример #14
0
 private static IReadOnlyList <Statement> Parse(string source)
 {
     _parser.TryParse(source, out var template, out var errors);
     return(template.Statements);
 }
Пример #15
0
        private async Task CheckAsync(string source, string expected, Action <TemplateContext> init = null)
        {
            _parser.TryParse(source, out var template, out var error);

            var context = new TemplateContext();

            context.Options.MemberAccessStrategy.Register(new { name = "product 1", price = 1 }.GetType());
            init?.Invoke(context);

            var result = await template.RenderAsync(context);

            Assert.Equal(expected, result);
        }
Пример #16
0
        public void IncludeTag_With()
        {
            var fileProvider = new MockFileProvider();

            fileProvider.Add("product.liquid", "Product: {{ product.title }} ");

            var options = new TemplateOptions()
            {
                FileProvider = fileProvider, MemberAccessStrategy = UnsafeMemberAccessStrategy.Instance
            };
            var context = new TemplateContext(options);

            context.SetValue("products", new[] { new { title = "Draft 151cm" }, new { title = "Element 155cm" } });
            _parser.TryParse("{% include 'product' with products[0] %}", out var template);
            var result = template.Render(context);

            Assert.Equal("Product: Draft 151cm ", result);
        }
Пример #17
0
        public async Task ShouldPreserveSpace()
        {
            var source = @"# With whitespace control
{% assign name = 'John G. Chalmers-Smith' %}
{% if name and name.size > 10 %}
    Wow, {{ name }}, you have a long name!
{% else %}
    Hello there!
{% endif %}";

            var expected = @"# With whitespace control


    Wow, John G. Chalmers-Smith, you have a long name!
";

            _parser.TryParse(source, out var template);
            var result = await template.RenderAsync();

            Assert.Equal(expected, result);
        }