<commit_before>using System;
using System.Globalization;
using System.IO;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Fluid;
using Fluid.Accessors;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using OrchardCore.DisplayManagement.Shapes;
using OrchardCore.Liquid;
using OrchardCore.Modules;
using TimeZoneConverter;

namespace OrchardCore.DisplayManagement.Liquid
{
    public class LiquidViewTemplate
    {
        public static readonly string ViewsFolder = "Views";
        public static readonly string ViewExtension = ".liquid";
        public static readonly MemoryCache Cache = new MemoryCache(new MemoryCacheOptions());
        public IFluidTemplate FluidTemplate { get; }

        public LiquidViewTemplate(IFluidTemplate fluidTemplate)
        {
            FluidTemplate = fluidTemplate;
        }

        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
            {
                var content = new ViewBufferTextWriterContent();
                await context.EnterScopeAsync(page.ViewContext, (object)page.Model);
                await template.FluidTemplate.RenderAsync(content, htmlEncoder, context);
                content.WriteTo(page.Output, htmlEncoder);
            }
            finally<commit_msg>Don't allocate for page output writing in LiquidViewTemplate (#9192)<commit_after>using System;
using System.Globalization;
using System.IO;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Fluid;
using Fluid.Accessors;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using OrchardCore.DisplayManagement.Shapes;
using OrchardCore.Liquid;
using OrchardCore.Modules;
using TimeZoneConverter;

namespace OrchardCore.DisplayManagement.Liquid
{
    public class LiquidViewTemplate
    {
        public static readonly string ViewsFolder = "Views";
        public static readonly string ViewExtension = ".liquid";
        public static readonly MemoryCache Cache = new MemoryCache(new MemoryCacheOptions());
        public IFluidTemplate FluidTemplate { get; }

        public LiquidViewTemplate(IFluidTemplate fluidTemplate)
        {
            FluidTemplate = fluidTemplate;
        }

        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
            {
                var content = new ViewBufferTextWriterContent();
                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
{'fraction_non_alphanumeric': 0.0760414771693651, 'fraction_numerical': 0.0007276696379843551, 'mean_word_length': 3.543801652892562, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6745883', 'n_tokens_mistral': 1349, 'n_tokens_neox': 1351, 'n_words': 315}