예제 #1
0
        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 ?? "");
            }
        }
예제 #3
0
        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;
                }
            }));
        }
예제 #4
0
        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;
                }
            }));
        }
예제 #5
0
        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
            });
        }
예제 #6
0
        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"));
        }
예제 #7
0
        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);
        }
예제 #8
0
 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))));
        }