public async Task <string> RenderAsync(string stringTemplate, object model, string language = null) { var context = new LiquidTemplateContext() { EnableRelaxedMemberAccess = true, NewLine = Environment.NewLine, TemplateLoaderLexerOptions = new LexerOptions { Mode = ScriptMode.Liquid }, LoopLimit = _options.LoopLimit }; var scriptObject = AbstractTypeFactory <NotificationScriptObject> .TryCreateInstance(); scriptObject.Language = language; scriptObject.Import(model); foreach (var customFilterType in _options.CustomFilterTypes) { scriptObject.Import(customFilterType); } context.PushGlobal(scriptObject); var template = Template.ParseLiquid(stringTemplate); var result = await template.RenderAsync(context); return(result); }
internal static async Task RenderAsync(RazorPage <dynamic> page) { var services = page.Context.RequestServices; var liquidViewParser = services.GetRequiredService <LiquidViewParser>(); var path = Path.ChangeExtension(page.ViewContext.ExecutingFilePath, ViewExtension); var templateOptions = services.GetRequiredService <IOptions <TemplateOptions> >().Value; var isDevelopment = services.GetRequiredService <IHostEnvironment>().IsDevelopment(); var template = await ParseAsync(liquidViewParser, path, templateOptions.FileProvider, Cache, isDevelopment); var context = new LiquidTemplateContext(services, templateOptions); var htmlEncoder = services.GetRequiredService <HtmlEncoder>(); try { // Defer the buffer disposing so that a template can be rendered twice. var content = new ViewBufferTextWriterContent(releaseOnWrite: false); ShellScope.Current.RegisterBeforeDispose(scope => content.Dispose()); await context.EnterScopeAsync(page.ViewContext, (object)page.Model); await template.FluidTemplate.RenderAsync(content, htmlEncoder, context); // Use ViewBufferTextWriter.Write(object) from ASP.NET directly since it will use a special code path // for IHtmlContent. This prevent the TextWriter methods from copying the content from our buffer // if we did content.WriteTo(page.Output) page.Output.Write(content); } finally { context.ReleaseScope(); } }
public async Task ShapeRenderWithAmbientValues() { var templateContext = new LiquidTemplateContext(_serviceProvider, new TemplateOptions()); var displayHelper = _serviceProvider.GetRequiredService <IDisplayHelper>(); templateContext.AmbientValues["DisplayHelper"] = displayHelper; await ShapeRenderWithAmbientValues(_input, _filterArguments, templateContext); }
public BenchRenderers() { var parsers = new BenchParsers(); _scribanTemplate = parsers.TestScriban(); _dotLiquidTemplate = parsers.TestDotLiquid(); _stubbleTemplate = parsers.TestStubble(); _stubbleSettings = new Stubble.Core.Settings.RendererSettingsBuilder().BuildSettings(); _nustacheTemplate = parsers.TestNustache(); _handlebarsTemplate = parsers.TestHandlebars(); _cottleTemplate = parsers.TestCottle(); _fluidTemplate = parsers.TestFluid(); _razorTemplate = parsers.TestRazor(); const int ProductCount = 500; _products = new List <Product>(ProductCount); _scribanProducts = new List <ScriptObject>(); _dotLiquidProducts = new List <DotLiquid.Hash>(ProductCount); var cottleValues = new List <Cottle.Value>(); for (int i = 0; i < ProductCount; i++) { var product = new Product("Name" + i, i, Lorem); _products.Add(product); var hash = new Hash() { ["name"] = product.Name, ["price"] = product.Price, ["description"] = product.Description }; _dotLiquidProducts.Add(hash); var obj = new ScriptObject { ["name"] = product.Name, ["price"] = product.Price, ["description"] = product.Description }; _scribanProducts.Add(obj); cottleValues.Add(new Cottle.Values.ReflectionValue(product)); } _liquidTemplateContext = new LiquidTemplateContext(); // For Cottle, we match the behavior of Scriban that is accessing the Truncate function via an reflection invoke // In Scriban, we could also have a direct Truncate function, but it is much less practical in terms of declaration _cottleStringStore = new Dictionary <Cottle.Value, Cottle.Value>(); _cottleStringStore["truncate"] = new Cottle.Functions.NativeFunction((values, store, Output) => { if (values.Count != 2) { throw new InvalidOperationException("Unexpected number of arguments for truncate function"); } return(StringFunctions.Truncate(values[0].AsString, Convert.ToInt32(values[1].AsNumber))); }, 2); }
internal static async Task EnterScopeAsync(this LiquidTemplateContext context, object?model, Action <Scope> scopeAction) { if (context is LiquidTemplateContextInternal contextInternal) { if (!contextInternal.IsInitialized) { context.AmbientValues.EnsureCapacity(9); context.AmbientValues.Add("Services", context.Services); var shapeRenderer = context.Services.GetRequiredService <IShapeRenderer>(); context.AmbientValues.Add("ShapeRenderer", shapeRenderer); var shapeFactory = context.Services.GetRequiredService <IShapeFactory>(); context.AmbientValues.Add("ShapeFactory", shapeFactory); var options = context.Services.GetRequiredService <IOptions <LiquidOptions> >().Value; context.AddAsyncFilters(options); foreach (var handler in context.Services.GetServices <ILiquidTemplateEventHandler>()) { await handler.RenderingAsync(context); } context.CultureInfo = CultureInfo.CurrentUICulture; contextInternal.IsInitialized = true; } context.EnterChildScope(); if (model != null) { context.MemberAccessStrategy.Register(model.GetType()); } if (context.GetValue("Model")?.ToObjectValue() == model && model is IShape shape) { if (contextInternal.ShapeRecursions++ > LiquidTemplateContextInternal.MaxShapeRecursions) { throw new InvalidOperationException( $"The '{shape.Metadata.Type}' shape has been called recursively more than {LiquidTemplateContextInternal.MaxShapeRecursions} times."); } } else { contextInternal.ShapeRecursions = 0; } } context.SetValue("Model", model); scopeAction?.Invoke(context.LocalScope); }
public async Task <MetadataRenderResult[]> Render(MetadataRenderRequest[] requests) { var renderedResults = new List <MetadataRenderResult>(); var templates = await new LayoutLoader(_fileSystem, _metadataProvider).Load(_layoutDirectory); var templateLoader = new MyIncludeFromDisk(_fileSystem, _templateDirectory); foreach (var request in requests) { try { var template = templates.FirstOrDefault(t => t.Name.Equals(request.Template)); var content = template?.Content ?? "{{ content }}"; content = content.Replace("{{ content }}", request.Metadata.Content); var liquidTemplate = Template.ParseLiquid(content); var context = new LiquidTemplateContext() { TemplateLoader = templateLoader }; var scriptObject = new ScriptObject(); scriptObject.Import(request.Metadata); context.PushGlobal(scriptObject); scriptObject.Import(typeof(GlobalFunctions)); foreach (var plugin in _plugins) { scriptObject.Import(plugin.Name, new Func <string>(() => plugin.Render(request.Metadata))); // scriptObject.Import(plugin.Name, new Func<string>(() => // return plugin.Render(request.Model) // ); // scriptObject.Import(plugin.Name, new Func<TemplateContext, string>(templateContext => { // return plugin.Render(templateContext.CurrentGlobal); // })); } // scriptObject.Import("seo", new Func<TemplateContext, string>(templateContext => { // return "<strong>{{ build.git_hash }}</strong>"; // })); var renderedContent = await liquidTemplate.RenderAsync(context); renderedResults.Add(new MetadataRenderResult { Content = renderedContent }); } catch (Exception) { throw; } } return(renderedResults.ToArray()); }
internal static void AddAsyncFilters(this LiquidTemplateContext context, LiquidOptions options) { context.Filters.EnsureCapacity(options.FilterRegistrations.Count); foreach (var registration in options.FilterRegistrations) { context.Filters.AddAsyncFilter(registration.Key, (input, arguments, ctx) => { var filter = (ILiquidFilter)context.Services.GetRequiredService(registration.Value); return(filter.ProcessAsync(input, arguments, ctx)); }); } }
public string Render(object model = null) { var context = new LiquidTemplateContext { TemplateLoader = FileSystem }; var obj = new ScriptObject(); if (model != null) { obj.Import(model); } context.PushGlobal(obj); return(_template.Render(context)); }
/// <summary> /// Constructs a new instance of the <see cref="LiquidTemplateRenderer"/> class with a logger. /// </summary> public LiquidTemplateRenderer(ILogger logger) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); // Load functions to support Liquid rendering var funcScriptObject = new ScriptObject(); funcScriptObject.Import(typeof(CustomLiquidFunctions)); // Create template context (disable loop limit) _context = new LiquidTemplateContext() { LoopLimit = int.MaxValue }; _context.PushGlobal(funcScriptObject); }
public string Render(object data) { var liquidTemplate = Template.ParseLiquid(_raw); var context = new LiquidTemplateContext(); var ld = LdJson(data); var scriptObject = new ScriptObject { ["seo_tag"] = data, ["json_ld"] = ld }; scriptObject.Import(typeof(GlobalFunctions)); context.PushGlobal(scriptObject); var pluginResult = liquidTemplate.Render(context); return(pluginResult); }
public async Task <string> RenderAsync(string template, object contextObj) { var scribanContext = new LiquidTemplateContext() { EnableRelaxedMemberAccess = true, NewLine = Environment.NewLine, TemplateLoaderLexerOptions = new LexerOptions { Mode = ScriptMode.Liquid } }; var scriptObject = new ScriptObject(); scriptObject.Import(contextObj); scribanContext.PushGlobal(scriptObject); var parsedTemplate = Template.ParseLiquid(template); return(await parsedTemplate.RenderAsync(scribanContext)); }
public Task RenderAsync(string source, TextWriter writer, TextEncoder encoder, object model = null, IEnumerable <KeyValuePair <string, FluidValue> > properties = null) { if (String.IsNullOrWhiteSpace(source)) { return(Task.CompletedTask); } var result = GetCachedTemplate(source); var context = new LiquidTemplateContext(_serviceProvider, _templateOptions); if (properties != null) { foreach (var property in properties) { context.SetValue(property.Key, property.Value); } } return(result.RenderAsync(writer, encoder, context, model)); }
public async Task <IHtmlContent> RenderHtmlContentAsync(string source, TextEncoder encoder, object model = null, IEnumerable <KeyValuePair <string, FluidValue> > properties = null) { if (String.IsNullOrWhiteSpace(source)) { return(HtmlString.Empty); } var result = GetCachedTemplate(source); var context = new LiquidTemplateContext(_serviceProvider, _templateOptions); if (properties != null) { foreach (var property in properties) { context.SetValue(property.Key, property.Value); } } var htmlContentWriter = new ViewBufferTextWriterContent(); await result.RenderAsync(htmlContentWriter, encoder, context, model); return(htmlContentWriter); }
public async ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext ctx) { string listContentItemId; if (input.Type == FluidValues.Object && input.ToObjectValue() is ContentItem contentItem) { listContentItemId = contentItem.ContentItemId; } else { listContentItemId = input.ToStringValue(); } var listCount = await ListQueryHelpers.QueryListItemsCountAsync(_session, listContentItemId); return(NumberValue.Create(listCount)); }
public ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext context) { var relativePath = input.ToStringValue(); if (string.IsNullOrWhiteSpace(relativePath)) { return(new ValueTask <FluidValue>(input)); } var urlHelper = _urlHelperFactory.GetUrlHelper(context.ViewContext); var result = new StringValue(urlHelper.ToAbsoluteUrl(relativePath)); return(new ValueTask <FluidValue>(result)); }
public ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext context) { var item = input.ToObjectValue() as ContentItem; if (item == null) { throw new ArgumentException("ContentItem missing while calling 'user_can_view' filter"); } if (_contentPermissionsService.CanAccess(item)) { return(new ValueTask <FluidValue>(BooleanValue.True)); } return(new ValueTask <FluidValue>(BooleanValue.False)); }
public ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext context) { var urlHelper = _urlHelperFactory.GetUrlHelper(context.ViewContext); return(new ValueTask <FluidValue>(new StringValue((urlHelper).Content(input.ToStringValue())))); }
public ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext context) { var claimType = arguments["type"].Or(arguments.At(0)).ToStringValue(); if (input.ToObjectValue() is ClaimsPrincipal principal && principal.FindFirst(claimType) != null) { return(new ValueTask <FluidValue>(new StringValue(principal.FindFirst(claimType).Value))); } return(new ValueTask <FluidValue>(new StringValue(""))); }
public ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments args, LiquidTemplateContext context) { var toEncode = input.ToStringValue(); return(string.IsNullOrEmpty(toEncode) ? StringValue.Empty : new StringValue(System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(toEncode)))); }
public async ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext context) { var shortcodeContext = new Context(); // Retrieve the 'ContentItem' from the ambient liquid scope. var model = context.GetValue("Model").ToObjectValue(); if (model is Shape shape && shape.Properties.TryGetValue("ContentItem", out var contentItem)) { shortcodeContext["ContentItem"] = contentItem; }
public async ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext context) { var locations = new List <string>(); foreach (var value in input.Enumerate(context)) { locations.Add((await value.GetValueAsync("LeverPostingPart.Location", context)).ToStringValue()); } return(new StringValue(StringUtils.GetOptions(locations.Distinct().OrderBy(x => x).ToList(), _httpContextAccessor.HttpContext.Request.Query["location"].FirstOrDefault()))); }
public ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext context) { var contentItem = input.ToObjectValue(); if (!(contentItem is ContentItem) || !(contentItem as ContentItem).Has("AnimationPart")) { return(new ValueTask <FluidValue>(new StringValue(string.Empty))); } var animationPart = (contentItem as ContentItem).GetAnimationPart(); if (animationPart.Type == "none") { return(new ValueTask <FluidValue>(new StringValue(string.Empty))); } var styles = new List <string>(); if (!string.IsNullOrWhiteSpace(animationPart.Timing)) { styles.Add($"--animationTiming: {animationPart.Timing};"); } if (animationPart.Delay.HasValue) { styles.Add($"--animationDelay: {animationPart.Delay}ms;"); } if (animationPart.Duration.HasValue) { styles.Add($"--animationDuration: {animationPart.Duration}ms;"); } return(new ValueTask <FluidValue>(new StringValue(string.Join(" ", styles)))); }
public ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext context) { var urlHelper = _urlHelperFactory.GetUrlHelper(context.ViewContext); var request = _httpContextAccessor.HttpContext?.Request; if (request == null) { throw new ArgumentException("HttpRequest missing while invoking 'switch_culture_url'"); } var targetCulture = input.ToStringValue(); var url = urlHelper.RouteUrl("RedirectToLocalizedContent", new { area = "OrchardCore.ContentLocalization", targetCulture = targetCulture, contentItemUrl = request.Path.Value, queryStringValue = request.QueryString.Value }); return(new ValueTask <FluidValue>(FluidValue.Create(url, context.Options))); }
public async ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext ctx) { if (!ctx.AmbientValues.TryGetValue("Services", out var services)) { throw new ArgumentException("Services missing while invoking 'github_issuecomments'"); } var gitHubApiService = ((IServiceProvider)services).GetRequiredService <IGitHubApiService>(); var owner = arguments["owner"].Or(arguments.At(0)).ToStringValue(); var repo = arguments["repository"].Or(arguments.At(1)).ToStringValue(); var tokenName = arguments["tokenName"].Or(arguments.At(2)).ToStringValue(); var prNumber = input.ToStringValue(); if (string.IsNullOrEmpty(owner) || string.IsNullOrEmpty(repo) || string.IsNullOrEmpty(tokenName)) { throw new ArgumentException("Missing owner, repository or tokenName while invoking 'github_issuecomments'"); } if (!int.TryParse(prNumber, out var parsedNumber)) { throw new ArgumentException("Please provide a valid pull request number while invoking 'github_issuecomments'"); } try { var client = await gitHubApiService.GetGitHubClient(tokenName); return(FluidValue.Create(await client.Issue.Comment.GetAllForIssue(owner, repo, parsedNumber), ctx.Options)); } catch (Octokit.ApiException ex) { return(FluidValue.Create(ex.Message, ctx.Options)); } }
public async ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext ctx) { string taxonomyContentItemId = null; string[] termContentItemIds = null; if (input.Type == FluidValues.Object && input.ToObjectValue() is TaxonomyField field) { taxonomyContentItemId = field.TaxonomyContentItemId; termContentItemIds = field.TermContentItemIds; } else if (input.Type == FluidValues.Object && input.ToObjectValue() is JObject jobj && jobj.ContainsKey(nameof(TaxonomyField.TermContentItemIds)) && jobj.ContainsKey(nameof(TaxonomyField.TaxonomyContentItemId))) { taxonomyContentItemId = jobj["TaxonomyContentItemId"].Value <string>(); termContentItemIds = ((JArray)jobj["TermContentItemIds"]).Values <string>().ToArray(); }
public ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext context) { int paramFirstIndex = 0; var culture = context.CultureInfo.Name; var value = ""; var inputObj = input.ToObjectValue(); ContentItem contentItem = null; if (inputObj is ContentItem) { contentItem = inputObj as ContentItem; } if (inputObj is JObject) { contentItem = (inputObj as JObject)?.ToObject <ContentItem>(); } // if the ContentItem is passed to the filter, use the first argument as the name of the value to find if (contentItem != null) { var stringKey = arguments.At(0).ToStringValue(); paramFirstIndex = 1; var part = contentItem.As <LocalizedTextPart>(); if (part == null) { return(new ValueTask <FluidValue>(input)); //throw new ArgumentException(" The 'localize' filter requires the LocalizedTextPart"); } value = part.Data.FirstOrDefault(lt => lt.Name == stringKey)?.LocalizedItems.FirstOrDefault(li => li.Culture == culture)?.Value; } else { // try to get the ContentItem from the accessor when the name of the value is passed as the input to the filter value = _accessor.GetTranslation(culture, input.ToStringValue()); } if (!string.IsNullOrEmpty(value) && arguments.Count > 0) { var parameters = new object[arguments.Count]; for (var i = paramFirstIndex; i < arguments.Count; i++) { parameters[i] = arguments.At(i).ToStringValue(); } value = string.Format(value, parameters); } if (value == null) { value = string.Empty; } return(new ValueTask <FluidValue>(new StringValue(value, false))); }
public ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext ctx) { var html = input.ToStringValue(); html = _htmlSanitizerService.Sanitize(html); return(new ValueTask <FluidValue>(new StringValue(html))); }
public ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext ctx) { var urlHelper = _urlHelperFactory.GetUrlHelper(ctx.ViewContext); var workflowContextValue = ctx.GetValue("Workflow"); if (workflowContextValue.IsNil()) { throw new ArgumentException("WorkflowExecutionContext missing while invoking 'signal_url'"); } var workflowContext = (WorkflowExecutionContext)workflowContextValue.ToObjectValue(); var signalName = input.ToStringValue(); var payload = String.IsNullOrWhiteSpace(workflowContext.CorrelationId) ? SignalPayload.ForWorkflow(signalName, workflowContext.WorkflowId) : SignalPayload.ForCorrelation(signalName, workflowContext.CorrelationId); var token = _securityTokenService.CreateToken(payload, TimeSpan.FromDays(7)); var urlValue = new StringValue(urlHelper.Action("Trigger", "HttpWorkflow", new { area = "OrchardCore.Workflows", token })); return(new ValueTask <FluidValue>(urlValue)); }
public async ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext ctx) { string taxonomyContentItemId = input.ToStringValue(); var taxonomy = await _contentManager.GetAsync(taxonomyContentItemId); if (taxonomy == null) { return(null); } var terms = GetTermsRecursive(taxonomy.Content.TaxonomyPart.Terms as JArray); return(FluidValue.Create(terms, ctx.Options)); }
public ValueTask <FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext ctx) { if (input.ToObjectValue() is LiquidUserAccessor) { var user = _httpContextAccessor.HttpContext?.User; if (user != null) { var claimName = arguments["name"].Or(arguments.At(0)).ToStringValue(); var roleClaimType = _identityOptions.ClaimsIdentity.RoleClaimType; if (user.Claims.Any(claim => claim.Type == roleClaimType && claim.Value.Equals(claimName, StringComparison.OrdinalIgnoreCase))) { return(new ValueTask <FluidValue>(BooleanValue.True)); } } } return(new ValueTask <FluidValue>(BooleanValue.False)); }