private string ReadTemplateByName(string templateName) { var templatePath = ResolveTemplatePath(templateName); if (string.IsNullOrEmpty(templatePath)) { throw new FileSystemException($"The template '{templateName}' was not found. The following locations were searched:<br/>{string.Join("<br/>", DiscoveryPaths)}"); } var cacheKey = CacheKey.With(GetType(), "ReadTemplateByName", templatePath); return(_memoryCache.GetOrCreate(cacheKey, (cacheItem) => { cacheItem.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(templatePath) })); using (var stream = _themeBlobProvider.OpenRead(templatePath)) { return stream.ReadToString(); } })); }
/// <summary> /// Read localization resources /// </summary> /// <returns></returns> public JObject ReadLocalization() { var cacheKey = CacheKey.With(GetType(), "ReadLocalization", CurrentThemeLocalePath, WorkContext.CurrentLanguage.CultureName); return(_memoryCache.GetOrCreateExclusive(cacheKey, (cacheItem) => { var result = new JObject(); cacheItem.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(CurrentThemeLocalePath + "/*") })); //Try to load localization resources from base theme path and merge them with resources for local theme if (BaseThemeLocalePath != null) { cacheItem.AddExpirationToken(new CompositeChangeToken(new[] { ThemeEngineCacheRegion.CreateChangeToken(), _themeBlobProvider.Watch(BaseThemeLocalePath + "/*") })); result = InnerReadLocalization(_themeBlobProvider, BaseThemeLocalePath, WorkContext.CurrentLanguage); } result.Merge(InnerReadLocalization(_themeBlobProvider, CurrentThemeLocalePath, WorkContext.CurrentLanguage) ?? new JObject(), new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Merge }); return result; })); }
/// <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)); }