Last active
April 22, 2024 07:14
-
-
Save jermdavis/469dbf0678ea5bc5ca7051955e1f5aba to your computer and use it in GitHub Desktop.
Example code for expiring outdated links in Statiq. Example code for a blog post: https://blog.jermdavis.dev/posts/2024/expiring-outdated-blog-links - More info there.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Statiq.App; | |
using Statiq.Common; | |
using StatiqGenerator.Customisations.ReadingTime; | |
namespace StatiqGenerator.Customisations.DisappearingLinks | |
{ | |
public class ExpiringLinkConfigurator : IConfigurator<Bootstrapper> | |
{ | |
public void Configure(Bootstrapper configurable) | |
{ | |
configurable.ModifyPipeline("Content", p => { | |
p.ProcessModules.Insert(4, new ExpiringLinkProcessor()); | |
}); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Statiq.Common; | |
using System.Collections.Generic; | |
using System.Text.RegularExpressions; | |
using System.Threading.Tasks; | |
using System.Transactions; | |
namespace StatiqGenerator.Customisations.DisappearingLinks | |
{ | |
public class ExpiringLinkProcessor : ParallelModule | |
{ | |
private static readonly Regex _links = new Regex("<a\\s?(?<attrs>.*?)>(?<inner>.*?)</a>\\s?", RegexOptions.Compiled | RegexOptions.IgnoreCase); | |
private static readonly Regex _date = new Regex("until=\"(?<date>.*?)\"", RegexOptions.Compiled | RegexOptions.IgnoreCase); | |
protected override async Task<IEnumerable<IDocument>> ExecuteInputAsync(IDocument input, IExecutionContext context) | |
{ | |
if (input.Source.Extension == ".md") | |
{ | |
var footnoteToAppend = string.Empty; | |
var hasChanged = false; | |
var content = await input.GetContentStringAsync(); | |
var links = _links.Matches(content); | |
foreach(Match link in links) | |
{ | |
var attrs = link.Groups["attrs"].Value; | |
var date = _date.Match(attrs); | |
if(date.Success) | |
{ | |
var txt = date.Groups["date"].Value; | |
if(DateTime.TryParse(txt, out DateTime parsedDate)) | |
{ | |
if(parsedDate.Date < DateTime.Now.Date) | |
{ | |
// remove link and return | |
content = content.Replace(link.Value, link.Groups["inner"].Value + "<a class=\"expired\" href=\"#expired\">**</a> "); | |
hasChanged = true; | |
footnoteToAppend += $"<li>{link.Value}</li>"; | |
continue; | |
} | |
} | |
// remove until="??" and return | |
content = content.Replace($" {date.Value}", ""); | |
hasChanged = true; | |
continue; | |
} | |
} | |
if(hasChanged) | |
{ | |
if(footnoteToAppend.Length > 0) | |
{ | |
content += "<blockquote><h4>Expired links</h4><div><a class=\"expired\" name=\"expired\">**</a> Some links in this page have expired. The originals are listed here, but they may no longer point to the correct content:</div><ol>" + footnoteToAppend + "</ol></blockquote>"; | |
} | |
var mt = input.GetContentProvider().MediaType; | |
return input | |
.Clone(new MetadataItems { { "ChangedLinks", "true" } }) | |
.Clone(context.GetContentProvider(content, mt)) | |
.Yield(); | |
} | |
} | |
return input.Yield(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment