From ab9c9fdc9047a00e68168d8a301ac8a33c07da67 Mon Sep 17 00:00:00 2001 From: tparnell Date: Wed, 30 Jan 2019 08:36:38 -0500 Subject: [PATCH] it works in fsharp --- .../Factories/BlogFactory.fs | 139 ++++++++++-------- src/TerribleDev.Blog.Core/Models/Post.fs | 4 +- .../Models/PostSettings.fs | 2 +- .../TerribleDev.Blog.Core.fsproj | 1 - src/TerribleDev.Blog.Core/Util/Seq.fs | 1 - .../Controllers/HomeController.cs | 14 +- .../Controllers/SeoController.cs | 2 +- .../Drafts/How-I-Analyze-page-performance.md | 0 .../Factories/BlogFactory.cs | 2 +- .../Models/GetTagViewModel.cs | 2 +- .../Models/HomeViewModel.cs | 2 +- .../Views/Home/Post.cshtml | 6 +- .../Views/Shared/DisplayTemplates/Post.cshtml | 2 +- .../Views/Shared/PostSummary.cshtml | 2 +- 14 files changed, 94 insertions(+), 85 deletions(-) delete mode 100644 src/TerribleDev.Blog.Core/Util/Seq.fs create mode 100644 src/TerribleDev.Blog.Web/Drafts/How-I-Analyze-page-performance.md diff --git a/src/TerribleDev.Blog.Core/Factories/BlogFactory.fs b/src/TerribleDev.Blog.Core/Factories/BlogFactory.fs index f1587e7..3fc6ba1 100644 --- a/src/TerribleDev.Blog.Core/Factories/BlogFactory.fs +++ b/src/TerribleDev.Blog.Core/Factories/BlogFactory.fs @@ -1,71 +1,82 @@ -module BlogFactory +namespace TerribleDev.Blog.Core.Factories +module BlogFactory = -open System.IO -open YamlDotNet.Serialization -open TerribleDev.Blog.Core.Models -open TerribleDev.Blog.Core -open Markdig -open TerribleDev.Blog.MarkdownPlugins -open Microsoft.AspNetCore.Html -open System.Linq -open System.Collections.Generic + open System.IO + open YamlDotNet.Serialization + open TerribleDev.Blog.Core.Models + open TerribleDev.Blog.Core + open Markdig + open TerribleDev.Blog.MarkdownPlugins + open Microsoft.AspNetCore.Html + open System.Linq + open System.Collections.Generic -let fixTagName (tag:string) = tag.Replace(' ', '-').WithoutSpecialCharacters().ToLower() -let mapImgUrl resolveUrl imgUrl = if imgUrl.StartsWith('/') then imgUrl else sprintf "/%s/%s" resolveUrl imgUrl + let fixTagName (tag:string) = tag.Replace(' ', '-').WithoutSpecialCharacters().ToLower() + let mapImgUrlResolver (resolveUrl:string) = + fun (imgUrl: string) -> if imgUrl.StartsWith('/') then imgUrl else sprintf "/%s/%s" resolveUrl imgUrl + -let getPosts (path) = Directory.EnumerateFiles(path, "*.md", SearchOption.TopDirectoryOnly) -let parseYml (postText:string):PostSettings = - postText.Split("---").[0] - |> DeserializerBuilder().Build().Deserialize + let getPosts (path) = Directory.EnumerateFiles(path, "*.md", SearchOption.TopDirectoryOnly) + let parseYml (postText:string):PostSettings = + postText.Split("---").[0] + |> DeserializerBuilder().Build().Deserialize -let getFileInfo (filePath:string) = - let fileInfo = FileInfo(filePath) - async { - let! text = File.ReadAllTextAsync(fileInfo.FullName) |> Async.AwaitTask - return (text, fileInfo) - } -let getMarkdownBuilder (imgRef) = - MarkdownPipelineBuilder() - .Use() - .Use(new ImageRecorder(imgRef)) - .UseMediaLinks() - .UseEmojiAndSmiley() - .Build() -let parsePost (postText:string, fileName:FileInfo, postSettings:PostSettings): Post = - let mutable images = System.Collections.Generic.List() - let markdownBuilder = getMarkdownBuilder(images) - //todo this function is a bit gross - let markdownText = postText.Split("---") |> Seq.skip 1 |> String.concat "" - let postContent = Markdown.ToHtml(markdownText, markdownBuilder); - let postContentPlain = Markdown.ToPlainText(markdownText, markdownBuilder).Split("") |> String.concat "" - //todo pattern match - let resolvedUrl = if System.String.IsNullOrWhiteSpace(postSettings.permalink) then fileName.Name.Split('.').[0].Replace(' ', '-').WithoutSpecialCharacters() else postSettings.permalink - let summary = postContent.Split("").[0]; - let postSummaryPlain = postContentPlain.Split("").[0]; - let tags = postSettings.tags |> Seq.map fixTagName |> Seq.toList - let summaryPlainShort = match postContentPlain with - | postContentPlain when postContentPlain.Length <= 147 -> postContentPlain - | postContentPlain -> postContentPlain.Substring(0, 146) + "..." - let mapImgUrlFromResolved = mapImgUrl resolvedUrl - let images = images |> Seq.distinct |> Seq.map mapImgUrlFromResolved |> Seq.toList - { - PublishDate = postSettings.date.ToUniversalTime(); - tags = tags; - Title = postSettings.title; - Url = resolvedUrl; - Content = HtmlString(postContent); - Summary = HtmlString(summary); - SummaryPlain = postSummaryPlain; - SummaryPlainShort = summaryPlainShort; - ContentPlain = postContentPlain; - Images = images - } -let getAllPosts path = - getPosts path - |> Seq.map getFileInfo - |> Seq.map(Async.map(fun (text, fileInfo) -> (text, fileInfo, parseYml(text)))) - |> Seq.map(Async.map(parsePost)) - + let getFileInfo (filePath:string) = + let fileInfo = FileInfo(filePath) + async { + let! text = File.ReadAllTextAsync(fileInfo.FullName) |> Async.AwaitTask + return (text, fileInfo) + } + let getMarkdownBuilder (imgRef) = + MarkdownPipelineBuilder() + .Use() + .Use(new ImageRecorder(imgRef)) + .UseMediaLinks() + .UseEmojiAndSmiley() + .Build() + let parsePost (postText:string, fileName:FileInfo, postSettings:PostSettings): Post = + let mutable images = System.Collections.Generic.List() + let markdownBuilder = getMarkdownBuilder(images) + //todo this function is a bit gross + let markdownText = postText.Split("---") |> Seq.skip 1 |> String.concat "" + let postContent = Markdown.ToHtml(markdownText, markdownBuilder); + let postContentPlain = Markdown.ToPlainText(markdownText, markdownBuilder).Split("") |> String.concat "" + //todo pattern match + let resolvedUrl = if System.String.IsNullOrWhiteSpace(postSettings.permalink) then fileName.Name.Split('.').[0].Replace(' ', '-').WithoutSpecialCharacters() else postSettings.permalink + let summary = postContent.Split("").[0]; + let postSummaryPlain = postContentPlain.Split("").[0]; + let tags = match postSettings.tags with + | null -> Seq.empty + | x -> x |> Seq.map fixTagName + let summaryPlainShort = match postContentPlain with + | postContentPlain when postContentPlain.Length <= 147 -> postContentPlain + | postContentPlain -> postContentPlain.Substring(0, 146) + "..." + let mapImgUrlFromResolved = mapImgUrlResolver resolvedUrl + let images = images |> Seq.distinct |> Seq.map mapImgUrlFromResolved |> Seq.toList + { + PublishDate = postSettings.date.ToUniversalTime(); + tags = tags |> System.Collections.Generic.List + Title = postSettings.title; + Url = resolvedUrl; + Content = HtmlString(postContent); + Summary = HtmlString(summary); + SummaryPlain = postSummaryPlain; + SummaryPlainShort = summaryPlainShort; + ContentPlain = postContentPlain; + Images = images |> System.Collections.Generic.List + } + let getAllPosts path = + getPosts path + |> Seq.map getFileInfo + |> Seq.map(Async.map(fun (text, fileInfo) -> (text, fileInfo, parseYml(text)))) + |> Seq.map(Async.map(parsePost)) + |> Async.Parallel + // todo stop this + |> Async.RunSynchronously + |> System.Collections.Generic.List + + + diff --git a/src/TerribleDev.Blog.Core/Models/Post.fs b/src/TerribleDev.Blog.Core/Models/Post.fs index b5552fb..9fc097b 100644 --- a/src/TerribleDev.Blog.Core/Models/Post.fs +++ b/src/TerribleDev.Blog.Core/Models/Post.fs @@ -12,6 +12,6 @@ type Post = ContentPlain: string; SummaryPlain: string; SummaryPlainShort: string; - tags : List - Images: List + tags : System.Collections.Generic.List + Images: System.Collections.Generic.List } \ No newline at end of file diff --git a/src/TerribleDev.Blog.Core/Models/PostSettings.fs b/src/TerribleDev.Blog.Core/Models/PostSettings.fs index 8690151..04df739 100644 --- a/src/TerribleDev.Blog.Core/Models/PostSettings.fs +++ b/src/TerribleDev.Blog.Core/Models/PostSettings.fs @@ -2,7 +2,7 @@ open System; open System.Collections.Generic - +[] type PostSettings = { tags: List; diff --git a/src/TerribleDev.Blog.Core/TerribleDev.Blog.Core.fsproj b/src/TerribleDev.Blog.Core/TerribleDev.Blog.Core.fsproj index cf5f2ef..811cd48 100644 --- a/src/TerribleDev.Blog.Core/TerribleDev.Blog.Core.fsproj +++ b/src/TerribleDev.Blog.Core/TerribleDev.Blog.Core.fsproj @@ -3,7 +3,6 @@ netcoreapp2.2 - diff --git a/src/TerribleDev.Blog.Core/Util/Seq.fs b/src/TerribleDev.Blog.Core/Util/Seq.fs deleted file mode 100644 index 5f28270..0000000 --- a/src/TerribleDev.Blog.Core/Util/Seq.fs +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/TerribleDev.Blog.Web/Controllers/HomeController.cs b/src/TerribleDev.Blog.Web/Controllers/HomeController.cs index 4af7fcd..bede9a3 100644 --- a/src/TerribleDev.Blog.Web/Controllers/HomeController.cs +++ b/src/TerribleDev.Blog.Web/Controllers/HomeController.cs @@ -12,10 +12,10 @@ namespace TerribleDev.Blog.Web.Controllers { public class HomeController : Controller { - public static List postsAsList = new BlogFactory().GetAllPosts().OrderByDescending(a=>a.PublishDate).ToList(); - public static Dictionary> tagToPost = postsAsList.Where(a=>a.tags != null) + public static List postsAsList = TerribleDev.Blog.Core.Factories.BlogFactory.getAllPosts("Posts").OrderByDescending(a => a.PublishDate).ToList(); + public static Dictionary> tagToPost = postsAsList.Where(a=>a.tags != null) .Aggregate( - new Dictionary>(), + new Dictionary>(), (accum, item) => { foreach(var tag in item.tags) { @@ -25,19 +25,19 @@ namespace TerribleDev.Blog.Web.Controllers } else { - accum[tag] = new List() { item }; + accum[tag] = new List() { item }; } } return accum; }); - public static IDictionary posts = postsAsList.ToDictionary(a => a.Url); - public static IDictionary> postsByPage = postsAsList.Aggregate(new Dictionary>() { [1] = new List() }, (accum, item) => + public static IDictionary posts = postsAsList.ToDictionary(a => a.Url); + public static IDictionary> postsByPage = postsAsList.Aggregate(new Dictionary>() { [1] = new List() }, (accum, item) => { var highestPage = accum.Keys.Max(); var current = accum[highestPage].Count; if (current >= 10) { - accum[highestPage + 1] = new List() { item }; + accum[highestPage + 1] = new List() { item }; return accum; } accum[highestPage].Add(item); diff --git a/src/TerribleDev.Blog.Web/Controllers/SeoController.cs b/src/TerribleDev.Blog.Web/Controllers/SeoController.cs index e6dd48c..2d9a0da 100644 --- a/src/TerribleDev.Blog.Web/Controllers/SeoController.cs +++ b/src/TerribleDev.Blog.Web/Controllers/SeoController.cs @@ -16,7 +16,7 @@ namespace TerribleDev.Blog.Web.Controllers public class SeoController : Controller { public static DateTimeOffset publishDate = DateTimeOffset.UtcNow; // keep publish date in memory so we just return when the server was kicked - public static IEnumerable postsToSyndication = HomeController.postsAsList.Select(a => a.ToSyndicationItem()).ToList(); + public static IEnumerable postsToSyndication = HomeController.postsAsList.Select(Core.Models.Util.ToSyndicationItem).ToList(); [Route("/rss")] [Route("/rss.xml")] [ResponseCache(Duration = 7200)] diff --git a/src/TerribleDev.Blog.Web/Drafts/How-I-Analyze-page-performance.md b/src/TerribleDev.Blog.Web/Drafts/How-I-Analyze-page-performance.md new file mode 100644 index 0000000..e69de29 diff --git a/src/TerribleDev.Blog.Web/Factories/BlogFactory.cs b/src/TerribleDev.Blog.Web/Factories/BlogFactory.cs index 486bfa5..96d58d1 100644 --- a/src/TerribleDev.Blog.Web/Factories/BlogFactory.cs +++ b/src/TerribleDev.Blog.Web/Factories/BlogFactory.cs @@ -45,7 +45,7 @@ namespace TerribleDev.Blog.Web List postImages = new List(); var pipeline = new MarkdownPipelineBuilder() .Use() - .Use(new ImageRecorder(ref postImages)) + .Use(new ImageRecorder(postImages)) .UseMediaLinks() .UseEmojiAndSmiley() .Build(); diff --git a/src/TerribleDev.Blog.Web/Models/GetTagViewModel.cs b/src/TerribleDev.Blog.Web/Models/GetTagViewModel.cs index 0e71623..39e1b8d 100644 --- a/src/TerribleDev.Blog.Web/Models/GetTagViewModel.cs +++ b/src/TerribleDev.Blog.Web/Models/GetTagViewModel.cs @@ -7,7 +7,7 @@ namespace TerribleDev.Blog.Web.Models { public class GetTagViewModel { - public IEnumerable Posts { get; set; } + public IEnumerable Posts { get; set; } public string Tag { get; set; } } } diff --git a/src/TerribleDev.Blog.Web/Models/HomeViewModel.cs b/src/TerribleDev.Blog.Web/Models/HomeViewModel.cs index 47c1971..2a91d1b 100644 --- a/src/TerribleDev.Blog.Web/Models/HomeViewModel.cs +++ b/src/TerribleDev.Blog.Web/Models/HomeViewModel.cs @@ -4,7 +4,7 @@ namespace TerribleDev.Blog.Web.Models { public class HomeViewModel { - public IEnumerable Posts { get; set;} + public IEnumerable Posts { get; set;} public int Page { get; set; } public string NextUrl { get; set; } public string PreviousUrl { get; set; } diff --git a/src/TerribleDev.Blog.Web/Views/Home/Post.cshtml b/src/TerribleDev.Blog.Web/Views/Home/Post.cshtml index b0134e6..db4cae2 100644 --- a/src/TerribleDev.Blog.Web/Views/Home/Post.cshtml +++ b/src/TerribleDev.Blog.Web/Views/Home/Post.cshtml @@ -1,4 +1,4 @@ -@model IPost +@model TerribleDev.Blog.Core.Models.Post @{ ViewData["Title"] = "Post"; ViewData["HideNav"] = true; @@ -23,10 +23,10 @@ @foreach(var image in Model.Images.Take(6)) { - + } @if(Model.Images.Count > 0) { - + } } diff --git a/src/TerribleDev.Blog.Web/Views/Shared/DisplayTemplates/Post.cshtml b/src/TerribleDev.Blog.Web/Views/Shared/DisplayTemplates/Post.cshtml index ce30b13..47177ad 100644 --- a/src/TerribleDev.Blog.Web/Views/Shared/DisplayTemplates/Post.cshtml +++ b/src/TerribleDev.Blog.Web/Views/Shared/DisplayTemplates/Post.cshtml @@ -1,4 +1,4 @@ -@model IPost +@model TerribleDev.Blog.Core.Models.Post

@Model.Title

diff --git a/src/TerribleDev.Blog.Web/Views/Shared/PostSummary.cshtml b/src/TerribleDev.Blog.Web/Views/Shared/PostSummary.cshtml index d809ca3..c069458 100644 --- a/src/TerribleDev.Blog.Web/Views/Shared/PostSummary.cshtml +++ b/src/TerribleDev.Blog.Web/Views/Shared/PostSummary.cshtml @@ -1,4 +1,4 @@ -@model IPost +@model TerribleDev.Blog.Core.Models.Post