private void PopulateSearchByDate(HtmlContext searchPage, FinaliseContext context)
        {
            var searchByDate  = context.MarkupContexts.OrderByDescending(c => c.PostedDate).ToList();
            var currentPeriod = searchByDate[0].PostedDate.ToString("MMMM yyyy");
            var lastPeriod    = currentPeriod;
            var sb            = new StringBuilder($"<h1>{currentPeriod}</h1>");

            foreach (var article in searchByDate)
            {
                Console.WriteLine($"\tInserting search entry for: {article.Title}");
                currentPeriod = article.PostedDate.ToString("MMMM yyyy");

                if (currentPeriod != lastPeriod)
                {
                    lastPeriod = currentPeriod;
                    sb.Append($"<h1>{currentPeriod}</h1>");
                }

                sb.Append(GetSearchCard(
                              article.Image.Url,
                              article.Image.Credit,
                              article.Image.Provider,
                              article.Title,
                              article.Slug,
                              article.GetPostedDateAsString(),
                              article.Html.Url.RelativeUrl
                              ));
            }

            searchPage.Content = searchPage.Content.Replace("$(search-by-post-date)", sb.ToString());
        }
        public override void Invoke(FinaliseContext context)
        {
            Console.WriteLine($"Building article navigations buttons");

            var articleMax = context.MarkupContexts.Count - 1;
            var markups    = context.MarkupContexts.OrderBy(a => a.PostedDate).ToList();

            for (var i = 0; i <= articleMax; i++)
            {
                var previousDisabled = i == 0 ? "disabled" : "";
                var previousPath     = i == 0 ? "#" : markups[i - 1].Html.Url.RelativeUrl;
                var nextDisabled     = i == articleMax ? "disabled" : "";
                var nextPath         = i == articleMax ? "#" : markups[i + 1].Html.Url.RelativeUrl;


                // Markups.Html context contains all the information we need to implement navigation buttons
                // However this context is read-only during finalise processing.
                // Instead we have to look up the Html context for the same file.
                context.HtmlContexts[markups[i].Html.Url.RelativeUrl].Content = markups[i].Html.Content
                                                                                .Replace("$(disable-previous-article-navigation)", previousDisabled)
                                                                                .Replace("$(previous-article-path)", previousPath)
                                                                                .Replace("$(disable-next-article-navigation)", nextDisabled)
                                                                                .Replace("$(next-article-path)", nextPath)
                ;
            }
        }
        public override void Invoke(FinaliseContext context)
        {
            Console.WriteLine("Generating article search page:");
            var searchPage = context.HtmlContexts[_searchUrl];

            PopulateSearchByDate(searchPage, context);
            PopulateSearchByTag(searchPage, context);
        }
        private void PopulateSearchByTag(HtmlContext searchPage, FinaliseContext context)
        {
            var searchTable = new StringBuilder();
            var searchList  = new StringBuilder();
            var searchByTag =
                from article in context.MarkupContexts
                from tag in article.Tags
                group article by new { tag.Value, tag.NakedValue } into articleTags
            orderby articleTags.Key.Value
                select new
            {
                Tag           = articleTags.Key.Value,
                TagId         = articleTags.Key.NakedValue,
                Articles      = articleTags.ToList(),
                ArticlesCount = articleTags.Sum(a => 1)
            }
            ;


            searchTable.Append("<div class=\"list-group\" style=\"max-width: 600px;\">");

            // To avoid iterating over the collection twice, we build the search table and the search list together.
            // The search table contains one row per tag and links to the various sections of the search list.
            // The search list appears below the search table and has tag per section.  Each section contains a series
            // of cards linking to the various articles with that tag.  Each article can appear in multiple sections.
            foreach (var tag in searchByTag)
            {
                Console.WriteLine($"\tInserting search entry for tag: {tag.Tag}");

                searchTable.Append(GetSearchTableRow(tag.TagId, tag.Tag, tag.ArticlesCount));

                searchList.Append($"<h3 id=\"{tag.TagId}\"><code>{tag.Tag}</code></h3>");
                foreach (var article in tag.Articles)
                {
                    searchList.Append(GetSearchCard(
                                          article.Image.Url,
                                          article.Image.Credit,
                                          article.Image.Provider,
                                          article.Title,
                                          article.Slug,
                                          article.GetPostedDateAsString(),
                                          article.Html.Url.RelativeUrl
                                          ));
                }
            }

            searchTable.Append("</div><hr>\n");
            searchTable.Append(searchList.ToString());

            searchPage.Content = searchPage.Content.Replace("$(search-by-tag)", searchTable.ToString());
        }
示例#5
0
        public override void Invoke(FinaliseContext context)
        {
            Console.WriteLine("Generating sitemaps page:");
            var sb = new StringBuilder();

            // Every .html page is added to the sitemaps file.
            foreach (var html in context.HtmlContexts.Values)
            {
                if (html.Path.EndsWith(".template.html"))
                {
                    continue;
                }

                var location     = $"https://david-rushton.dev{html.Url}";
                var lastModified = ExtractLastModified(html.Content);
                Console.WriteLine($"\tInserting entry: {html.Url}");

                sb.AppendLine(GetPageEntry(location, lastModified));
            }


            // Write sitemaps to file system
            WriteSitemaps(context.ScaffoldContext.SiteRoot, sb.ToString());


            string ExtractLastModified(string htmlContent)
            {
                var htmlDoc = new HtmlDocument();

                htmlDoc.LoadHtml(htmlContent);

                return(htmlDoc.DocumentNode
                       .SelectSingleNode("/html/head/meta[@name = \"date\"]")
                       .Attributes["content"].Value
                       ?? DateTime.Now.ToString("yyy-MM-dd")
                       );
            }

            void WriteSitemaps(string path, string urls)
            {
                var content      = GetSitemapsTemplate(urls);
                var sitemapsPath = Path.Join(path, "sitemaps.xml");

                File.WriteAllText(sitemapsPath, content);
            }
        }
示例#6
0
        public override void Invoke(FinaliseContext context)
        {
            var index    = context.HtmlContexts["/index.html"];
            var articles = context.MarkupContexts
                           .OrderByDescending(a => a.PostedDate)
                           .Take(5)
                           .Select((a, i) => new
            {
                a.Title,
                a.Author,
                a.PostedDate,
                a.Slug,
                Tags      = a.GetDelimitedTags(),
                IsNew     = a.AgeInDays <= context.ScaffoldContext.NewBadgeCutoffInDays,
                ImagePath = a.Image.Url,
                HtmlUrl   = a.Html.Url,
                Index     = i.ToString()
            })
                           .ToList()
            ;


            Console.WriteLine($"Generating index page: {index.Url}");
            index.Content = index.Content
                            .Replace("$(last-updated)", DateTime.Now.ToString("yyyy-MM-dd"))
                            .Replace("$(version-number)", context.ScaffoldContext.VersionNumber)
            ;

            foreach (var article in articles)
            {
                Console.WriteLine($"\tInserting article preview #{article.Index}: {article.Title}");
                index.Content = index.Content
                                .Replace($"$(article-title-{article.Index})", article.Title)
                                .Replace($"$(article-slug-{article.Index})", article.Slug)
                                .Replace($"$(article-tags-{article.Index})", article.Tags)
                                .Replace($"$(article-image-{article.Index})", article.ImagePath)
                                .Replace($"$(article-path-{article.Index})", article.HtmlUrl.RelativeUrl)
                                .Replace($"$(article-badge-{article.Index})", GetBadge(article.IsNew))
                ;
            }
        }
示例#7
0
 public abstract void Invoke(FinaliseContext context);