upperType = stackalloc char[type.Length];
- type.ToUpperInvariant(upperType);
-
- if (!CalloutTypes.TryGetValue(upperType.ToString(), out string? lucideClass))
- {
- lucideClass = "pencil";
- }
-
- var typeString = type.ToString().ToLowerInvariant();
-
- renderer.Write($"');
- renderer.Write("
");
-
- string calloutTitle = title.Length == 0 ? typeString.Humanize(LetterCasing.Sentence) : title;
- WriteTitle(renderer, pipeline, calloutTitle);
-
- if (block.Foldable)
- {
- renderer.Write("");
- }
-
- renderer.WriteLine("
");
- renderer.Write("
");
- renderer.WriteChildren(block);
- renderer.WriteLine("
");
- renderer.WriteLine("
");
- renderer.EnsureLine();
- }
-
- private static void WriteTitle(TextRendererBase renderer, MarkdownPipeline pipeline, string calloutTitle)
- {
- string html = Markdig.Markdown.ToHtml(calloutTitle, pipeline);
- var document = new HtmlDocument();
- document.LoadHtml(html);
- if (document.DocumentNode.FirstChild is { Name: "p" } child)
- {
- // ugly hack to remove tag generated by Markdig
- document.DocumentNode.InnerHtml = child.InnerHtml;
- }
-
- document.Save(renderer.Writer);
- }
-
- private static void RenderAsText(HtmlRenderer renderer, CalloutBlock block)
- {
- string title = block.Title.Text;
- ReadOnlySpan type = block.Type.AsSpan();
- renderer.WriteLine(title.Length == 0 ? type.ToString().ToUpperInvariant() : title.ToUpperInvariant());
- renderer.WriteChildren(block);
- renderer.EnsureLine();
- }
-}
diff --git a/OliverBooth/Markdown/MarkdownExtensions.cs b/OliverBooth/Markdown/MarkdownExtensions.cs
deleted file mode 100644
index d63d869..0000000
--- a/OliverBooth/Markdown/MarkdownExtensions.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using Markdig;
-using OliverBooth.Markdown.Callout;
-
-namespace OliverBooth.Markdown;
-
-///
-/// Extension methods for .
-///
-internal static class MarkdownExtensions
-{
- ///
- /// Uses this extension to enable Obsidian-style callouts.
- ///
- /// The pipeline.
- /// The modified pipeline.
- public static MarkdownPipelineBuilder UseCallouts(this MarkdownPipelineBuilder pipeline)
- {
- pipeline.Extensions.AddIfNotAlready();
- return pipeline;
- }
-}
diff --git a/OliverBooth/Markdown/Timestamp/TimestampExtension.cs b/OliverBooth/Markdown/Timestamp/TimestampExtension.cs
deleted file mode 100644
index 45ae2df..0000000
--- a/OliverBooth/Markdown/Timestamp/TimestampExtension.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using Markdig;
-using Markdig.Renderers;
-
-namespace OliverBooth.Markdown.Timestamp;
-
-///
-/// Represents a Markdig extension that supports Discord-style timestamps.
-///
-public class TimestampExtension : IMarkdownExtension
-{
- ///
- public void Setup(MarkdownPipelineBuilder pipeline)
- {
- pipeline.InlineParsers.AddIfNotAlready();
- }
-
- ///
- public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
- {
- if (renderer is HtmlRenderer htmlRenderer)
- {
- htmlRenderer.ObjectRenderers.AddIfNotAlready();
- }
- }
-}
diff --git a/OliverBooth/Markdown/Timestamp/TimestampFormat.cs b/OliverBooth/Markdown/Timestamp/TimestampFormat.cs
deleted file mode 100644
index 29eca6b..0000000
--- a/OliverBooth/Markdown/Timestamp/TimestampFormat.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-namespace OliverBooth.Markdown.Timestamp;
-
-///
-/// An enumeration of timestamp formats.
-///
-public enum TimestampFormat
-{
- ///
- /// Short time format. Example: 12:00
- ///
- ShortTime = 't',
-
- ///
- /// Long time format. Example: 12:00:00
- ///
- LongTime = 'T',
-
- ///
- /// Short date format. Example: 1/1/2000
- ///
- ShortDate = 'd',
-
- ///
- /// Long date format. Example: 1 January 2000
- ///
- LongDate = 'D',
-
- ///
- /// Short date/time format. Example: 1 January 2000 at 12:00
- ///
- LongDateShortTime = 'f',
-
- ///
- /// Long date/time format. Example: Saturday, 1 January 2000 at 12:00
- ///
- LongDateTime = 'F',
-
- ///
- /// Relative date/time format. Example: 1 second ago
- ///
- Relative = 'R',
-}
diff --git a/OliverBooth/Markdown/Timestamp/TimestampInline.cs b/OliverBooth/Markdown/Timestamp/TimestampInline.cs
deleted file mode 100644
index 615ee03..0000000
--- a/OliverBooth/Markdown/Timestamp/TimestampInline.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using Markdig.Syntax.Inlines;
-
-namespace OliverBooth.Markdown.Timestamp;
-
-///
-/// Represents a Markdown inline element that contains a timestamp.
-///
-public sealed class TimestampInline : Inline
-{
- ///
- /// Gets or sets the format.
- ///
- /// The format.
- public TimestampFormat Format { get; set; }
-
- ///
- /// Gets or sets the timestamp.
- ///
- /// The timestamp.
- public DateTimeOffset Timestamp { get; set; }
-}
diff --git a/OliverBooth/Markdown/Timestamp/TimestampInlineParser.cs b/OliverBooth/Markdown/Timestamp/TimestampInlineParser.cs
deleted file mode 100644
index 414fc48..0000000
--- a/OliverBooth/Markdown/Timestamp/TimestampInlineParser.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-using Markdig.Helpers;
-using Markdig.Parsers;
-
-namespace OliverBooth.Markdown.Timestamp;
-
-///
-/// Represents a Markdown inline parser that matches Discord-style timestamps.
-///
-public sealed class TimestampInlineParser : InlineParser
-{
- ///
- /// Initializes a new instance of the class.
- ///
- public TimestampInlineParser()
- {
- OpeningCharacters = new[] { '<' };
- }
-
- ///
- public override bool Match(InlineProcessor processor, ref StringSlice slice)
- {
- // Previous char must be a space
- if (!slice.PeekCharExtra(-1).IsWhiteSpaceOrZero())
- {
- return false;
- }
-
- ReadOnlySpan span = slice.Text.AsSpan(slice.Start, slice.Length);
-
- if (!TryConsumeTimestamp(span, out ReadOnlySpan rawTimestamp, out char format))
- {
- return false;
- }
-
- if (!long.TryParse(rawTimestamp, out long timestamp))
- {
- return false;
- }
-
- bool hasFormat = format != '\0';
- processor.Inline = new TimestampInline
- {
- Format = (TimestampFormat)format,
- Timestamp = DateTimeOffset.FromUnixTimeSeconds(timestamp)
- };
-
- int paddingCount = hasFormat ? 6 : 4; // or optionally
- slice.Start += rawTimestamp.Length + paddingCount;
- return true;
- }
-
- private bool TryConsumeTimestamp(ReadOnlySpan source,
- out ReadOnlySpan timestamp,
- out char format)
- {
- timestamp = default;
- format = default;
-
- if (!source.StartsWith("') == -1)
- {
- timestamp = default;
- return false;
- }
-
- int delimiterIndex = timestamp.IndexOf(':');
- if (delimiterIndex == 0)
- {
- // invalid format
- timestamp = default;
- return false;
- }
-
- if (delimiterIndex == -1)
- {
- // no format, default to relative
- format = 'R';
- timestamp = timestamp[..^1]; // trim >
- }
- else
- {
- // use specified format
- format = timestamp[^2];
- timestamp = timestamp[..^3];
- }
-
- return true;
- }
-}
diff --git a/OliverBooth/Markdown/Timestamp/TimestampRenderer.cs b/OliverBooth/Markdown/Timestamp/TimestampRenderer.cs
deleted file mode 100644
index b2c7f3d..0000000
--- a/OliverBooth/Markdown/Timestamp/TimestampRenderer.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using System.ComponentModel;
-using Humanizer;
-using Markdig.Renderers;
-using Markdig.Renderers.Html;
-
-namespace OliverBooth.Markdown.Timestamp;
-
-///
-/// Represents a Markdown object renderer that renders elements.
-///
-public sealed class TimestampRenderer : HtmlObjectRenderer
-{
- ///
- protected override void Write(HtmlRenderer renderer, TimestampInline obj)
- {
- DateTimeOffset timestamp = obj.Timestamp;
- TimestampFormat format = obj.Format;
-
- renderer.Write("");
-
- switch (format)
- {
- case TimestampFormat.LongDate:
- renderer.Write(timestamp.ToString("d MMMM yyyy"));
- break;
-
- case TimestampFormat.LongDateShortTime:
- renderer.Write(timestamp.ToString(@"d MMMM yyyy \a\t HH:mm"));
- break;
-
- case TimestampFormat.LongDateTime:
- renderer.Write(timestamp.ToString(@"dddd, d MMMM yyyy \a\t HH:mm"));
- break;
-
- case TimestampFormat.Relative:
- renderer.Write(timestamp.Humanize());
- break;
-
- case var _ when !Enum.IsDefined(format):
- throw new InvalidEnumArgumentException(nameof(format), (int)format, typeof(TimestampFormat));
-
- default:
- renderer.Write(timestamp.ToString(((char)format).ToString()));
- break;
- }
-
- renderer.Write("");
- }
-}
diff --git a/OliverBooth/Program.cs b/OliverBooth/Program.cs
index 006a3b7..84203ce 100644
--- a/OliverBooth/Program.cs
+++ b/OliverBooth/Program.cs
@@ -5,9 +5,8 @@ using OliverBooth.Data.Blog;
using OliverBooth.Data.Web;
using OliverBooth.Extensions;
using OliverBooth.Extensions.Markdig;
+using OliverBooth.Extensions.Markdig.Markdown.Timestamp;
using OliverBooth.Extensions.Markdig.Services;
-using OliverBooth.Markdown;
-using OliverBooth.Markdown.Timestamp;
using OliverBooth.Services;
using Serilog;