public override async Task WriteAsync(ScriptScopeContext scope, PageBlockFragment block, CancellationToken token) { var result = await block.Argument.GetJsExpressionAndEvaluateAsync(scope, ifNone : () => throw new NotSupportedException("'with' block does not have a valid expression")); if (result != null) { var resultAsMap = result.ToObjectDictionary(); var withScope = scope.ScopeWithParams(resultAsMap); await WriteBodyAsync(withScope, block, token); } else { await WriteElseAsync(scope, block.ElseBlocks, token); } }
public override async Task WriteAsync(ScriptScopeContext scope, PageBlockFragment block, CancellationToken token) { var htmlAttrs = block.Argument.GetJsExpressionAndEvaluate(scope) as Dictionary <string, object>; var hasEach = false; IEnumerable each = null; var binding = "it"; var hasExplicitBinding = false; JsToken where = null; if (htmlAttrs != null) { if (htmlAttrs.TryGetValue("if", out var oIf)) { if (Script.DefaultScripts.isFalsy(oIf)) { return; } htmlAttrs.Remove("if"); } if (htmlAttrs.TryGetValue(nameof(where), out var oWhere)) { if (!(oWhere is string whereExpr)) { throw new NotSupportedException($"'where' should be a string expression but instead found '{oWhere.GetType().Name}'"); } where = whereExpr.GetCachedJsExpression(scope); htmlAttrs.Remove(nameof(where)); } if (htmlAttrs.TryGetValue(nameof(each), out var oEach)) { hasEach = true; htmlAttrs.Remove(nameof(each)); } each = oEach as IEnumerable; if (htmlAttrs.TryGetValue("it", out var oIt) && oIt is string it) { binding = it; hasExplicitBinding = true; htmlAttrs.Remove("it"); } if (htmlAttrs.TryGetValue("class", out var oClass)) { var cls = scope.Context.HtmlMethods.htmlClassList(oClass); if (string.IsNullOrEmpty(cls)) { htmlAttrs.Remove("class"); } else { htmlAttrs["class"] = cls; } } } var attrString = scope.Context.HtmlMethods.htmlAttrsList(htmlAttrs); if (HtmlScripts.VoidElements.Contains(Tag)) //e.g. img, input, br, etc { await scope.OutputStream.WriteAsync($"<{Tag}{attrString}>{Suffix}", token); } else { if (hasEach) { var hasElements = each != null && each.GetEnumerator().MoveNext(); if (hasElements) { await scope.OutputStream.WriteAsync($"<{Tag}{attrString}>{Suffix}", token); var index = 0; var whereIndex = 0; foreach (var element in each) { // Add all properties into scope if called without explicit in argument var scopeArgs = !hasExplicitBinding && CanExportScopeArgs(element) ? element.ToObjectDictionary() : new Dictionary <string, object>(); scopeArgs[binding] = element; scopeArgs[nameof(index)] = AssertWithinMaxQuota(whereIndex++); var itemScope = scope.ScopeWithParams(scopeArgs); if (where != null) { var result = where.EvaluateToBool(itemScope); if (!result) { continue; } } itemScope.ScopedParams[nameof(index)] = AssertWithinMaxQuota(index++); await WriteBodyAsync(itemScope, block, token); } await scope.OutputStream.WriteAsync($"</{Tag}>{Suffix}", token); } else { await WriteElseAsync(scope, block.ElseBlocks, token); } } else { await scope.OutputStream.WriteAsync($"<{Tag}{attrString}>{Suffix}", token); await WriteBodyAsync(scope, block, token); await scope.OutputStream.WriteAsync($"</{Tag}>{Suffix}", token); } } }
public static async Task WritePageAsync(this ScriptScopeContext scope, SharpPage page, SharpCodePage codePage, Dictionary <string, object> pageParams, CancellationToken token = default(CancellationToken)) { await scope.PageResult.WritePageAsync(page, codePage, scope.ScopeWithParams(pageParams), token); }
public override async Task WriteAsync(ScriptScopeContext scope, PageBlockFragment block, CancellationToken token) { if (block.Argument.IsNullOrEmpty()) { throw new NotSupportedException("'each' block requires the collection to iterate"); } var cache = (EachArg)scope.Context.Cache.GetOrAdd(block.ArgumentString, _ => ParseArgument(scope, block)); var collection = cache.Source.Evaluate(scope, out var syncResult, out var asyncResult) ? (IEnumerable)syncResult : (IEnumerable)(await asyncResult.ConfigAwait()); var index = 0; if (collection != null) { if (cache.Where != null || cache.OrderBy != null || cache.OrderByDescending != null || cache.Skip != null || cache.Take != null) { var filteredResults = new List <Dictionary <string, object> >(); foreach (var element in collection) { // Add all properties into scope if called without explicit in argument var scopeArgs = !cache.HasExplicitBinding && CanExportScopeArgs(element) ? element.ToObjectDictionary() : new Dictionary <string, object>(); scopeArgs[cache.Binding] = element; scopeArgs[nameof(index)] = AssertWithinMaxQuota(index++); var itemScope = scope.ScopeWithParams(scopeArgs); if (cache.Where != null) { var result = await cache.Where.EvaluateToBoolAsync(itemScope).ConfigAwait(); if (!result) { continue; } } filteredResults.Add(scopeArgs); } IEnumerable <Dictionary <string, object> > selectedResults = filteredResults; var comparer = (IComparer <object>)Comparer <object> .Default; if (cache.OrderBy != null) { var i = 0; selectedResults = selectedResults.OrderBy(scopeArgs => { scopeArgs[nameof(index)] = i++; return(cache.OrderBy.Evaluate(scope.ScopeWithParams(scopeArgs))); }, comparer); } else if (cache.OrderByDescending != null) { var i = 0; selectedResults = selectedResults.OrderByDescending(scopeArgs => { scopeArgs[nameof(index)] = i++; return(cache.OrderByDescending.Evaluate(scope.ScopeWithParams(scopeArgs))); }, comparer); } if (cache.Skip != null) { var skip = cache.Skip.Evaluate(scope).ConvertTo <int>(); selectedResults = selectedResults.Skip(skip); } if (cache.Take != null) { var take = cache.Take.Evaluate(scope).ConvertTo <int>(); selectedResults = selectedResults.Take(take); } index = 0; foreach (var scopeArgs in selectedResults) { var itemScope = scope.ScopeWithParams(scopeArgs); itemScope.ScopedParams[nameof(index)] = index++; await WriteBodyAsync(itemScope, block, token).ConfigAwait(); } } else { foreach (var element in collection) { // Add all properties into scope if called without explicit in argument var scopeArgs = !cache.HasExplicitBinding && CanExportScopeArgs(element) ? element.ToObjectDictionary() : new Dictionary <string, object>(); scopeArgs[cache.Binding] = element; scopeArgs[nameof(index)] = AssertWithinMaxQuota(index++); var itemScope = scope.ScopeWithParams(scopeArgs); await WriteBodyAsync(itemScope, block, token).ConfigAwait(); } } } if (index == 0) { await WriteElseAsync(scope, block.ElseBlocks, token).ConfigAwait(); } }