diff --git a/src/TerribleDev.Blog.Web/Controllers/HomeController.cs b/src/TerribleDev.Blog.Web/Controllers/HomeController.cs index 53edb65..84623c5 100644 --- a/src/TerribleDev.Blog.Web/Controllers/HomeController.cs +++ b/src/TerribleDev.Blog.Web/Controllers/HomeController.cs @@ -27,8 +27,8 @@ namespace TerribleDev.Blog.Web.Controllers [Route("/index.html", Order = 2)] [Route("/")] [Route("/page/{pageNumber:required:int:min(1)}")] - [OutputCache(Duration = 31536000, VaryByParam = "pageNumber")] - [ResponseCache(Duration = 900)] + [OutputCache(Duration = 31536000, VaryByParam = "pageNumber", VaryByHeader = "User-Agent")] + // [ResponseCache(Duration = 900)] public IActionResult Index(int pageNumber = 1) { if(!postCache.PostsByPage.TryGetValue(pageNumber, out var result)) @@ -47,7 +47,7 @@ namespace TerribleDev.Blog.Web.Controllers } [Route("/offline")] [Route("/offline.html")] - [ResponseCache(Duration = 3600)] + // [ResponseCache(Duration = 3600)] public IActionResult Offline() { return View(); @@ -60,8 +60,8 @@ namespace TerribleDev.Blog.Web.Controllers } [Route("{postUrl}/{amp?}")] - [OutputCache(Duration = 31536000, VaryByParam = "postUrl,amp")] - [ResponseCache(Duration = 900)] + [OutputCache(Duration = 31536000, VaryByParam = "postUrl,amp", VaryByHeader = "User-Agent")] + // [ResponseCache(Duration = 900)] public IActionResult Post(string postUrl, string amp = "") { if(!String.IsNullOrEmpty(amp) && amp != "amp") diff --git a/src/TerribleDev.Blog.Web/Controllers/TagsController.cs b/src/TerribleDev.Blog.Web/Controllers/TagsController.cs index f69170e..48d2724 100644 --- a/src/TerribleDev.Blog.Web/Controllers/TagsController.cs +++ b/src/TerribleDev.Blog.Web/Controllers/TagsController.cs @@ -18,13 +18,13 @@ namespace TerribleDev.Blog.Web.Controllers this.postCache = postCache; } [Route("/all-tags")] - [OutputCache(Duration = 31536000)] + [OutputCache(Duration = 31536000, VaryByHeader = "User-Agent")] public IActionResult AllTags() { return View(postCache.TagsToPosts); } [Route("/tags/{tagName}")] - [OutputCache(Duration = 31536000, VaryByParam = "tagName")] + [OutputCache(Duration = 31536000, VaryByParam = "tagName", VaryByHeader = "User-Agent")] public IActionResult TagPluralRedirect(string tagName) { if(string.IsNullOrEmpty(tagName)) @@ -34,7 +34,7 @@ namespace TerribleDev.Blog.Web.Controllers return Redirect($"/tag/{tagName}/"); } [Route("/tag/{tagName}")] - [OutputCache(Duration = 31536000, VaryByParam = "tagName")] + [OutputCache(Duration = 31536000, VaryByParam = "tagName", VaryByHeader = "User-Agent")] public IActionResult GetTag(string tagName) { if(!postCache.TagsToPosts.TryGetValue(tagName.ToLower(), out var models)) diff --git a/src/TerribleDev.Blog.Web/Factories/CodeFactory.cs b/src/TerribleDev.Blog.Web/Factories/CodeFactory.cs index 399c43a..f633969 100644 --- a/src/TerribleDev.Blog.Web/Factories/CodeFactory.cs +++ b/src/TerribleDev.Blog.Web/Factories/CodeFactory.cs @@ -9,8 +9,13 @@ namespace TerribleDev.Blog.Web.Factories public class CodeFactory { private HttpClient httpClient = new HttpClient(); + private static Boolean IsDisabled = !String.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("DISABLE_PRISMA")); public async Task<(string result, bool hasCode)> ReplaceFencedCode(string markdown) { + if(CodeFactory.IsDisabled) + { + return (markdown, false); + } // regex grab all text between backticks var regex = new Regex(@"```(.*?)```", RegexOptions.Singleline); diff --git a/src/TerribleDev.Blog.Web/Filters/Http2PushFilter.cs b/src/TerribleDev.Blog.Web/Filters/Http2PushFilter.cs index ba2b0ee..f8cc667 100644 --- a/src/TerribleDev.Blog.Web/Filters/Http2PushFilter.cs +++ b/src/TerribleDev.Blog.Web/Filters/Http2PushFilter.cs @@ -17,16 +17,16 @@ namespace TerribleDev.Blog.Web.Filters logger.LogDebug("Did not find any links to push"); return; } - var linkData = links as System.Collections.Generic.List; + var linkData = links as System.Collections.Generic.List; if(linkData == null || linkData.Count == 0) { logger.LogDebug("Http2PushFilter.OnActionExecuted: No links"); return; } var headerBuilder = new StringBuilder(); for(var i = 0; i < linkData.Count; i++) { - var url = linkData[i]; + var (url, AsProperty) = linkData[i]; var resolvedUrl = url.StartsWith("~") ? context.HttpContext.Request.PathBase.ToString() + url.Substring(1) : url; - headerBuilder.Append($"<{resolvedUrl}>; rel=preload; as=style"); + headerBuilder.Append($"<{resolvedUrl}>; rel=preload; as={AsProperty}"); if(i < linkData.Count - 1) { headerBuilder.Append(", "); } diff --git a/src/TerribleDev.Blog.Web/Taghelpers/AbstractPlatformTagHelper.cs b/src/TerribleDev.Blog.Web/Taghelpers/AbstractPlatformTagHelper.cs new file mode 100644 index 0000000..32f2ab7 --- /dev/null +++ b/src/TerribleDev.Blog.Web/Taghelpers/AbstractPlatformTagHelper.cs @@ -0,0 +1,45 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.AspNetCore.Razor.TagHelpers; +using System; +using System.Collections.Concurrent; +using System.Text.RegularExpressions; + +namespace TerribleDev.Blog.Web.Taghelpers +{ + public abstract class AbstractPlatformTagHelper : TagHelper + { + static Regex MobileCheck = new Regex(@"(?:phone|windows\s+phone|ipod|blackberry|(?:android|bb\d+|meego|silk|googlebot) .+? mobile|palm|windows\s+ce|opera\ mini|avantgo|mobilesafari|docomo|ipad)", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ECMAScript); + static ConcurrentDictionary CachedChecks = new ConcurrentDictionary(); // dictionary of user agent -> mobilre + protected HttpRequest Request => ViewContext.HttpContext.Request; + protected HttpResponse Response => ViewContext.HttpContext.Response; + + [ViewContext] + public ViewContext ViewContext { get; set; } + protected abstract bool ShouldRender(); + public Platform GetPlatform() + { + var userAgent = this.Request.Headers.UserAgent; + if (string.IsNullOrEmpty(userAgent)) + { + return Platform.Desktop; // mobile is default + } + if(CachedChecks.TryGetValue(userAgent, out var cacheResult)) + { + return cacheResult; + } + var isMobile = AbstractPlatformTagHelper.MobileCheck.IsMatch(this.Request.Headers.UserAgent); + return isMobile ? Platform.Mobile : Platform.Desktop; + } + public override void Process(TagHelperContext context, TagHelperOutput output) + { + output.TagName = null; + if(!this.ShouldRender()) + { + output.SuppressOutput(); + return; + } + } + } +} \ No newline at end of file diff --git a/src/TerribleDev.Blog.Web/Taghelpers/Desktop.cs b/src/TerribleDev.Blog.Web/Taghelpers/Desktop.cs new file mode 100644 index 0000000..8fad5ce --- /dev/null +++ b/src/TerribleDev.Blog.Web/Taghelpers/Desktop.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNetCore.Razor.TagHelpers; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace TerribleDev.Blog.Web.Taghelpers +{ + [HtmlTargetElement("desktop", TagStructure = TagStructure.NormalOrSelfClosing)] + public class DesktopTagHelper : AbstractPlatformTagHelper + { + protected override bool ShouldRender() => this.GetPlatform() == Platform.Desktop; + } +} diff --git a/src/TerribleDev.Blog.Web/Taghelpers/Http2Push.cs b/src/TerribleDev.Blog.Web/Taghelpers/Http2Push.cs index 3c86002..ae7ae54 100644 --- a/src/TerribleDev.Blog.Web/Taghelpers/Http2Push.cs +++ b/src/TerribleDev.Blog.Web/Taghelpers/Http2Push.cs @@ -13,9 +13,12 @@ using Microsoft.AspNetCore.Razor.TagHelpers; namespace TerribleDev.Blog.Web.Taghelpers { - [HtmlTargetElement("link", Attributes = "rel, href, http-2-push")] + public record PushUrl(string Url, string asProperty); + [HtmlTargetElement("link", Attributes = "[rel=stylesheet],href,push")] + [HtmlTargetElement("img", Attributes = "src,push")] public class HttpPush : LinkTagHelper { + [HtmlAttributeNotBound] public bool Http2PushEnabled { get; set; } = true; public static readonly string Key = "http2push-link"; @@ -24,23 +27,34 @@ namespace TerribleDev.Blog.Web.Taghelpers { } + private (string Url, string AsProperty) GetTagInfo(string tag) => + tag switch { + "link" => ("href", "link"), + "img" => ("src", "image"), + _ => (null, null) + }; + public override void Process(TagHelperContext context, TagHelperOutput output) { if(!this.Http2PushEnabled) { return; } - var url = base.TryResolveUrl(output.Attributes["href"].Value.ToString(), out string resolvedUrl) ? resolvedUrl : output.Attributes["href"].Value.ToString(); - var linkList = ViewContext.HttpContext.Items.TryGetValue(Key, out var links) ? links as List : null; + var (urlAttribute, asProperty) = GetTagInfo(output.TagName); + // var urlAttribute = context.TagName == "link" ? "href" : "src"; + var url = base.TryResolveUrl(output.Attributes[urlAttribute].Value.ToString(), out string resolvedUrl) ? resolvedUrl : output.Attributes[urlAttribute].Value.ToString(); + var linkList = ViewContext.HttpContext.Items.TryGetValue(Key, out var links) ? links as List : null; + if(linkList == null) { - linkList = new List() { url }; + linkList = new List() { new PushUrl(url, asProperty) }; ViewContext.HttpContext.Items.Add(HttpPush.Key, linkList); } else { - linkList.Add(url); + linkList.Add(new PushUrl(url, asProperty)); } + output.Attributes.Remove(output.Attributes["push"]); } } } \ No newline at end of file diff --git a/src/TerribleDev.Blog.Web/Taghelpers/Mobile.cs b/src/TerribleDev.Blog.Web/Taghelpers/Mobile.cs index 48f0875..abb38d4 100644 --- a/src/TerribleDev.Blog.Web/Taghelpers/Mobile.cs +++ b/src/TerribleDev.Blog.Web/Taghelpers/Mobile.cs @@ -8,34 +8,9 @@ using System.Threading.Tasks; namespace TerribleDev.Blog.Web.Taghelpers { - [HtmlTargetElement("desktopOnly", TagStructure = TagStructure.NormalOrSelfClosing)] - public class DesktopTagHelper : TagHelper + [HtmlTargetElement("mobile", TagStructure = TagStructure.NormalOrSelfClosing)] + public class MobileTagHelper : AbstractPlatformTagHelper { - static Regex MobileCheck = new Regex(@"(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled); - static ConcurrentDictionary CachedChecks = new ConcurrentDictionary(); - public string UserAgent { get; set; } - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = null; - if (string.IsNullOrEmpty(UserAgent)) - { - return; - } - var shouldRender = true; - if(CachedChecks.TryGetValue(UserAgent, out var cacheResult)) - { - shouldRender = cacheResult; - } - else - { - var isMobile = MobileCheck.IsMatch(UserAgent); - shouldRender = !isMobile; - CachedChecks.TryAdd(UserAgent, !isMobile); - } - if(!shouldRender) - { - output.SuppressOutput(); - } - } + protected override bool ShouldRender() => this.GetPlatform() == Platform.Mobile; } } diff --git a/src/TerribleDev.Blog.Web/Taghelpers/Platforms.cs b/src/TerribleDev.Blog.Web/Taghelpers/Platforms.cs new file mode 100644 index 0000000..951060b --- /dev/null +++ b/src/TerribleDev.Blog.Web/Taghelpers/Platforms.cs @@ -0,0 +1,8 @@ +namespace TerribleDev.Blog.Web.Taghelpers +{ + public enum Platform + { + Desktop, + Mobile, + } +} \ No newline at end of file diff --git a/src/TerribleDev.Blog.Web/Views/Shared/Nav.cshtml b/src/TerribleDev.Blog.Web/Views/Shared/Nav.cshtml index 4825599..b0a56e5 100644 --- a/src/TerribleDev.Blog.Web/Views/Shared/Nav.cshtml +++ b/src/TerribleDev.Blog.Web/Views/Shared/Nav.cshtml @@ -10,10 +10,11 @@ } else { - - - An image of TerribleDev - + + + An image of TerribleDev + + } Tommy "Terrible Dev" Parnell
    diff --git a/src/TerribleDev.Blog.Web/Views/Shared/_Layout.cshtml b/src/TerribleDev.Blog.Web/Views/Shared/_Layout.cshtml index 22028be..56ca5c5 100644 --- a/src/TerribleDev.Blog.Web/Views/Shared/_Layout.cshtml +++ b/src/TerribleDev.Blog.Web/Views/Shared/_Layout.cshtml @@ -8,18 +8,13 @@ - - - - @if(!amp) { } - - + @ViewData["Title"] | @config.Title @if(amp) { @@ -29,10 +24,22 @@ else { - + @* *@ + + + + + + - + + + + + + + @* *@ } @@ -43,6 +50,12 @@ } + + + + + + @RenderSection("Head", false) diff --git a/src/TerribleDev.Blog.Web/wwwroot/js/sw.js b/src/TerribleDev.Blog.Web/wwwroot/js/sw.js index 3cc4d2a..62e4900 100644 --- a/src/TerribleDev.Blog.Web/wwwroot/js/sw.js +++ b/src/TerribleDev.Blog.Web/wwwroot/js/sw.js @@ -3,7 +3,9 @@ //Install stage sets up the offline page in the cache and opens a new cache self.addEventListener('install', function (event) { - event.waitUntil(preLoad()); + setTimeout(function() { + event.waitUntil(preLoad()); + }, 5000); }); var preLoad = function () {