/// <summary> /// Return hash of requested asset (used for file versioning) /// </summary> /// <param name="filePath"></param> /// <returns></returns> public string GetAssetHash(string filePath) { var cacheKey = CacheKey.With(GetType(), "GetAssetHash", filePath); return(_memoryCache.GetOrCreate(cacheKey, (cacheEntry) => { cacheEntry.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(filePath) })); using (var stream = GetAssetStream(filePath)) { var hashAlgorithm = CryptoConfig.AllowOnlyFipsAlgorithms ? (SHA256) new SHA256CryptoServiceProvider() : new SHA256Managed(); return WebEncoders.Base64UrlEncode(hashAlgorithm.ComputeHash(stream)); } })); }
/// <summary> /// Render template by content and parameters /// </summary> /// <param name="templateContent"></param> /// <param name="parameters"></param> /// <returns></returns> public ValueTask<string> RenderTemplateAsync(string templateContent, string templatePath, object context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (!(context is IScriptObject scriptObject)) { throw new StorefrontException($"{ nameof(context) } must implement IScriptObject"); } if (string.IsNullOrEmpty(templateContent)) { return new ValueTask<string>(templateContent); } var isLiquidTemplate = _isLiquid.Match(templateContent); if (!isLiquidTemplate.Success) { return new ValueTask<string>(templateContent); } //TODO: Handle _options.RethrowLiquidRenderErrors var cacheKey = CacheKey.With(GetType(), "ParseTemplate", templatePath ?? templateContent); var parsedTemplate = _memoryCache.GetOrCreate(cacheKey, (cacheItem) => { if (!string.IsNullOrEmpty(templatePath)) { cacheItem.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(templatePath) })); } else { cacheItem.AddExpirationToken(ThemeEngineCacheRegion.CreateChangeToken()); } return Template.ParseLiquid(templateContent, templatePath); }); if (parsedTemplate.HasErrors) { throw new InvalidOperationException(string.Join("\n", parsedTemplate.Messages)); } var templateContext = new TemplateContext() { TemplateLoader = this, EnableRelaxedMemberAccess = true, NewLine = Environment.NewLine, TemplateLoaderLexerOptions = new LexerOptions { Mode = ScriptMode.Liquid } }; templateContext.PushGlobal(scriptObject); var result = parsedTemplate.Render(templateContext); return new ValueTask<string>(result); }