public override IDisplayResult Display(HtmlField field, BuildFieldDisplayContext context) { return(Initialize <DisplayHtmlFieldViewModel>(GetDisplayShapeType(context), async model => { model.Html = field.Html; model.Field = field; model.Part = context.ContentPart; model.PartFieldDefinition = context.PartFieldDefinition; var settings = context.PartFieldDefinition.GetSettings <HtmlFieldSettings>(); if (!settings.SanitizeHtml) { model.Html = await _liquidTemplateManager.RenderAsync(field.Html, _htmlEncoder, model, scope => scope.SetValue("ContentItem", field.ContentItem)); } model.Html = await _shortcodeService.ProcessAsync(model.Html, new Context { ["ContentItem"] = field.ContentItem, ["PartFieldDefinition"] = context.PartFieldDefinition }); }) .Location("Detail", "Content") .Location("Summary", "Content")); }
private async ValueTask BuildViewModel(MarkdownBodyPartViewModel model, MarkdownBodyPart markdownBodyPart, BuildPartDisplayContext context) { model.Markdown = markdownBodyPart.Markdown; model.MarkdownBodyPart = markdownBodyPart; model.ContentItem = markdownBodyPart.ContentItem; // The default Markdown option is to entity escape html // so filters must be run after the markdown has been processed. model.Html = _markdownService.ToHtml(model.Markdown ?? ""); var settings = context.TypePartDefinition.GetSettings <MarkdownBodyPartSettings>(); // The liquid rendering is for backwards compatibility and can be removed in a future version. if (!settings.SanitizeHtml) { model.Html = await _liquidTemplateManager.RenderStringAsync(model.Html, _htmlEncoder, model, new Dictionary <string, FluidValue>() { ["ContentItem"] = new ObjectValue(model.ContentItem) }); } model.Html = await _shortcodeService.ProcessAsync(model.Html, new Context { ["ContentItem"] = markdownBodyPart.ContentItem, ["TypePartDefinition"] = context.TypePartDefinition }); if (settings.SanitizeHtml) { model.Html = _htmlSanitizerService.Sanitize(model.Html ?? ""); } }
public override Task GetContentItemAspectAsync(ContentItemAspectContext context, MarkdownBodyPart part) { return(context.ForAsync <BodyAspect>(async bodyAspect => { if (bodyAspect != null && part.ContentItem.Id == _contentItemId) { bodyAspect.Body = _bodyAspect; return; } try { var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(part.ContentItem.ContentType); var contentTypePartDefinition = contentTypeDefinition.Parts.FirstOrDefault(x => String.Equals(x.PartDefinition.Name, "MarkdownBodyPart")); var settings = contentTypePartDefinition.GetSettings <MarkdownBodyPartSettings>(); // The default Markdown option is to entity escape html // so filters must be run after the markdown has been processed. var html = _markdownService.ToHtml(part.Markdown); // The liquid rendering is for backwards compatability and can be removed in a future version. if (!settings.SanitizeHtml) { var model = new MarkdownBodyPartViewModel() { Markdown = part.Markdown, Html = html, MarkdownBodyPart = part, ContentItem = part.ContentItem }; html = await _liquidTemplateManager.RenderAsync(html, _htmlEncoder, model, scope => scope.SetValue("ContentItem", model.ContentItem)); } html = await _shortcodeService.ProcessAsync(html, new Context { ["ContentItem"] = part.ContentItem, ["TypePartDefinition"] = contentTypePartDefinition }); if (settings.SanitizeHtml) { html = _htmlSanitizerService.Sanitize(html); } bodyAspect.Body = _bodyAspect = new HtmlString(html); _contentItemId = part.ContentItem.Id; } catch { bodyAspect.Body = HtmlString.Empty; _contentItemId = default; } })); }
public override Task GetContentItemAspectAsync(ContentItemAspectContext context, HtmlBodyPart part) { return(context.ForAsync <BodyAspect>(async bodyAspect => { if (bodyAspect != null && part.ContentItem.Id == _contentItemId) { bodyAspect.Body = _bodyAspect; return; } try { var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(part.ContentItem.ContentType); var contentTypePartDefinition = contentTypeDefinition.Parts.FirstOrDefault(x => string.Equals(x.PartDefinition.Name, "HtmlBodyPart")); var settings = contentTypePartDefinition.GetSettings <HtmlBodyPartSettings>(); var html = part.Html; if (!settings.SanitizeHtml) { var model = new HtmlBodyPartViewModel() { Html = part.Html, HtmlBodyPart = part, ContentItem = part.ContentItem }; html = await _liquidTemplateManager.RenderAsync(html, _htmlEncoder, model, scope => scope.SetValue("ContentItem", model.ContentItem)); } html = await _shortcodeService.ProcessAsync(html, new Context { ["ContentItem"] = part.ContentItem, ["TypePartDefinition"] = contentTypePartDefinition }); bodyAspect.Body = _bodyAspect = new HtmlString(html); _contentItemId = part.ContentItem.Id; } catch { bodyAspect.Body = HtmlString.Empty; _contentItemId = default; } })); }
private async ValueTask BuildViewModelAsync(HtmlBodyPartViewModel model, HtmlBodyPart htmlBodyPart, BuildPartDisplayContext context) { model.Html = htmlBodyPart.Html; model.HtmlBodyPart = htmlBodyPart; model.ContentItem = htmlBodyPart.ContentItem; var settings = context.TypePartDefinition.GetSettings <HtmlBodyPartSettings>(); if (!settings.SanitizeHtml) { model.Html = await _liquidTemplateManager.RenderAsync(htmlBodyPart.Html, _htmlEncoder, model, scope => scope.SetValue("ContentItem", model.ContentItem)); } model.Html = await _shortcodeService.ProcessAsync(model.Html, new Context { ["ContentItem"] = htmlBodyPart.ContentItem, ["TypePartDefinition"] = context.TypePartDefinition }); }
public override IDisplayResult Display(MarkdownField field, BuildFieldDisplayContext context) { return(Initialize <MarkdownFieldViewModel>(GetDisplayShapeType(context), async model => { var settings = context.PartFieldDefinition.GetSettings <MarkdownFieldSettings>(); model.Markdown = field.Markdown; model.Field = field; model.Part = context.ContentPart; model.PartFieldDefinition = context.PartFieldDefinition; // The default Markdown option is to entity escape html // so filters must be run after the markdown has been processed. model.Html = _markdownService.ToHtml(model.Markdown ?? ""); // The liquid rendering is for backwards compatability and can be removed in a future version. if (!settings.SanitizeHtml) { model.Markdown = await _liquidTemplateManager.RenderStringAsync(model.Html, _htmlEncoder, model, new Dictionary <string, FluidValue>() { ["ContentItem"] = new ObjectValue(field.ContentItem) }); } model.Html = await _shortcodeService.ProcessAsync(model.Html, new Context { ["ContentItem"] = field.ContentItem, ["PartFieldDefinition"] = context.PartFieldDefinition }); if (settings.SanitizeHtml) { model.Html = _htmlSanitizerService.Sanitize(model.Html ?? ""); } }) .Location("Detail", "Content") .Location("Summary", "Content")); }
public override async Task <IDisplayResult> DisplayAsync(ContentItem contentItem, BuildDisplayContext context) { // We only apply this on the primary content item, which is considered the first call to BuildDisplay. if (_primaryContentRendered) { return(null); } _primaryContentRendered = true; // Do not include Widgets or any display type other than detail. if (context.DisplayType != "Detail" || context.Shape.TryGetProperty(nameof(ContentTypeSettings.Stereotype), out string _)) { return(null); } var aspect = await _contentManager.PopulateAspectAsync <SeoAspect>(contentItem); if (!aspect.Render) { return(null); } var shortCodeContext = new Context { ["ContentItem"] = contentItem }; if (!String.IsNullOrEmpty(aspect.PageTitle)) { _pageTitleBuilder.SetFixedTitle(new HtmlString(_htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.PageTitle, shortCodeContext)))); } if (!String.IsNullOrEmpty(aspect.MetaDescription)) { _resourceManager.RegisterMeta(new MetaEntry { Name = "description", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.MetaDescription, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.MetaKeywords)) { _resourceManager.RegisterMeta(new MetaEntry { Name = "keywords", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.MetaKeywords, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.Canonical)) { _resourceManager.RegisterLink(new LinkEntry { Href = aspect.Canonical, Rel = "canonical" }); } if (!String.IsNullOrEmpty(aspect.MetaRobots)) { _resourceManager.RegisterMeta(new MetaEntry { Name = "robots", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.MetaRobots, shortCodeContext)) }); } foreach (var customMetaTag in aspect.CustomMetaTags) { // Generate a new meta entry as the builder is preopulated. _resourceManager.RegisterMeta(new MetaEntry( _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(customMetaTag.Name, shortCodeContext)), _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(customMetaTag.Property, shortCodeContext)), _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(customMetaTag.Content, shortCodeContext)), _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(customMetaTag.HttpEquiv, shortCodeContext)), _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(customMetaTag.Charset, shortCodeContext)))); } // OpenGraph. if (!String.IsNullOrEmpty(aspect.OpenGraphType)) { _resourceManager.RegisterMeta(new MetaEntry { Property = "og:type", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphType, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.OpenGraphTitle)) { _resourceManager.RegisterMeta(new MetaEntry { Property = "og:title", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphTitle, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.OpenGraphDescription)) { _resourceManager.RegisterMeta(new MetaEntry { Property = "og:description", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphDescription, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.OpenGraphImage)) { _resourceManager.RegisterMeta(new MetaEntry { Property = "og:image", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphImage, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.OpenGraphImageAlt)) { _resourceManager.RegisterMeta(new MetaEntry { Property = "og:image:alt", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphImageAlt, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.OpenGraphUrl)) { _resourceManager.RegisterMeta(new MetaEntry { Property = "og:url", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphUrl, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.OpenGraphSiteName)) { _resourceManager.RegisterMeta(new MetaEntry { Property = "og:site_name", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphSiteName, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.OpenGraphAppId)) { _resourceManager.RegisterMeta(new MetaEntry { Property = "fb:app_id", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphAppId, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.OpenGraphLocale)) { _resourceManager.RegisterMeta(new MetaEntry { Property = "og:locale", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.OpenGraphLocale, shortCodeContext)) }); } // Twitter. if (!String.IsNullOrEmpty(aspect.TwitterCard)) { _resourceManager.RegisterMeta(new MetaEntry { Property = "twitter:card", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterCard, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.TwitterSite)) { _resourceManager.RegisterMeta(new MetaEntry { Property = "twitter:site", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterSite, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.TwitterTitle)) { _resourceManager.RegisterMeta(new MetaEntry { Name = "twitter:title", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterTitle, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.TwitterDescription)) { _resourceManager.RegisterMeta(new MetaEntry { Name = "twitter:description", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterDescription, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.TwitterImage)) { _resourceManager.RegisterMeta(new MetaEntry { Name = "twitter:image", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterImage, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.TwitterImageAlt)) { _resourceManager.RegisterMeta(new MetaEntry { Name = "twitter:image:alt", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterImageAlt, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.TwitterCreator)) { _resourceManager.RegisterMeta(new MetaEntry { Name = "twitter:creator", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterCreator, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.TwitterUrl)) { _resourceManager.RegisterMeta(new MetaEntry { Name = "twitter:url", Content = _htmlEncoder.Encode(await _shortcodeService.ProcessAsync(aspect.TwitterUrl, shortCodeContext)) }); } if (!String.IsNullOrEmpty(aspect.GoogleSchema)) { var json = await _shortcodeService.ProcessAsync(aspect.GoogleSchema, shortCodeContext); try { // Validate json format JsonDocument.Parse(json); } catch { json = "{ \"error\": \"Invalid JSON content in SEO settings\" }"; } _resourceManager.RegisterHeadScript(new HtmlString($"<script type=\"application/ld+json\">\n{json}\n</script>")); } return(null); }
private ValueTask <string> RenderAsync(string template, ContentItem contentItem) => _shortcodeService.ProcessAsync(template, new Context { ["ContentItem"] = contentItem });
public async Task <IActionResult> Submit(string formId) { var canView = ContentTypePermissionsHelper.CreateDynamicPermission(ContentTypePermissionsHelper.PermissionTemplates[CommonPermissions.ViewContent.Name], "VueForm"); if (!await _authorizationService.AuthorizeAsync(User, canView)) { return(NotFound()); } var form = await _contentManager.GetAsync(formId, VersionOptions.Published); if (form == null) { return(NotFound()); } var formPart = form.As <VueForm>(); if (formPart.Disabled.Value) { return(NotFound()); } if (!_contentPermissionsService.CanAccess(form)) { return(NotFound()); } var scriptingProvider = new VueFormMethodsProvider(form); var script = form.As <VueFormScripts>(); // This object holds the return value of the script object serverScriptResult = EvaluateScript(script?.OnValidation?.Text, scriptingProvider, formPart, "OnValidation"); // Return if any errors are returned in the OnValidation script if (ModelState.ErrorCount > 0) { return(Json(new VueFormSubmitResult(GetErrorDictionary(), serverScriptResult, GetDebugLogs(formPart)))); } serverScriptResult = EvaluateScript(script?.OnSubmitted?.Text, scriptingProvider, formPart, "OnSubmitted"); // Return if any errors are returned from the OnSubmitted script if (ModelState.ErrorCount > 0) { return(Json(new VueFormSubmitResult(GetErrorDictionary(), serverScriptResult, GetDebugLogs(formPart)))); } // _workflow manager is null if workflow feature is not enabled if (_workflowManager != null) { await _workflowManager.TriggerEventAsync(nameof(VueFormSubmittedEvent), input : new { VueForm = form }, correlationId : form.ContentItemId ); } // Return if any errors are returned from the Workflow if (ModelState.ErrorCount > 0) { return(Json(new VueFormSubmitResult(GetErrorDictionary(), serverScriptResult, GetDebugLogs(formPart)))); } // Handle the redirects with ajax requests. // 302 are equivalent to 301 in this case. No permanent redirect. // This can come from a scripting method or the HttpRedirect Workflow Task if (HttpContext.Response.StatusCode == 301 || HttpContext.Response.StatusCode == 302) { var returnValue = new { redirect = WebUtility.UrlDecode(HttpContext.Response.Headers["Location"]) }; HttpContext.Response.Clear(); return(Json(returnValue)); } // This get's set by either the workflow's HttpRedirectTask or HttpResponseTask if (HttpContext.Items[WorkflowHttpResult.Instance] != null) { // Let the HttpResponseTask control the response. This will fail on the client if it's anything other than json return(new EmptyResult()); } //try to get the message from the http context as set by the addSuccessMessage() scripting function var successMessage = string.Empty; if (HttpContext.Items[Constants.VueFormSuccessMessage] != null) { successMessage = (string)HttpContext.Items[Constants.VueFormSuccessMessage]; } else { if (!string.IsNullOrWhiteSpace(formPart.SuccessMessage?.Text)) { var formSuccessMessage = await _liquidTemplateManager.RenderStringAsync(formPart.SuccessMessage.Text, _htmlEncoder); successMessage = await _shortcodeService.ProcessAsync(formSuccessMessage); } } return(Json(new VueFormSubmitResult(successMessage, serverScriptResult, GetDebugLogs(formPart)))); }