This commit is contained in:
Tommy Parnell
2022-03-10 22:31:39 -05:00
parent 1d49ce2ec5
commit 6303af4640
8 changed files with 51 additions and 8 deletions

View File

@@ -14,6 +14,7 @@ using System.Diagnostics;
using System.Collections.Concurrent;
using Schema.NET;
using System.Text.RegularExpressions;
using TerribleDev.Blog.Web.Factories;
namespace TerribleDev.Blog.Web
{
@@ -45,7 +46,7 @@ namespace TerribleDev.Blog.Web
return serializer.Deserialize<PostSettings>(ymlText);
}
public (string postContent, string postContentPlain, string summary, string postSummaryPlain, IList<string> postImages) ResolveContentForPost(string markdownText, string fileName, string resolvedUrl, string domain)
public (string postContent, string postContentPlain, string summary, string postSummaryPlain, IList<string> postImages, Boolean hasCode) ResolveContentForPost(string markdownText, string fileName, string resolvedUrl, string domain)
{
List<string> postImages = new List<string>();
var pipeline = new MarkdownPipelineBuilder()
@@ -56,11 +57,12 @@ namespace TerribleDev.Blog.Web
.Use<PictureInline>()
.UseEmojiAndSmiley()
.Build();
var postContent = Markdown.ToHtml(markdownText, pipeline);
var postContentPlain = String.Join("", Markdown.ToPlainText(markdownText, pipeline).Split("<!-- more -->"));
var (replacedText, hasCode) = CodeFactory.ReplaceFencedCode(markdownText).Result;
var postContent = Markdown.ToHtml(replacedText, pipeline);
var postContentPlain = String.Join("", Markdown.ToPlainText(replacedText, pipeline).Split("<!-- more -->"));
var summary = postContent.Split("<!-- more -->")[0];
var postSummaryPlain = postContentPlain.Split("<!-- more -->")[0];
return (postContent, postContentPlain, summary, postSummaryPlain, postImages);
return (postContent, postContentPlain, summary, postSummaryPlain, postImages, hasCode);
}
public IPost ParsePost(string postText, string fileName, string domain)
{
@@ -89,7 +91,7 @@ namespace TerribleDev.Blog.Web
isLanding = postSettings.isLanding,
Content = new Lazy<IPostContent>(() =>
{
(string postContent, string postContentPlain, string summary, string postSummaryPlain, IList<string> postImages) = ResolveContentForPost(markdownText, fileName, resolvedUrl, domain);
(string postContent, string postContentPlain, string summary, string postSummaryPlain, IList<string> postImages, bool hasCode) = ResolveContentForPost(markdownText, fileName, resolvedUrl, domain);
var ld = new Schema.NET.BlogPosting()
{
Headline = postSettings.title,
@@ -131,6 +133,7 @@ namespace TerribleDev.Blog.Web
JsonLDString = ld.ToHtmlEscapedString().Replace("https://schema.org", "https://schema.org/true"),
JsonLDBreadcrumb = breadcrumb,
JsonLDBreadcrumbString = breadcrumb.ToHtmlEscapedString().Replace("https://schema.org", "https://schema.org/true"),
HasCode = hasCode
};
}),
};
@@ -149,7 +152,7 @@ namespace TerribleDev.Blog.Web
isLanding = postSettings.isLanding,
Content = new Lazy<IPostContent>(() =>
{
(string postContent, string postContentPlain, string summary, string postSummaryPlain, IList<string> postImages) = ResolveContentForPost(markdownText, fileName, resolvedUrl, domain);
(string postContent, string postContentPlain, string summary, string postSummaryPlain, IList<string> postImages, bool hasCode) = ResolveContentForPost(markdownText, fileName, resolvedUrl, domain);
var breadcrumb = new Schema.NET.BreadcrumbList()
{
ItemListElement = new List<IListItem>() // Required
@@ -179,6 +182,7 @@ namespace TerribleDev.Blog.Web
SummaryPlainShort = (postContentPlain.Length <= 147 ? postContentPlain : postContentPlain.Substring(0, 146)) + "...",
JsonLDBreadcrumb = breadcrumb,
JsonLDBreadcrumbString = breadcrumb.ToHtmlEscapedString().Replace("https://schema.org", "https://schema.org/true"),
HasCode = hasCode
};
}),
};

View File

@@ -0,0 +1,31 @@
using System;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace TerribleDev.Blog.Web.Factories
{
public class CodeFactory
{
public async static Task<(string result, bool hasCode)> ReplaceFencedCode(string markdown)
{
// regex grab all text between backticks
var regex = new Regex(@"```(.*?)```", RegexOptions.Singleline);
var matches = regex.Matches(markdown);
var result = await Task.WhenAll(matches.Select(async match =>
{
var code = match.Value;
var codeContent = await new HttpClient().PostAsync("https://tp-prism-as-a-service.herokuapp.com/", new StringContent(code));
return (code, await codeContent.Content.ReadAsStringAsync());
}));
foreach(var (match, newValue) in result)
{
markdown = markdown.Replace(match, newValue);
}
return (markdown, matches.Count > 0);
}
}
}

View File

@@ -17,6 +17,8 @@ namespace TerribleDev.Blog.Web.Models
BlogPosting JsonLD { get; set; }
bool HasCode { get; set; }
public string JsonLDString { get; set; }
BreadcrumbList JsonLDBreadcrumb { get; set; }
string JsonLDBreadcrumbString { get; set; }

View File

@@ -19,5 +19,6 @@ namespace TerribleDev.Blog.Web.Models
public string JsonLDString { get; set; }
public BreadcrumbList JsonLDBreadcrumb { get; set; }
public string JsonLDBreadcrumbString { get; set; }
public bool HasCode { get; set; }
}
}

View File

@@ -176,7 +176,7 @@ AMP, [does allow for using JS](https://amp.dev/documentation/components/amp-scri
On pages that render AMP, you'll need to be able to generate 2 meta tags. The first is a canonical tag that tells google what the canonical URL is of the page. The second is one, to tell google where your amp pages are for a URL. This is data you typically want to pass to the Model of the view you are rendering. Adding these meta to the head of the layout through a section.
```cshtml
```cs
@section Head {
<link rel="canonical" href="@Model.Post.CanonicalUrl" />
<link rel="amphtml" href="@Model.Post.AMPUrl">

View File

@@ -2,6 +2,7 @@
@model PostViewModel
@{
ViewData["Title"] = Model.Post.Title;
var amp = ViewData["amp"] as bool? ?? false;
}
<cache vary-by-route="postUrl,amp">

View File

@@ -0,0 +1 @@
code[class*=language-],pre[class*=language-]{color:#f8f8f2;background:0 0;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background:#272822}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#8292a2}.token.punctuation{color:#f8f8f2}.token.namespace{opacity:.7}.token.constant,.token.deleted,.token.property,.token.symbol,.token.tag{color:#f92672}.token.boolean,.token.number{color:#ae81ff}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#a6e22e}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f8f8f2}.token.atrule,.token.attr-value,.token.class-name,.token.function{color:#e6db74}.token.keyword{color:#66d9ef}.token.important,.token.regex{color:#fd971f}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}

View File

@@ -245,4 +245,7 @@ a.skip-main:focus, a.skip-main:active {
margin: 0 auto;
font-size: 1.2em;
display: inline-block;
}
}
/* prism css */
code[class*=language-],pre[class*=language-]{color:#f8f8f2;background:0 0;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background:#272822}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#8292a2}.token.punctuation{color:#f8f8f2}.token.namespace{opacity:.7}.token.constant,.token.deleted,.token.property,.token.symbol,.token.tag{color:#f92672}.token.boolean,.token.number{color:#ae81ff}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#a6e22e}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f8f8f2}.token.atrule,.token.attr-value,.token.class-name,.token.function{color:#e6db74}.token.keyword{color:#66d9ef}.token.important,.token.regex{color:#fd971f}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}