Ejemplo n.º 1
0
        public void should_convert_markdown_to_html()
        {
            var md = "**Hello World**";

            var html = MarkdownConverter.ToHtml(md);

            Assert.Equal("<p><strong>Hello World</strong></p>\n", html);
        }
Ejemplo n.º 2
0
 public static TopicViewModel CreateFrom(Topic topic, List <Reply> replies)
 {
     return(new TopicViewModel(topic)
     {
         HtmlContent = MarkdownConverter.ToHtml(topic.Content),
         Replies = replies
     });
 }
Ejemplo n.º 3
0
        public void Should_Convert_Markdown_To_Html_Correctly()
        {
            string markdown = GetStream("BetterCms.Test.Module.Contents.Markdown.markdown.txt");
            string html     = GetStream("BetterCms.Test.Module.Contents.Markdown.html.txt");

            var result = MarkdownConverter.ToHtml(markdown);

            result = ClearSpaces(result);
            html   = ClearSpaces(html);

            Assert.AreEqual(html, result);
        }
Ejemplo n.º 4
0
        public void should_convert_markdown_with_fenced_code_block()
        {
            var md = @"**Hello World**

```js
console.log('hello js');
```

text after code block";

            var html = MarkdownConverter.ToHtml(md);

            Assert.Equal("<p><strong>Hello World</strong></p>\n<pre><code class=\"language-js\">console.log('hello js');\n</code></pre>\n\n<p>text after code block</p>\n", html);
        }
Ejemplo n.º 5
0
        public async Task <IActionResult> Details(string id)
        {
            if (string.IsNullOrWhiteSpace(id))
            {
                return(NotFound());
            }
            var note = await _noteService.FindOne(id);

            if (note == null)
            {
                return(NotFound());
            }

            note.Content = _markdown.ToHtml(note.Content);
            return(View(note));
        }
Ejemplo n.º 6
0
        public void should_convert_markdown_with_fenced_code_block_and_unescape_code_content()
        {
            var md = @"**Hello World**

```html
&lt;html&gt;
&lt;title&gt;title text&lt;/title&gt;
&lt;/html&gt;
```

text after code block";

            var html = MarkdownConverter.ToHtml(md);

            Assert.Equal("<p><strong>Hello World</strong></p>\n<pre><code class=\"language-html\">&lt;html&gt;\n&lt;title&gt;title text&lt;/title&gt;\n&lt;/html&gt;\n</code></pre>\n\n<p>text after code block</p>\n", html);
        }
        public void ToHTml_EmptyMarkdown_Throws()
        {
            // Setup the test.
            string markdown = string.Empty;

            try
            {
                // Run the test.
                MarkdownConverter target = new MarkdownConverter();
                target.ToHtml(markdown);
            }
            catch (ArgumentException ex)
            {
                // Validate the results.
                Assert.AreEqual("markdown", ex.ParamName);
                throw;
            }
        }
Ejemplo n.º 8
0
        public void Should_Strip_Widget_Paragraphs_Correctly()
        {
            string before = @"<p><widget data-id=""AFA0AFEF-6D71-4962-9EF4-324BB9344F92"" data-assign-id=""FCBD3A46-4A77-4FC9-B9CE-9515C9D6AF77"">Header Logo</widget>    </p>
# {{CmsPageTitle}}
<p>      <widget data-id=""AFA0AFEF-6D71-4962-9EF4-324BB9344F92"" data-assign-id=""FCBD3A46-4A77-4FC9-B9CE-9515C9D6AF77"">Header Logo</widget>   test    </p>
<h1>{{CmsPageTitle}}</h1>
<p>      <widget data-id=""AFA0AFEF-6D71-4962-9EF4-324BB9344F92"" data-assign-id=""FCBD3A46-4A77-4FC9-B9CE-9515C9D6AF77"">Header Logo</widget>           </p>";

            string shouldBe = @"<widget data-id=""AFA0AFEF-6D71-4962-9EF4-324BB9344F92"" data-assign-id=""FCBD3A46-4A77-4FC9-B9CE-9515C9D6AF77"">Header Logo</widget>
<h1>{{CmsPageTitle}}</h1>
<p>      <widget data-id=""AFA0AFEF-6D71-4962-9EF4-324BB9344F92"" data-assign-id=""FCBD3A46-4A77-4FC9-B9CE-9515C9D6AF77"">Header Logo</widget>   test    </p>
<h1>{{CmsPageTitle}}</h1>
<widget data-id=""AFA0AFEF-6D71-4962-9EF4-324BB9344F92"" data-assign-id=""FCBD3A46-4A77-4FC9-B9CE-9515C9D6AF77"">Header Logo</widget>";

            var after = MarkdownConverter.ToHtml(before);

            after    = ClearSpaces(after);
            shouldBe = ClearSpaces(shouldBe);

            Assert.AreEqual(after, shouldBe);
        }
        public void ToHTml_ValidMarkdown_Success()
        {
            //// TODO: Setup the test to cover all markdown syntax features.

            // Setup the test.
            string markdown =
                @"# Heading1
            
A paragraph with **bold** and *italic* text.";

            string expectedHtml =
                @"<h1>Heading1</h1>
<p>A paragraph with <strong>bold</strong> and <em>italic</em> text.</p>";

            // Run the test.
            MarkdownConverter target = new MarkdownConverter();
            string            result = target.ToHtml(markdown);

            // Validate the results.
            Assert.AreEqual(expectedHtml, result);
        }
Ejemplo n.º 10
0
        public IDictionary <string, object> ToDictionary(Config.Config config)
        {
            string languagePrefix = config.MultipleLanguages switch
            {
                true => Language,
                false => ""
            };

            // This is the "presentation layer" for this model object. The field names below are what the .hbs
            // templates will see.
            return(new Dictionary <string, object>
            {
                { "title", Title },
                { "date", Date.ToString("MMM d, yyyy") },
                { "date_iso", Date.ToString("yyyy-MM-dd") },
                { "body", MarkdownConverter.ToHtml(Body, LineBreaks ?? config.LineBreaks) },
                { "excerpt", MarkdownConverter.ToHtml(Excerpt, LineBreaks ?? config.LineBreaks) },
                { "language", Language },

                {
                    "link", Path.Join(
                        "/",
                        languagePrefix,
                        Slugify(Categories.First()),
                        Date.Year.ToString(),
                        Date.Month.ToString(),
                        Date.Day.ToString(),
                        Slugify(Title)
                        )
                },

                {
                    "categories", Categories.Select(c => new Dictionary <string, string>
                    {
                        { "name", c },
                        { "slug", Path.Join(languagePrefix, Slugify(c)) }
                    })
                }
            });
        }
        public ChangedContentResultViewModel Execute(SavePageHtmlContentCommandRequest request)
        {
            var model = request.Content;

            if (model.DesirableStatus == ContentStatus.Published)
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.PublishContent);
            }

            if (model.Id == default(Guid) || model.DesirableStatus != ContentStatus.Published)
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.EditContent);
            }

            PageContent pageContent;
            var         isNew = model.Id.HasDefaultValue();

            if (!isNew)
            {
                var query = Repository
                            .AsQueryable <PageContent>()
                            .Where(f => f.Id == model.Id && !f.IsDeleted)
                            .AsQueryable();

                if (!model.IsUserConfirmed)
                {
                    query = query.Fetch(f => f.Page);
                }

                if (configuration.Security.AccessControlEnabled)
                {
                    query = query.Fetch(f => f.Page).ThenFetchMany(f => f.AccessRules);
                }

                pageContent = query.ToList().FirstOne();

                // Check if user has confirmed the deletion of content
                if (!model.IsUserConfirmed && pageContent.Page.IsMasterPage)
                {
                    contentService.CheckIfContentHasDeletingChildrenWithException(model.PageId, model.ContentId, model.PageContent);
                }
            }
            else
            {
                pageContent       = new PageContent();
                pageContent.Order = contentService.GetPageContentNextOrderNumber(model.PageId, model.ParentPageContentId);

                if (configuration.Security.AccessControlEnabled)
                {
                    pageContent.Page = Repository
                                       .AsQueryable <Root.Models.Page>(p => p.Id == model.PageId)
                                       .FetchMany(p => p.AccessRules)
                                       .ToList()
                                       .FirstOne();
                }
            }

            // Demand access
            if (configuration.Security.AccessControlEnabled)
            {
                AccessControlService.DemandAccess(pageContent.Page, Context.Principal, AccessLevel.ReadWrite);
            }

            // Get page as proxy, if page is not retrieved yet
            if (!configuration.Security.AccessControlEnabled)
            {
                pageContent.Page = Repository.AsProxy <Root.Models.Page>(model.PageId);
            }
            pageContent.Region = Repository.AsProxy <Region>(model.RegionId);
            if (!model.ParentPageContentId.HasDefaultValue())
            {
                pageContent.Parent = Repository.AsProxy <PageContent>(model.ParentPageContentId);
            }
            else
            {
                pageContent.Parent = null;
            }

            var contentToSave = new HtmlContent
            {
                Id               = model.ContentId,
                ActivationDate   = model.LiveFrom,
                ExpirationDate   = TimeHelper.FormatEndDate(model.LiveTo),
                Name             = model.ContentName,
                Html             = model.PageContent ?? string.Empty,
                UseCustomCss     = model.EnabledCustomCss,
                CustomCss        = model.CustomCss,
                UseCustomJs      = model.EnabledCustomJs,
                CustomJs         = model.CustomJs,
                EditInSourceMode = model.EditInSourceMode,
                ContentTextMode  = ContentTextMode.Html
            };

            if (model.ContentTextMode == ContentTextMode.Markdown)
            {
                if (!string.IsNullOrWhiteSpace(model.PageContent))
                {
                    contentToSave.Html = MarkdownConverter.ToHtml(model.PageContent);
                }
                else
                {
                    contentToSave.Html = string.Empty;
                }
                contentToSave.ContentTextMode = ContentTextMode.Markdown;
                contentToSave.OriginalText    = model.PageContent;
            }

            if (model.ContentTextMode == ContentTextMode.SimpleText)
            {
                if (!string.IsNullOrWhiteSpace(model.PageContent))
                {
                    contentToSave.Html = HttpUtility.HtmlEncode(model.PageContent);
                }
                else
                {
                    contentToSave.Html = string.Empty;
                }
                contentToSave.ContentTextMode = ContentTextMode.SimpleText;
                contentToSave.OriginalText    = model.PageContent;
            }

            // Preserve content if user is not authorized to change it.
            if (!SecurityService.IsAuthorized(RootModuleConstants.UserRoles.EditContent) && model.Id != default(Guid))
            {
                var originalContent  = Repository.First <HtmlContent>(model.ContentId);
                var contentToPublish = (HtmlContent)(originalContent.History != null
                    ? originalContent.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) ?? originalContent
                    : originalContent);

                contentToSave.Name             = contentToPublish.Name;
                contentToSave.Html             = contentToPublish.Html;
                contentToSave.UseCustomCss     = contentToPublish.UseCustomCss;
                contentToSave.CustomCss        = contentToPublish.CustomCss;
                contentToSave.UseCustomJs      = contentToPublish.UseCustomJs;
                contentToSave.CustomJs         = contentToPublish.CustomJs;
                contentToSave.EditInSourceMode = contentToPublish.EditInSourceMode;
            }

            UnitOfWork.BeginTransaction();
            pageContent.Content = contentService.SaveContentWithStatusUpdate(
                contentToSave,
                model.DesirableStatus);
            optionsService.SaveChildContentOptions(pageContent.Content, request.ChildContentOptionValues, model.DesirableStatus);

            if (pageContent.Content.ContentRegions != null &&
                pageContent.Content.ContentRegions.Count > 0)
            {
                if (!pageContent.Page.IsMasterPage)
                {
                    var logMessage = string.Format("Dynamic regions are not allowed. Page: {0}, Content: {1}", pageContent.Page, pageContent.Id);
                    throw new ValidationException(() => PagesGlobalization.SaveContent_DynamicRegionsAreNotAllowed_Message, logMessage);
                }
            }

            Repository.Save(pageContent);
            UnitOfWork.Commit();

            // Notify.
            if (model.DesirableStatus != ContentStatus.Preview)
            {
                if (isNew)
                {
                    Events.PageEvents.Instance.OnHtmlContentCreated((HtmlContent)pageContent.Content);
                    Events.PageEvents.Instance.OnPageContentInserted(pageContent);
                }
                else
                {
                    Events.PageEvents.Instance.OnHtmlContentUpdated((HtmlContent)pageContent.Content);
                }
            }

            var contentData = (pageContent.Content.History != null
                    ? pageContent.Content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) ?? pageContent.Content
                    : pageContent.Content);

            var response = new ChangedContentResultViewModel
            {
                PageContentId      = pageContent.Id,
                ContentId          = contentData.Id,
                RegionId           = pageContent.Region.Id,
                PageId             = pageContent.Page.Id,
                DesirableStatus    = request.Content.DesirableStatus,
                Title              = contentData.Name,
                ContentVersion     = contentData.Version,
                PageContentVersion = pageContent.Version,
                ContentType        = HtmlContentAccessor.ContentWrapperType
            };

            if (request.Content.IncludeChildRegions)
            {
                response.Regions = widgetService.GetWidgetChildRegionViewModels(contentData);
            }

            return(response);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Saves the blog post.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="childContentOptionValues">The child content option values.</param>
        /// <param name="principal">The principal.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <param name="updateActivationIfNotChanged">if set to <c>true</c> update activation time even if it was not changed.</param>
        /// <returns>
        /// Saved blog post entity
        /// </returns>
        /// <exception cref="System.ComponentModel.DataAnnotations.ValidationException"></exception>
        /// <exception cref="SecurityException">Forbidden: Access is denied.</exception>
        public BlogPost SaveBlogPost(BlogPostViewModel request, IList <ContentOptionValuesViewModel> childContentOptionValues, IPrincipal principal, out string[] errorMessages, bool updateActivationIfNotChanged = true)
        {
            errorMessages = new string[0];
            string[] roles;
            if (request.DesirableStatus == ContentStatus.Published)
            {
                accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.PublishContent);
                roles = new[] { RootModuleConstants.UserRoles.PublishContent };
            }
            else
            {
                accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.EditContent);
                roles = new[] { RootModuleConstants.UserRoles.EditContent };
            }

            var isNew       = request.Id.HasDefaultValue();
            var userCanEdit = securityService.IsAuthorized(RootModuleConstants.UserRoles.EditContent);

            ValidateData(isNew, request);

            BlogPost        blogPost;
            BlogPostContent content;
            PageContent     pageContent;

            GetBlogPostAndContentEntities(request, principal, roles, ref isNew, out content, out pageContent, out blogPost);
            var beforeChange = new UpdatingBlogModel(blogPost);

            // Master page / layout
            Layout layout;
            Page   masterPage;
            Region region;

            LoadDefaultLayoutAndRegion(out layout, out masterPage, out region);

            if (masterPage != null)
            {
                var level = accessControlService.GetAccessLevel(masterPage, principal);
                if (level < AccessLevel.Read)
                {
                    var          message    = BlogGlobalization.SaveBlogPost_FailedToSave_InaccessibleMasterPage;
                    const string logMessage = "Failed to save blog post. Selected template for page layout is inaccessible.";
                    throw new ValidationException(() => message, logMessage);
                }
            }

            if (pageContent.Region == null)
            {
                pageContent.Region = region;
            }

            // Load master pages for updating page's master path and page's children master path
            IList <Guid>       newMasterIds;
            IList <Guid>       oldMasterIds;
            IList <Guid>       childrenPageIds;
            IList <MasterPage> existingChildrenMasterPages;

            PrepareForUpdateChildrenMasterPages(isNew, blogPost, request, out newMasterIds, out oldMasterIds, out childrenPageIds, out existingChildrenMasterPages);

            // TODO: TEST AND TRY TO FIX IT: TRANSACTION HERE IS REQUIRED!
            // UnitOfWork.BeginTransaction(); // NOTE: this causes concurrent data exception.

            Redirect redirectCreated = null;

            if (!isNew && userCanEdit && !string.Equals(blogPost.PageUrl, request.BlogUrl) && !string.IsNullOrWhiteSpace(request.BlogUrl))
            {
                request.BlogUrl = urlService.FixUrl(request.BlogUrl);
                pageService.ValidatePageUrl(request.BlogUrl, request.Id);
                if (request.RedirectFromOldUrl)
                {
                    var redirect = redirectService.CreateRedirectEntity(blogPost.PageUrl, request.BlogUrl);
                    if (redirect != null)
                    {
                        repository.Save(redirect);
                        redirectCreated = redirect;
                    }
                }

                blogPost.PageUrl = urlService.FixUrl(request.BlogUrl);
            }

            // Push to change modified data each time.
            blogPost.ModifiedOn = DateTime.Now;

            if (userCanEdit)
            {
                blogPost.Title       = request.Title;
                blogPost.Description = request.IntroText;
                blogPost.Author      = request.AuthorId.HasValue ? repository.AsProxy <Author>(request.AuthorId.Value) : null;

                blogPost.Image = (request.Image != null && request.Image.ImageId.HasValue) ? repository.AsProxy <MediaImage>(request.Image.ImageId.Value) : null;
                if (isNew || request.DesirableStatus == ContentStatus.Published)
                {
                    if (updateActivationIfNotChanged)
                    {
                        blogPost.ActivationDate = request.LiveFromDate;
                        blogPost.ExpirationDate = TimeHelper.FormatEndDate(request.LiveToDate);
                    }
                    else
                    {
                        blogPost.ActivationDate = TimeHelper.GetFirstIfTheSameDay(blogPost.ActivationDate, request.LiveFromDate);
                        blogPost.ExpirationDate = TimeHelper.GetFirstIfTheSameDay(blogPost.ExpirationDate, TimeHelper.FormatEndDate(request.LiveToDate));
                    }
                }
            }

            if (isNew)
            {
                if (!string.IsNullOrWhiteSpace(request.BlogUrl))
                {
                    blogPost.PageUrl = urlService.FixUrl(request.BlogUrl);
                    pageService.ValidatePageUrl(blogPost.PageUrl);
                }
                else
                {
                    blogPost.PageUrl = CreateBlogPermalink(request.Title, null, request.Categories != null ? request.Categories.Select(c => Guid.Parse(c.Key)) : null);
                }

                blogPost.MetaTitle = request.MetaTitle ?? request.Title;
                if (masterPage != null)
                {
                    blogPost.MasterPage = masterPage;
                    masterPageService.SetPageMasterPages(blogPost, masterPage.Id);
                }
                else
                {
                    blogPost.Layout = layout;
                }
                UpdateStatus(blogPost, request.DesirableStatus);
                AddDefaultAccessRules(blogPost, principal, masterPage);
            }
            else if (request.DesirableStatus == ContentStatus.Published ||
                     blogPost.Status == PageStatus.Preview)
            {
                // Update only if publishing or current status is preview.
                // Else do not change, because it may change from published to draft status
                UpdateStatus(blogPost, request.DesirableStatus);
            }

            // Create content.
            var newContent = new BlogPostContent
            {
                Id               = content != null ? content.Id : Guid.Empty,
                Name             = request.Title,
                Html             = request.Content ?? string.Empty,
                OriginalText     = request.OriginalText,
                EditInSourceMode = request.EditInSourceMode,
                ActivationDate   = request.LiveFromDate,
                ExpirationDate   = TimeHelper.FormatEndDate(request.LiveToDate),
                ContentTextMode  = request.ContentTextMode,
            };

            if (!updateActivationIfNotChanged && content != null)
            {
                newContent.ActivationDate = TimeHelper.GetFirstIfTheSameDay(content.ActivationDate, newContent.ActivationDate);
                newContent.ExpirationDate = TimeHelper.GetFirstIfTheSameDay(content.ExpirationDate, newContent.ExpirationDate);
            }

            if (request.ContentTextMode == ContentTextMode.Markdown &&
                request.Content == null &&
                request.OriginalText != null)
            {
                newContent.Html = MarkdownConverter.ToHtml(request.OriginalText);
            }

            // Preserve content if user is not authorized to change it.
            if (!userCanEdit)
            {
                if (content == null)
                {
                    throw new SecurityException("Forbidden: Access is denied."); // User has no rights to create new content.
                }

                var contentToPublish = (BlogPostContent)(content.History != null
                    ? content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) ?? content
                    : content);

                newContent.Name            = contentToPublish.Name;
                newContent.Html            = contentToPublish.Html;
                newContent.ContentTextMode = contentToPublish.ContentTextMode;
                newContent.OriginalText    = contentToPublish.OriginalText;
            }

            content             = SaveContentWithStatusUpdate(isNew, newContent, request, principal);
            pageContent.Content = content;
            optionService.SaveChildContentOptions(content, childContentOptionValues, request.DesirableStatus);

            blogPost.PageUrlHash     = blogPost.PageUrl.UrlHash();
            blogPost.UseCanonicalUrl = request.UseCanonicalUrl;

            MapExtraProperties(isNew, blogPost, content, pageContent, request, principal);

            // Notify about page properties changing.
            var cancelEventArgs = Events.BlogEvents.Instance.OnBlogChanging(beforeChange, new UpdatingBlogModel(blogPost));

            if (cancelEventArgs.Cancel)
            {
                errorMessages = cancelEventArgs.CancellationErrorMessages.ToArray();
                return(null);
            }

            if (isNew || userCanEdit)
            {
                categoryService.CombineEntityCategories <BlogPost, PageCategory>(blogPost, request.Categories);
            }

            var oldLanguageId = blogPost.Language != null ? blogPost.Language.Id : (Guid?)null;
            var newLanguageId = request.LanguageId;

            if (oldLanguageId != newLanguageId)
            {
                blogPost.Language = request.LanguageId.HasValue ? repository.AsProxy <Language>(request.LanguageId.Value) : null;
            }

            repository.Save(blogPost);
            repository.Save(content);
            repository.Save(pageContent);

            masterPageService.UpdateChildrenMasterPages(existingChildrenMasterPages, oldMasterIds, newMasterIds, childrenPageIds);

            pageContent.Content   = content;
            blogPost.PageContents = new [] { pageContent };

            IList <Tag> newTags = null;

            if (userCanEdit)
            {
                newTags = SaveTags(blogPost, request);
            }

            if (userCanEdit && ConfigurationHelper.IsFillSeoDataFromArticlePropertiesEnabled(configuration))
            {
                FillMetaInfo(blogPost);
            }

            // Commit
            unitOfWork.Commit();

            // Notify about new created tags.
            Events.RootEvents.Instance.OnTagCreated(newTags);

            // Notify about new or updated blog post.
            if (isNew)
            {
                Events.BlogEvents.Instance.OnBlogCreated(blogPost);
            }
            else
            {
                Events.BlogEvents.Instance.OnBlogUpdated(blogPost);
            }

            // Notify about redirect creation.
            if (redirectCreated != null)
            {
                Events.PageEvents.Instance.OnRedirectCreated(redirectCreated);
            }

            return(blogPost);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Puts the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>
        ///   <c>PutHtmlContentResponse</c> with html content id.
        /// </returns>
        public PutHtmlContentResponse Put(PutHtmlContentRequest request)
        {
            var isNew = !request.Id.HasValue || request.Id.Value.HasDefaultValue();

            Module.Pages.Models.HtmlContent originalContent = null;
            if (!isNew)
            {
                originalContent = repository.FirstOrDefault <Module.Pages.Models.HtmlContent>(request.Id.Value);
                isNew           = originalContent == null;
            }

            var contentToSave = new Module.Pages.Models.HtmlContent
            {
                Id              = request.Id.GetValueOrDefault(),
                ActivationDate  = request.Data.ActivationDate,
                ExpirationDate  = TimeHelper.FormatEndDate(request.Data.ExpirationDate),
                Name            = request.Data.Name,
                Html            = request.Data.Html ?? string.Empty,
                OriginalText    = request.Data.OriginalText ?? string.Empty,
                ContentTextMode = (Module.Pages.Models.Enums.ContentTextMode)request.Data.ContentTextMode,
                UseCustomCss    = request.Data.UseCustomCss,
                CustomCss       = request.Data.CustomCss,
                UseCustomJs     = request.Data.UseCustomJavaScript,
                CustomJs        = request.Data.CustomJavaScript
            };

            if (request.Data.ContentTextMode == ContentTextMode.Markdown &&
                request.Data.Html == null &&
                request.Data.OriginalText != null)
            {
                contentToSave.Html = MarkdownConverter.ToHtml(request.Data.OriginalText);
            }

            if (request.Data.ContentTextMode == ContentTextMode.SimpleText &&
                request.Data.Html == null &&
                request.Data.OriginalText != null)
            {
                contentToSave.Html = HttpUtility.HtmlEncode(request.Data.OriginalText);
            }

            if (request.Data.IsPublished)
            {
                if (isNew)
                {
                    if (request.Data.PublishedOn.HasValue)
                    {
                        contentToSave.PublishedOn = request.Data.PublishedOn;
                    }
                    if (!string.IsNullOrEmpty(request.Data.PublishedByUser))
                    {
                        contentToSave.PublishedByUser = request.Data.PublishedByUser;
                    }
                }
                else
                {
                    contentToSave.PublishedOn     = originalContent.PublishedOn;
                    contentToSave.PublishedByUser = originalContent.PublishedByUser;
                }
            }

            unitOfWork.BeginTransaction();

            Module.Pages.Models.HtmlContent content;
            var desirableStatus = request.Data.IsPublished ? ContentStatus.Published : ContentStatus.Draft;

            if (isNew && contentToSave.Id != default(Guid))
            {
                content = contentToSave;
                contentService.UpdateDynamicContainer(content);

                content.Status = desirableStatus;
                content.Id     = contentToSave.Id;

                repository.Save(content);
            }
            else
            {
                if (request.Data.Version > 0)
                {
                    contentToSave.Version = request.Data.Version;
                }

                content = (Module.Pages.Models.HtmlContent)contentService
                          .SaveContentWithStatusUpdate(contentToSave, desirableStatus);
            }
            var childContentOptionValues = request.Data.ChildContentsOptionValues != null?request.Data.ChildContentsOptionValues.ToViewModel() : null;

            optionService.SaveChildContentOptions(content, childContentOptionValues, desirableStatus);

            unitOfWork.Commit();

            if (isNew)
            {
                Events.PageEvents.Instance.OnHtmlContentCreated(content);
            }
            else
            {
                Events.PageEvents.Instance.OnHtmlContentUpdated(content);
            }

            return(new PutHtmlContentResponse
            {
                Data = content.Id
            });
        }