private string SaveFeed(HandlebarsPageData data)
        {
            var content = _feed(data);

            Log.Debug("Rendered feed.xml");
            return(_client.UploadContent(_bucket, "feed.xml", content)
                ? "/feed.xml"
                : null);
        }
        private string SaveIndex(HandlebarsPageData data)
        {
            var fname = string.Format("{0}{1}.html", data.Prefix, data.PageNum > 0 ? string.Format("-{0}", data.PageNum) : null);

            var content = _index(data);

            Log.Debug(string.Format("Rendered index {0}", fname));
            return(_client.UploadContent(_bucket, fname, content)
                ? string.Format("/{0}", fname)
                : null);
        }
        private string SavePost(HandlebarsPageData data)
        {
            if (_post == null)
            {
                return(null);
            }

            var fname   = string.Format("post-{0}.html", data.Post.Id);
            var content = _post(data);

            Log.Debug(string.Format("Rendered post {0}", fname));
            return(_client.UploadContent(_bucket, fname, content)
                ? string.Format("/{0}", fname)
                : null);
        }
        public override void Publish(IEnumerator <Post> posts, int count)
        {
            // git all hashtags from all posts to build recent/popular lists
            List <string>            recentHashtags  = null;
            Dictionary <string, int> popularHashtags = null;

            if (Config["hashtags"] == "true")
            {
                recentHashtags  = new List <string>();
                popularHashtags = new Dictionary <string, int>();
                while (posts.MoveNext())
                {
                    var matches = _hashtags.Matches(posts.Current.Content);
                    foreach (Match match in matches)
                    {
                        var hashtag = match.Value.ToLower();
                        if (!recentHashtags.Contains(hashtag))
                        {
                            recentHashtags.Add(hashtag);
                        }
                        if (!popularHashtags.ContainsKey(hashtag))
                        {
                            popularHashtags.Add(hashtag, 0);
                        }
                        popularHashtags[hashtag] += 1;
                    }
                }
            }

            posts.Reset();

            var invalidations = new List <string> {
                "/"
            };

            var pagePosts = new List <ExtendedPost>();
            var hashtags  = new Dictionary <string, List <ExtendedPost> >();
            var data      = new HandlebarsPageData
            {
                Config      = Config,
                TotalPosts  = count,
                MaxPage     = (int)Math.Ceiling((float)count / _postsPerPage) - 1,
                PageNum     = 0,
                Prefix      = "index",
                RecentTags  = recentHashtags.Take(10),
                PopularTags = popularHashtags != null
                    ? popularHashtags.OrderByDescending(t => t.Value).Take(10).Select(t => t.Key).ToArray()
                    : null
            };

            while (posts.MoveNext())
            {
                var clone = new ExtendedPost((Post)posts.Current.Clone())
                {
                    Config = Config
                };
                if (Config["hashtags"] == "true")
                {
                    Hashtagify(hashtags, clone);
                }

                data.Post = clone;
                invalidations.Add(SavePost(data));
                pagePosts.Add(clone);
                if (pagePosts.Count == _postsPerPage)
                {
                    data.Posts = pagePosts.ToArray();
                    invalidations.Add(SaveIndex(data));
                    if (data.PageNum == 0)
                    {
                        invalidations.Add(SaveFeed(data));
                    }
                    data.PageNum += 1;
                    pagePosts.Clear();
                }
            }
            if (pagePosts.Count > 0)
            {
                data.Posts = pagePosts.ToArray();
                invalidations.Add(SaveIndex(data));
                if (data.PageNum == 0)
                {
                    invalidations.Add(SaveFeed(data));
                }
            }

            foreach (var hashtag in hashtags.Keys)
            {
                var hashData = new HandlebarsPageData
                {
                    Config      = Config,
                    TotalPosts  = hashtags[hashtag].Count,
                    MaxPage     = (int)Math.Ceiling((float)hashtags[hashtag].Count / _postsPerPage) - 1,
                    PageNum     = 0,
                    Prefix      = hashtag,
                    RecentTags  = recentHashtags.Take(10),
                    PopularTags = popularHashtags != null
                        ? popularHashtags.OrderByDescending(t => t.Value).Take(10).Select(t => t.Key).ToArray()
                        : null
                };
                pagePosts.Clear();
                foreach (var post in hashtags[hashtag])
                {
                    pagePosts.Add(post);
                    if (pagePosts.Count == _postsPerPage)
                    {
                        hashData.Posts = pagePosts.ToArray();
                        invalidations.Add(SaveIndex(hashData));
                        hashData.PageNum += 1;
                        pagePosts.Clear();
                    }
                }
                if (pagePosts.Count > 0)
                {
                    hashData.Posts = pagePosts.ToArray();
                    invalidations.Add(SaveIndex(hashData));
                }
            }

            var invalidPaths = invalidations.Where(i => !string.IsNullOrEmpty(i)).ToList();

            invalidPaths.AddRange(UploadDirectory(_assetPath, "assets"));

            Log.Debug("S3 upload complete");
            if (invalidPaths.Count > 0)
            {
                var distId = Config["cloudfrontDistId"];
                if (distId != null)
                {
                    _client.InvalidateCloudFrontDistribution(distId, invalidPaths);
                }
            }
        }