public async Task includeFileWithCache(TemplateScopeContext scope, string virtualPath, 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[TemplateConstants.DefaultFileCacheExpiry]; var cacheKey = CreateCacheKey("file:" + scope.PageResult.VirtualPath + ">" + virtualPath, 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 file = ResolveFile(nameof(includeFileWithCache), scope, virtualPath); var ms = MemoryStreamFactory.GetStream(); using (ms) { using (var reader = file.OpenRead()) { await reader.CopyToAsync(ms); } ms.Position = 0; var bytes = ms.ToArray(); Context.ExpiringCache[cacheKey] = Tuple.Create(DateTime.UtcNow.Add(expireIn), (object)bytes); await scope.OutputStream.WriteAsync(bytes); } }
public async Task includeUrl(TemplateScopeContext scope, string url, object options) { var scopedParams = scope.AssertOptions(nameof(includeUrl), options); var dataType = scopedParams.TryGetValue("dataType", out object value) ? ConvertDataTypeToContentType((string)value) : null; var webReq = (HttpWebRequest)WebRequest.Create(url); if (scopedParams.TryGetValue("method", out value)) { webReq.Method = (string)value; } if (scopedParams.TryGetValue("contentType", out value) || dataType != null) { webReq.ContentType = (string)value ?? dataType; } if (scopedParams.TryGetValue("accept", out value) || dataType != null) { webReq.Accept = (string)value ?? dataType; } if (scopedParams.TryGetValue("userAgent", out value)) { #if NET45 || NET40 webReq.UserAgent = value.ToString(); #else webReq.Headers[HttpRequestHeader.UserAgent] = value.ToString(); #endif } if (scopedParams.TryRemove("data", out object data)) { if (webReq.Method == null) { webReq.Method = HttpMethods.Post; } if (webReq.ContentType == null) { webReq.ContentType = MimeTypes.FormUrlEncoded; } var body = ConvertDataToString(data, webReq.ContentType); using (var stream = await webReq.GetRequestStreamAsync()) { await stream.WriteAsync(body); } } using (var webRes = await webReq.GetResponseAsync()) using (var stream = webRes.GetResponseStream()) { await stream.CopyToAsync(scope.OutputStream); } }
public async Task includeUrlWithCache(TemplateScopeContext scope, string url, object options) { var scopedParams = scope.AssertOptions(nameof(includeUrl), options); var expireIn = scopedParams.TryGetValue("expireInSecs", out var value) ? TimeSpan.FromSeconds(value.ConvertTo <int>()) : (TimeSpan)scope.Context.Args[TemplateConstants.DefaultUrlCacheExpiry]; var cacheKey = CreateCacheKey($"url:{url}", scopedParams); if (Context.ExpiringCache.TryGetValue(cacheKey, out var 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(DateTime.UtcNow.Add(expireIn), (object)bytes); await scope.OutputStream.WriteAsync(bytes); } }
public static Dictionary <string, object> GetParamsWithItemBindingOnly(this TemplateScopeContext scope, string filterName, TemplatePage page, object scopedParams, out string itemBinding) { var pageParams = scope.AssertOptions(filterName, scopedParams); itemBinding = pageParams.TryGetValue("it", out object bindingName) && bindingName is string binding ? binding : "it"; if (bindingName != null && !(bindingName is string)) { throw new NotSupportedException($"'it' option in filter '{filterName}' should contain the name to bind to but contained a '{bindingName.GetType().Name}' instead"); } // page vars take precedence if (page != null && page.Args.TryGetValue("it", out object pageBinding)) { itemBinding = (string)pageBinding; } return(pageParams); }
public async Task includeFileWithCache(TemplateScopeContext scope, string virtualPath, 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[TemplateConstants.DefaultCacheExpiry]; var cacheKey = CreateCacheKey("file:" + virtualPath, 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 file = scope.Context.VirtualFiles.GetFile(virtualPath); if (file == null) { throw new FileNotFoundException($"{nameof(includeFileWithCache)} with '{virtualPath}' in page '{scope.Page.VirtualPath}' was not found"); } var ms = MemoryStreamFactory.GetStream(); using (ms) { var captureScope = scope.ScopeWithStream(ms); await includeFile(captureScope, virtualPath); ms.Position = 0; var bytes = ms.ToArray(); Context.ExpiringCache[cacheKey] = cacheEntry = Tuple.Create(DateTime.UtcNow.Add(expireIn), (object)bytes); await scope.OutputStream.WriteAsync(bytes); } }
public IRawString htmlDump(TemplateScopeContext scope, object target, object scopeOptions) { var scopedParams = scope.AssertOptions(nameof(htmlDump), scopeOptions); var depth = scopedParams.TryGetValue("depth", out object oDepth) ? (int)oDepth : 0; var childDepth = scopedParams.TryGetValue("childDepth", out object oChildDepth) ? oChildDepth.ConvertTo <int>() : 1; scopedParams["depth"] = depth + 1; try { if (!isComplexType(target)) { return(GetScalarHtml(target).ToRawString()); } scopedParams.TryGetValue("captionIfEmpty", out object captionIfEmpty); scopedParams.TryGetValue("headerStyle", out object oHeaderStyle); scopedParams.TryGetValue("className", out object parentClass); scopedParams.TryGetValue("childClass", out object childClass); var headerStyle = oHeaderStyle as string ?? "splitCase"; var className = ((depth < childDepth ? parentClass : childClass ?? parentClass) ?? Context.Args[TemplateConstants.DefaultTableClassName]).ToString(); if (target is IEnumerable e) { var objs = e.Map(x => x); var isEmpty = objs.Count == 0; if (isEmpty && captionIfEmpty == null) { return(RawString.Empty); } var first = !isEmpty ? objs[0] : null; if (first is IDictionary) { return(htmlList(scope, target, scopeOptions)); } var sb = StringBuilderCacheAlt.Allocate(); sb.Append("<table"); if (scopedParams.TryGetValue("id", out object id)) { sb.Append(" id=\"").Append(id).Append("\""); } sb.Append(" class=\"").Append(className).Append("\""); sb.Append(">"); scopedParams.TryGetValue("caption", out object caption); if (isEmpty) { caption = captionIfEmpty; } if (caption != null && !scopedParams.TryGetValue("hasCaption", out _)) { sb.Append("<caption>").Append(caption.ToString().HtmlEncode()).Append("</caption>"); scopedParams["hasCaption"] = true; } if (!isEmpty) { sb.Append("<tbody>"); if (first is KeyValuePair <string, object> ) { foreach (var o in objs) { if (o is KeyValuePair <string, object> kvp) { if (kvp.Value == target) { break; // Prevent cyclical deps like 'it' binding } sb.Append("<tr>"); sb.Append("<th>"); sb.Append(Context.DefaultFilters?.textStyle(kvp.Key, headerStyle)?.HtmlEncode()); sb.Append("</th>"); sb.Append("<td>"); if (!isComplexType(kvp.Value)) { sb.Append(GetScalarHtml(kvp.Value)); } else { var body = htmlDump(scope, kvp.Value, scopeOptions); sb.Append(body.ToRawString()); } sb.Append("</td>"); sb.Append("</tr>"); } } } else if (!isComplexType(first)) { foreach (var o in objs) { sb.Append("<tr>"); sb.Append("<td>"); sb.Append(GetScalarHtml(o)); sb.Append("</td>"); sb.Append("</tr>"); } } else { if (objs.Count > 1) { var rows = objs.Map(x => x.ToObjectDictionary()); sb.Append("<tr>"); sb.Append("<td>"); var list = htmlList(scope, rows, scopeOptions); sb.Append(list.ToRawString()); sb.Append("</td>"); sb.Append("</tr>"); } else { foreach (var o in objs) { sb.Append("<tr>"); if (!isComplexType(o)) { sb.Append("<td>"); sb.Append(GetScalarHtml(o)); sb.Append("</td>"); } else { sb.Append("<td>"); var body = htmlDump(scope, o, scopeOptions); sb.Append(body.ToRawString()); sb.Append("</td>"); } sb.Append("</tr>"); } } } sb.Append("</tbody>"); } sb.Append("</table>"); var html = StringBuilderCacheAlt.ReturnAndFree(sb); return(html.ToRawString()); } return(htmlDump(scope, target.ToObjectDictionary(), scopeOptions)); } finally { scopedParams["depth"] = depth; } }
public IRawString htmlList(TemplateScopeContext scope, object target, object scopeOptions) { if (target is IDictionary <string, object> single) { target = new[] { single } } ; var items = target.AssertEnumerable(nameof(htmlList)); var scopedParams = scope.AssertOptions(nameof(htmlList), scopeOptions); var depth = scopedParams.TryGetValue("depth", out object oDepth) ? (int)oDepth : 0; var childDepth = scopedParams.TryGetValue("childDepth", out object oChildDepth) ? oChildDepth.ConvertTo <int>() : 1; scopedParams["depth"] = depth + 1; try { scopedParams.TryGetValue("className", out object parentClass); scopedParams.TryGetValue("childClass", out object childClass); var className = ((depth < childDepth ? parentClass : childClass ?? parentClass) ?? Context.Args[TemplateConstants.DefaultTableClassName]).ToString(); scopedParams.TryGetValue("headerStyle", out object oHeaderStyle); scopedParams.TryGetValue("headerTag", out object oHeaderTag); scopedParams.TryGetValue("captionIfEmpty", out object captionIfEmpty); var headerTag = oHeaderTag as string ?? "th"; var headerStyle = oHeaderStyle as string ?? "splitCase"; var sbHeader = StringBuilderCache.Allocate(); var sbRows = StringBuilderCacheAlt.Allocate(); List <string> keys = null; foreach (var item in items) { if (item is IDictionary <string, object> d) { if (keys == null) { keys = d.Keys.ToList(); sbHeader.Append("<tr>"); foreach (var key in keys) { sbHeader.Append('<').Append(headerTag).Append('>'); sbHeader.Append(Context.DefaultFilters?.textStyle(key, headerStyle)?.HtmlEncode()); sbHeader.Append("</").Append(headerTag).Append('>'); } sbHeader.Append("</tr>"); } sbRows.Append("<tr>"); foreach (var key in keys) { var value = d[key]; if (value == target) { break; // Prevent cyclical deps like 'it' binding } sbRows.Append("<td>"); if (!isComplexType(value)) { sbRows.Append(GetScalarHtml(value)); } else { var htmlValue = htmlDump(scope, value, scopeOptions); sbRows.Append(htmlValue.ToRawString()); } sbRows.Append("</td>"); } sbRows.Append("</tr>"); } } var isEmpty = sbRows.Length == 0; if (isEmpty && captionIfEmpty == null) { return(RawString.Empty); } var htmlHeaders = StringBuilderCache.ReturnAndFree(sbHeader); var htmlRows = StringBuilderCacheAlt.ReturnAndFree(sbRows); var sb = StringBuilderCache.Allocate(); sb.Append("<table"); if (scopedParams.TryGetValue("id", out object id)) { sb.Append(" id=\"").Append(id).Append("\""); } if (!string.IsNullOrEmpty(className)) { sb.Append(" class=\"").Append(className).Append("\""); } sb.Append(">"); scopedParams.TryGetValue("caption", out object caption); if (isEmpty) { caption = captionIfEmpty; } if (caption != null && !scopedParams.TryGetValue("hasCaption", out _)) { sb.Append("<caption>").Append(caption.ToString().HtmlEncode()).Append("</caption>"); scopedParams["hasCaption"] = true; } if (htmlHeaders.Length > 0) { sb.Append("<thead>").Append(htmlHeaders).Append("</thead>"); } if (htmlRows.Length > 0) { sb.Append("<tbody>").Append(htmlRows).Append("</tbody>"); } sb.Append("</table>"); var html = StringBuilderCache.ReturnAndFree(sb); return(html.ToRawString()); } finally { scopedParams["depth"] = depth; } }
public IRawString textDump(TemplateScopeContext scope, object target, object scopeOptions) { var scopedParams = scope.AssertOptions(nameof(textDump), scopeOptions); var depth = scopedParams.TryGetValue("depth", out object oDepth) ? (int)oDepth : 0; scopedParams["depth"] = depth + 1; try { if (!isComplexType(target)) { return(GetScalarText(target).ToRawString()); } scopedParams.TryGetValue("captionIfEmpty", out object captionIfEmpty); scopedParams.TryGetValue("headerStyle", out object oHeaderStyle); var headerStyle = oHeaderStyle as string ?? "splitCase"; if (target is IEnumerable e) { var objs = e.Map(x => x); var isEmpty = objs.Count == 0; if (isEmpty && captionIfEmpty == null) { return(RawString.Empty); } var first = !isEmpty ? objs[0] : null; if (first is IDictionary) { return(textList(scope, target, scopeOptions)); } scopedParams.TryGetValue("caption", out object caption); if (isEmpty) { caption = captionIfEmpty; } var sb = StringBuilderCacheAlt.Allocate(); string writeCaption = null; if (caption != null && !scopedParams.TryGetValue("hasCaption", out _)) { writeCaption = caption.ToString(); scopedParams["hasCaption"] = true; } if (!isEmpty) { var keys = new List <string>(); var values = new List <string>(); if (first is KeyValuePair <string, object> ) { foreach (var o in objs) { if (o is KeyValuePair <string, object> kvp) { if (kvp.Value == target) { break; // Prevent cyclical deps like 'it' binding } keys.Add(Context.DefaultFilters?.textStyle(kvp.Key, headerStyle) ?? ""); var field = !isComplexType(kvp.Value) ? GetScalarText(kvp.Value) : textDump(scope, kvp.Value, scopeOptions).ToRawString(); values.Add(field); } } var keySize = keys.Max(x => x.Length); var valuesSize = values.Max(x => x.Length); sb.AppendLine(writeCaption != null ? $"| {writeCaption} ||" : $"|||"); sb.AppendLine("|-|-|"); for (var i = 0; i < keys.Count; i++) { sb.Append("| ") .Append(keys[i].PadRight(keySize, ' ')) .Append(" | ") .Append(values[i].PadRight(valuesSize, ' ')) .Append(" |") .AppendLine(); } } else { if (!isComplexType(first)) { sb.AppendLine(writeCaption != null ? $"| {writeCaption} |" : $"||"); sb.AppendLine("|-|"); foreach (var o in objs) { sb.Append("| ") .Append(GetScalarText(o)) .Append(" |") .AppendLine(); } } else { if (writeCaption != null) { sb.AppendLine(writeCaption); } if (objs.Count > 1) { var rows = objs.Map(x => x.ToObjectDictionary()); var list = textList(scope, rows, scopeOptions).ToRawString(); sb.AppendLine(list); } else { foreach (var o in objs) { if (!isComplexType(o)) { sb.AppendLine(GetScalarText(o)); } else { var body = textDump(scope, o, scopeOptions).ToRawString(); sb.AppendLine(body); } } } } } } return(StringBuilderCache.ReturnAndFree(sb).ToRawString()); } return(textDump(scope, target.ToObjectDictionary(), scopeOptions)); } finally { scopedParams["depth"] = depth; } }
public IRawString textList(TemplateScopeContext scope, object target, object scopeOptions) { if (target is IDictionary <string, object> single) { target = new[] { single } } ; var items = target.AssertEnumerable(nameof(textList)); var scopedParams = scope.AssertOptions(nameof(textList), scopeOptions); var depth = scopedParams.TryGetValue("depth", out object oDepth) ? (int)oDepth : 0; scopedParams["depth"] = depth + 1; try { scopedParams.TryGetValue("headerStyle", out object oHeaderStyle); scopedParams.TryGetValue("captionIfEmpty", out object captionIfEmpty); var headerStyle = oHeaderStyle as string ?? "splitCase"; List <string> keys = null; var table = new MarkdownTable(); if (scopedParams.TryGetValue("rowNumbers", out object rowNumbers)) { table.IncludeRowNumbers = !(rowNumbers is bool b) || b; } foreach (var item in items) { if (item is IDictionary <string, object> d) { if (keys == null) { keys = d.Keys.ToList(); foreach (var key in keys) { table.Headers.Add(Context.DefaultFilters?.textStyle(key, headerStyle)); } } var row = new List <string>(); foreach (var key in keys) { var value = d[key]; if (value == target) { break; // Prevent cyclical deps like 'it' binding } if (!isComplexType(value)) { row.Add(GetScalarText(value)); } else { var cellValue = textDump(scope, value, scopeOptions); row.Add(cellValue.ToRawString()); } } table.Rows.Add(row); } } var isEmpty = table.Rows.Count == 0; if (isEmpty && captionIfEmpty == null) { return(RawString.Empty); } scopedParams.TryGetValue("caption", out object caption); if (isEmpty) { caption = captionIfEmpty; } if (caption != null && !scopedParams.TryGetValue("hasCaption", out _)) { table.Caption = caption.ToString(); scopedParams["hasCaption"] = true; } var txt = table.Render(); return(txt.ToRawString()); } finally { scopedParams["depth"] = depth; } }
public IRawString htmltable(TemplateScopeContext scope, object target, object scopeOptions) { if (target is IDictionary <string, object> single) { target = new[] { single } } ; var items = target.AssertEnumerable(nameof(htmltable)); var scopedParams = scope.AssertOptions(nameof(htmltable), scopeOptions); scopedParams.TryGetValue("headerStyle", out object oHeaderStyle); scopedParams.TryGetValue("headerTag", out object oHeaderTag); scopedParams.TryGetValue("emptyCaption", out object emptyCaption); var headerTag = oHeaderTag as string ?? "th"; var headerStyle = oHeaderStyle as string ?? "splitCase"; var sbHeader = StringBuilderCache.Allocate(); var sbRows = StringBuilderCacheAlt.Allocate(); List <string> keys = null; foreach (var item in items) { if (item is IDictionary <string, object> d) { if (keys == null) { keys = d.Keys.ToList(); sbHeader.Append("<tr>"); foreach (var key in keys) { sbHeader.Append('<').Append(headerTag).Append('>'); sbHeader.Append(TemplateDefaultFilters.Instance.textStyle(key, headerStyle)?.HtmlEncode()); sbHeader.Append("</").Append(headerTag).Append('>'); } sbHeader.Append("</tr>"); } sbRows.Append("<tr>"); foreach (var key in keys) { var value = d[key]; var encodedValue = value?.ToString()?.HtmlEncode(); sbRows.Append("<td>").Append(encodedValue).Append("</td>"); } sbRows.Append("</tr>"); } } var isEmpty = sbRows.Length == 0; if (isEmpty && emptyCaption == null) { return(RawString.Empty); } var htmlHeaders = StringBuilderCache.ReturnAndFree(sbHeader); var htmlRows = StringBuilderCacheAlt.ReturnAndFree(sbRows); var sb = StringBuilderCache.Allocate(); sb.Append("<table"); if (scopedParams.TryGetValue("id", out object id)) { sb.Append(" id=\"").Append(id).Append("\""); } if (scopedParams.TryGetValue("className", out object className)) { sb.Append(" class=\"").Append(className).Append("\""); } sb.Append(">"); scopedParams.TryGetValue("caption", out object caption); if (isEmpty) { caption = emptyCaption; } if (caption != null) { sb.Append("<caption>").Append(caption.ToString().HtmlEncode()).Append("</caption>"); } if (htmlHeaders.Length > 0) { sb.Append("<thead>").Append(htmlHeaders).Append("</thead>"); } if (htmlRows.Length > 0) { sb.Append("<tbody>").Append(htmlRows).Append("</tbody>"); } sb.Append("</table>"); var html = StringBuilderCache.ReturnAndFree(sb); return(html.ToRawString()); } }