Esempio n. 1
0
        private static async Task GetFavoriteIconAsync(Settings settings, TemplatingOptions options)
        {
            var iconUrl = settings.Icon;

            if (string.IsNullOrWhiteSpace(settings.Icon))
            {
                iconUrl = "favicon.ico";
            }
            var httpClient = new HttpClient();
            var response   = await httpClient.GetAsync(new Uri(options.GhostUrl, iconUrl.Replace(settings.Url, string.Empty)));

            if (response.IsSuccessStatusCode)
            {
                var iconBytes = await response.Content.ReadAsByteArrayAsync();

                var path = iconUrl.Replace(settings.Url, string.Empty);
                path = Path.Combine(options.OutputDirectory, path);
                var fileInfo  = new System.IO.FileInfo(path);
                var directory = fileInfo.Directory;
                if (!directory.Exists)
                {
                    directory.Create();
                }
                File.WriteAllBytes(path, iconBytes);
            }
        }
Esempio n. 2
0
        private static async Task HandlePostAsync(Post post, Settings settings, TemplatingOptions options, IServiceProvider services, IRazorViewEngine engine, string type)
        {
            var httpContext = new DefaultHttpContext {
                RequestServices = services
            };
            var routeData             = new RouteData();
            var actionDescriptor      = new ActionDescriptor();
            var modelStateDictionary  = new ModelStateDictionary();
            var modelMetadataProvider = new EmptyModelMetadataProvider();
            var tempDataProvider      = new VirtualTempDataProvider();
            var htmlHelperOptions     = new HtmlHelperOptions();

            var actionContext      = new ActionContext(httpContext, routeData, actionDescriptor, modelStateDictionary);
            var viewDataDictionary = new ViewDataDictionary(modelMetadataProvider, modelStateDictionary);
            var tempDataDictionary = new TempDataDictionary(httpContext, tempDataProvider);

            viewDataDictionary.Model = post;

            using (var stringWriter = new StringWriter())
            {
                var view        = engine.GetView(".", $"/Templates/{type}.cshtml", true);
                var viewContext = new ViewContext(actionContext, view.View, viewDataDictionary, tempDataDictionary, stringWriter, htmlHelperOptions);

                await view.View.RenderAsync(viewContext);

                var result    = stringWriter.ToString();
                var directory = Path.Combine(options.OutputDirectory, post.Slug);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                File.WriteAllText(Path.Combine(directory, "index.html"), result);
                await DownloadImagesFromPostAsync(post.HTML, settings, options);

                if (type == "post")
                {
                    //amp it
                    view        = engine.GetView(".", $"/Templates/post-amp.cshtml", true);
                    viewContext = new ViewContext(actionContext, view.View, viewDataDictionary, tempDataDictionary, stringWriter, htmlHelperOptions);

                    await view.View.RenderAsync(viewContext);

                    result    = stringWriter.ToString();
                    directory = Path.Combine(directory, "amp");
                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }

                    File.WriteAllText(Path.Combine(directory, "index.html"), result);
                }
            }
        }
Esempio n. 3
0
        private static void BuildSitemap(Page[] pages, Post[] posts, Author[] authors, Tag[] tags, Settings settings, TemplatingOptions options)
        {
            //build the index that ties the maps together
            var siteIndex = new Sitemap.sitemapindex
            {
                sitemap = GetArray(
                    new Sitemap.tSitemap {
                    lastmod = DateTime.UtcNow.ToString("O"), loc = settings.Url + "sitemaps/pages.xml"
                },
                    new Sitemap.tSitemap {
                    lastmod = DateTime.UtcNow.ToString("O"), loc = settings.Url + "sitemaps/posts.xml"
                },
                    new Sitemap.tSitemap {
                    lastmod = DateTime.UtcNow.ToString("O"), loc = settings.Url + "sitemaps/authors.xml"
                },
                    new Sitemap.tSitemap {
                    lastmod = DateTime.UtcNow.ToString("O"), loc = settings.Url + "sitemaps/tags.xml"
                })
            };

            File.WriteAllBytes(Path.Combine(options.OutputDirectory, "sitemap.xml"), XmlSerialize(siteIndex));
            var sitemapDirectory = Path.Combine(options.OutputDirectory, "sitemaps");

            if (!Directory.Exists(sitemapDirectory))
            {
                Directory.CreateDirectory(sitemapDirectory);
            }

            var map = new Sitemap.urlset
            {
                url = pages.Select(page => new Sitemap.tUrl
                {
                    changefreq          = Sitemap.tChangeFreq.daily,
                    changefreqSpecified = true,
                    lastmod             = page.UpdatedAt.ToString("O"),
                    loc = settings.Url + page.Slug + "/"
                }).ToArray()
            };

            File.WriteAllBytes(Path.Combine(sitemapDirectory, "pages.xml"), XmlSerialize(map));

            map = new Sitemap.urlset
            {
                url = posts.Select(post => new Sitemap.tUrl
                {
                    changefreq          = Sitemap.tChangeFreq.daily,
                    changefreqSpecified = true,
                    lastmod             = post.UpdatedAt.ToString("O"),
                    loc = settings.Url + post.Slug + "/"
                }).ToArray()
            };
            File.WriteAllBytes(Path.Combine(sitemapDirectory, "posts.xml"), XmlSerialize(map));

            map = new Sitemap.urlset
            {
                url = authors.Select(author => new Sitemap.tUrl
                {
                    changefreq          = Sitemap.tChangeFreq.daily,
                    changefreqSpecified = true,
                    lastmod             = DateTime.UtcNow.ToString("O"),
                    loc = settings.Url + "authors/" + author.Slug + "/"
                }).ToArray()
            };
            File.WriteAllBytes(Path.Combine(sitemapDirectory, "authors.xml"), XmlSerialize(map));

            map = new Sitemap.urlset
            {
                url = tags.Select(tag => new Sitemap.tUrl
                {
                    changefreq          = Sitemap.tChangeFreq.daily,
                    changefreqSpecified = true,
                    lastmod             = DateTime.UtcNow.ToString("O"),
                    loc = settings.Url + "tag/" + tag.Slug + "/"
                }).ToArray()
            };
            File.WriteAllBytes(Path.Combine(sitemapDirectory, "tags.xml"), XmlSerialize(map));
        }
Esempio n. 4
0
        private static void BuildRssFeed(Post[] posts, Author[] authors, Tag[] tags, Settings settings, TemplatingOptions options, IServiceProvider services, IRazorViewEngine engine)
        {
            var targetDirectory = Path.Combine(options.OutputDirectory, "rss");

            if (!Directory.Exists(targetDirectory))
            {
                Directory.CreateDirectory(targetDirectory);
            }

            var oldestPost = DateTime.Now.AddMonths(-6);
            var items      = new List <RssFeed.Item>();

            foreach (var post in posts.Where(x => x.PublishedAt > oldestPost))
            {
                var item = new RssFeed.Item();
                item.Authors = post.Authors.Select(author => new RssFeed.ItemAuthor {
                    Name = author.Name, Uri = settings.Url + "author/" + author.Slug
                }).ToArray();
                item.Categories  = post.Tags.Select(tag => tag.Name).ToArray();
                item.Content     = post.HTML;
                item.Creator     = post.PrimaryAuthor.Name;
                item.Description = post.MetaDescription ?? post.CustomExcerpt ?? post.Excerpt;
                item.Guid        = new RssFeed.ItemGuid {
                    Value = post.UUID
                };
                item.Link          = post.Settings.Url + post.Slug + "/";
                item.PublishedDate = post.PublishedAt.Value.ToString("R");
                item.Title         = post.Title;

                items.Add(item);
            }

            var feed    = new RssFeed.Feed();
            var channel = new RssFeed.Channel();

            channel.AtomLink = new RssFeed.AtomLink
            {
                HRef         = options.RssFeed,
                Relationship = "self",
                Type         = "application/rss+xml"
            };
            channel.Categories   = tags.Select(tag => tag.Name).ToArray();
            channel.Contributors = authors.Select(author => new RssFeed.Contributor {
                Name = author.Name, Uri = settings.Url + "author/" + author.Slug + "/"
            }).ToArray();
            channel.Copyright   = options.FormattedCopyright;
            channel.Description = settings.Description;
            channel.Generator   = options.GeneratorName;
            channel.Image       = new RssFeed.Image {
                Link = settings.Url, Title = settings.Title, Url = settings.Url + "favicon.png"
            };
            channel.Items         = items.ToArray();
            channel.LastBuildDate = DateTime.UtcNow.ToString("R");
            channel.Link          = settings.Url;
            channel.Title         = settings.Title;
            channel.TTL           = 60;

            feed.Channels = new[] { channel };
            feed.Version  = "2.0";

            using var memoryStream = new MemoryStream();
            using var xmlWriter    = XmlWriter.Create(memoryStream, new XmlWriterSettings
            {
                Indent = true,
            });

            var namespaces = new XmlSerializerNamespaces();

            namespaces.Add("dc", "http://purl.org/dc/elements/1.1/");
            namespaces.Add("content", "http://purl.org/rss/1.0/modules/content/");
            namespaces.Add("atom", "http://www.w3.org/2005/Atom");
            namespaces.Add("media", "http://search.yahoo.com/mrss/");

            var serializer = new XmlSerializer(typeof(RssFeed.Feed));

            serializer.Serialize(xmlWriter, feed, namespaces);
            xmlWriter.Flush();
            File.WriteAllBytes(Path.Combine(targetDirectory, "index.html"), memoryStream.ToArray());
        }
Esempio n. 5
0
        private static async Task DownloadImagesFromPostAsync(string post, Settings settings, TemplatingOptions options)
        {
            //this straight sucks
            var imageRegex = new Regex("<img.+?>");
            var tagMatches = imageRegex.Matches(post);

            if (tagMatches.Count > 0)
            {
                foreach (Match tagMatch in tagMatches)
                {
                    var quoteRegex   = new Regex("\".+?\"");
                    var quoteMatches = quoteRegex.Matches(tagMatch.Value);
                    foreach (Match quoteMatch in quoteMatches)
                    {
                        var splits = quoteMatch.Value.Split(' ');
                        foreach (var split in splits)
                        {
                            var item = split.Trim('\"');
                            if (item.StartsWith(settings.Url))
                            {
                                //we have an image, download it.
                                var imageResult = await _imageClient.GetAsync(new Uri(options.GhostUrl, item.Replace(settings.Url, "")));

                                if (imageResult.IsSuccessStatusCode)
                                {
                                    var filePath             = item.Replace(settings.Url, string.Empty);
                                    var destinationFile      = Path.Combine(options.OutputDirectory, filePath);
                                    var destination          = new System.IO.FileInfo(destinationFile);
                                    var destinationDirectory = destination.Directory.FullName;
                                    if (!Directory.Exists(destinationDirectory))
                                    {
                                        Directory.CreateDirectory(destinationDirectory);
                                    }
                                    var image = await imageResult.Content.ReadAsByteArrayAsync();

                                    if (File.Exists(destinationFile))
                                    {
                                        File.Delete(destinationFile);
                                    }
                                    File.WriteAllBytes(destinationFile, image);
                                }
                            }
                        }
                    }
                }
            }
        }
Esempio n. 6
0
        private static async Task HandleIndexPageAsync(Post[] posts, Settings settings, TemplatingOptions options, IServiceProvider services, IRazorViewEngine engine)
        {
            var postsToDisplay = 27;
            var httpContext    = new DefaultHttpContext {
                RequestServices = services
            };
            var routeData             = new RouteData();
            var actionDescriptor      = new ActionDescriptor();
            var modelStateDictionary  = new ModelStateDictionary();
            var modelMetadataProvider = new EmptyModelMetadataProvider();
            var tempDataProvider      = new VirtualTempDataProvider();
            var htmlHelperOptions     = new HtmlHelperOptions();
            var actionContext         = new ActionContext(httpContext, routeData, actionDescriptor, modelStateDictionary);
            var viewDataDictionary    = new ViewDataDictionary(modelMetadataProvider, modelStateDictionary);
            var tempDataDictionary    = new TempDataDictionary(httpContext, tempDataProvider);
            var imageDirectory        = Path.Combine(options.OutputDirectory, "content", "images", "index");
            var index = new IndexPage
            {
                Options  = options,
                Settings = settings
            };

            posts = posts.OrderByDescending(x => x.PublishedAt).ToArray();

            if (!Directory.Exists(imageDirectory))
            {
                Directory.CreateDirectory(imageDirectory);
            }

            if (!string.IsNullOrWhiteSpace(settings.CoverImage))
            {
                using var client = new HttpClient();
                var imageResult = await client.GetAsync(new Uri(options.GhostUrl, settings.CoverImage));

                if (imageResult.IsSuccessStatusCode)
                {
                    using var imageStream = await imageResult.Content.ReadAsStreamAsync();

                    using var memoryStream = new MemoryStream();
                    await imageStream.CopyToAsync(memoryStream);

                    var widths = new[] { 600, 1000, 2000 };
                    foreach (var width in widths)
                    {
                        memoryStream.Position = 0;
                        using var image       = await Image.LoadAsync(memoryStream);

                        index.ImageHeight = image.Height;
                        index.ImageWidth  = image.Width;

                        image.Mutate(context => context.Resize(width, 0));
                        await image.SaveAsPngAsync(Path.Combine(imageDirectory, width + ".png"));
                    }
                }
            }

            viewDataDictionary.Model = index;

            var batch = 1;

            while (posts.Length > 0)
            {
                var directory = options.OutputDirectory;

                if (batch > 1)
                {
                    directory = Path.Combine(directory, "index", batch.ToString());
                }

                if (batch == 1)
                {
                    index.Previous = null;
                }
                else if (batch == 2)
                {
                    index.Previous = "/";
                }
                else
                {
                    index.Previous = "/index/" + (batch - 1) + "/";
                }

                if (posts.Length > postsToDisplay)
                {
                    index.Next = "/index/" + (batch + 1) + "/";
                }
                else
                {
                    index.Next = null;
                }

                using (var stringWriter = new StringWriter())
                {
                    var view        = engine.GetView(".", $"/Templates/index.cshtml", true);
                    var viewContext = new ViewContext(actionContext, view.View, viewDataDictionary, tempDataDictionary, stringWriter, htmlHelperOptions);

                    index.PostsToDisplay = posts.Take(postsToDisplay).ToArray();
                    await view.View.RenderAsync(viewContext);

                    var result = stringWriter.ToString();

                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }

                    File.WriteAllText(Path.Combine(directory, "index.html"), result);
                }

                posts = posts.Skip(postsToDisplay).ToArray();
                batch++;
            }
        }
Esempio n. 7
0
        private static async Task HandleTagAsync(Tag tag, Post[] posts, Settings settings, TemplatingOptions options, IServiceProvider services, IRazorViewEngine engine)
        {
            var postsToDisplay = 27;
            var httpContext    = new DefaultHttpContext {
                RequestServices = services
            };
            var routeData             = new RouteData();
            var actionDescriptor      = new ActionDescriptor();
            var modelStateDictionary  = new ModelStateDictionary();
            var modelMetadataProvider = new EmptyModelMetadataProvider();
            var tempDataProvider      = new VirtualTempDataProvider();
            var htmlHelperOptions     = new HtmlHelperOptions();

            posts         = posts.Where(x => x.Tags.Any(x => x.Id == tag.Id)).OrderByDescending(x => x.PublishedAt).ToArray();
            tag.PostCount = posts.Length;

            var actionContext      = new ActionContext(httpContext, routeData, actionDescriptor, modelStateDictionary);
            var viewDataDictionary = new ViewDataDictionary(modelMetadataProvider, modelStateDictionary);
            var tempDataDictionary = new TempDataDictionary(httpContext, tempDataProvider);

            viewDataDictionary.Model = tag;

            var batch = 1;

            while (posts.Length > 0)
            {
                var directory = Path.Combine(options.OutputDirectory, "tag", tag.Slug);
                if (batch > 1)
                {
                    directory = Path.Combine(directory, batch.ToString());
                }

                if (batch == 1)
                {
                    tag.Previous = null;
                }
                else if (batch == 2)
                {
                    tag.Previous = tag.Url;
                }
                else
                {
                    tag.Previous = tag.Url + (batch - 1) + "/";
                }

                if (posts.Length > postsToDisplay)
                {
                    tag.Next = tag.Url + (batch + 1) + "/";
                }
                else
                {
                    tag.Next = null;
                }

                using (var stringWriter = new StringWriter())
                {
                    var view        = engine.GetView(".", $"/Templates/tag.cshtml", true);
                    var viewContext = new ViewContext(actionContext, view.View, viewDataDictionary, tempDataDictionary, stringWriter, htmlHelperOptions);

                    tag.PostsToDisplay = posts.Take(postsToDisplay).ToArray();
                    await view.View.RenderAsync(viewContext);

                    var result = stringWriter.ToString();

                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }

                    File.WriteAllText(Path.Combine(directory, "index.html"), result);
                }

                posts = posts.Skip(postsToDisplay).ToArray();
                batch++;
            }
        }