public async Task includeUrlWithCache(ScriptScopeContext scope, string url, object options)
        {
            var scopedParams = scope.AssertOptions(nameof(includeUrl), options);
            var expireIn     = scopedParams.TryGetValue("expireInSecs", out object value)
                ? TimeSpan.FromSeconds(value.ConvertTo <int>())
                : (TimeSpan)scope.Context.Args[ScriptConstants.DefaultUrlCacheExpiry];

            var cacheKey = CreateCacheKey("url:" + url, scopedParams);

            if (Context.ExpiringCache.TryGetValue(cacheKey, out Tuple <DateTime, object> cacheEntry))
            {
                if (cacheEntry.Item1 > DateTime.UtcNow && cacheEntry.Item2 is byte[] bytes)
                {
                    await scope.OutputStream.WriteAsync(bytes);

                    return;
                }
            }

            var dataType = scopedParams.TryGetValue("dataType", out value)
                ? ConvertDataTypeToContentType((string)value)
                : null;

            if (scopedParams.TryGetValue("method", out value) && !((string)value).EqualsIgnoreCase("GET"))
            {
                throw new NotSupportedException($"Only GET requests can be used in {nameof(includeUrlWithCache)} filters in page '{scope.Page.VirtualPath}'");
            }
            if (scopedParams.TryGetValue("data", out value))
            {
                throw new NotSupportedException($"'data' is not supported in {nameof(includeUrlWithCache)} filters in page '{scope.Page.VirtualPath}'");
            }

            var ms = MemoryStreamFactory.GetStream();

            using (ms)
            {
                var captureScope = scope.ScopeWithStream(ms);
                await includeUrl(captureScope, url, options);

                ms.Position = 0;
                var expireAt = DateTime.UtcNow.Add(expireIn);

                var bytes = ms.ToArray();
                Context.ExpiringCache[cacheKey] = cacheEntry = Tuple.Create(expireAt, (object)bytes);
                await scope.OutputStream.WriteAsync(bytes);
            }
        }
        public override async Task <bool> WritePageFragmentAsync(ScriptScopeContext scope, PageFragment fragment, CancellationToken token)
        {
            var page = scope.PageResult;

            if (fragment is PageJsBlockStatementFragment blockFragment)
            {
                var blockStatements = blockFragment.Block.Statements;
                if (blockFragment.Quiet && scope.OutputStream != Stream.Null)
                {
                    scope = scope.ScopeWithStream(Stream.Null);
                }

                await page.WriteStatementsAsync(scope, blockStatements, token);

                return(true);
            }
            return(false);
        }