diff --git a/docs/README.md b/docs/README.md index 67956e2..1a9a72b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,3 +8,7 @@ https://css-tricks.com/functional-css-tabs-revisited/ How to Add Copy to Clipboard Buttons to Code Blocks in Hugo March 22, 2019 https://www.dannyguo.com/blog/how-to-add-copy-to-clipboard-buttons-to-code-blocks-in-hugo/ + +Neat Annotations +https://neat-annotations.syabro.com/ +https://github.com/syabro/neat-annotations diff --git a/docs/figure-annotations.png b/docs/figure-annotations.png new file mode 100644 index 0000000..6b611e8 Binary files /dev/null and b/docs/figure-annotations.png differ diff --git a/docs/figures.md b/docs/figures.md index 8656183..de55e5b 100644 --- a/docs/figures.md +++ b/docs/figures.md @@ -1258,6 +1258,16 @@ A .NET object serialised to XML and deserialised back to an equivalent object. --- +## Annotation screenshot example + +The generated `maps` page now includes text callouts rendered with Neat +Annotations. This screenshot shows an annotation attached to +`TryGetValue`, between the figure banner and runner output. + +![maps example page showing an annotation callout for TryGetValue](figure-annotations.png) + +--- + ## Reference — all figures | Figure name | Paint method | Canvas (w×h) | Attached to | diff --git a/src/dotnetbyexample.Tests/NoccoTests.cs b/src/dotnetbyexample.Tests/NoccoTests.cs index dcb8b4d..1a924d5 100644 --- a/src/dotnetbyexample.Tests/NoccoTests.cs +++ b/src/dotnetbyexample.Tests/NoccoTests.cs @@ -45,6 +45,16 @@ public void FigureAttachments_GetFigures_ReturnsConfiguredFigure() Assert.All(figures, figure => Assert.False(string.IsNullOrWhiteSpace(figure.Svg))); } + [Fact] + public void AnnotationAttachments_GetAnnotations_ReturnsConfiguredAnnotation() + { + var annotations = AnnotationAttachments.GetAnnotations("maps").ToList(); + + Assert.NotEmpty(annotations); + Assert.Contains(annotations, annotation => annotation.Text.Contains("TryGetValue", StringComparison.OrdinalIgnoreCase)); + Assert.All(annotations, annotation => Assert.Contains("ann", annotation.CssClass, StringComparison.Ordinal)); + } + [Fact] public async Task GenerateAsync_GeneratesIndexAndExamplePage() { diff --git a/src/dotnetbyexample/Marginalia/AnnotationAttachments.cs b/src/dotnetbyexample/Marginalia/AnnotationAttachments.cs new file mode 100644 index 0000000..cc133c4 --- /dev/null +++ b/src/dotnetbyexample/Marginalia/AnnotationAttachments.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; + +namespace dotnetbyexample.Marginalia; + +/// +/// Describes a text annotation attached to an example page. +/// +public readonly record struct AnnotationAttachment( + string Text, + string Note, + string DirectionClass, + string ColorClass, + string? Context = null); + +/// +/// Maps example directory slugs to optional annotation callouts. +/// +public static class AnnotationAttachments +{ + private static readonly Dictionary> Registry = + new(StringComparer.OrdinalIgnoreCase) + { + ["hello-world"] = new[] + { + new AnnotationAttachment( + "Console.WriteLine", + "writes to standard output", + "ann-s", + "ann-amber", + "Core API") + }, + ["maps"] = new[] + { + new AnnotationAttachment( + "TryGetValue", + "read safely without exceptions", + "ann-s", + "ann-blue", + "Lookup"), + new AnnotationAttachment( + "delete", + "remove a key/value entry", + "ann-se", + "ann-green", + "Mutation") + }, + ["goroutines"] = new[] + { + new AnnotationAttachment( + "go", + "starts concurrent work", + "ann-ne", + "ann-purple", + "Concurrency") + } + }; + + public static IEnumerable<(string Text, string Note, string CssClass, string? Context)> GetAnnotations(string slug) + { + if (!Registry.TryGetValue(slug, out var annotations)) + return []; + + return annotations.Select(annotation => ( + annotation.Text, + annotation.Note, + $"ann {annotation.DirectionClass} {annotation.ColorClass}", + annotation.Context)); + } +} diff --git a/src/dotnetbyexample/Nocco.cs b/src/dotnetbyexample/Nocco.cs index ebcc47c..9274aff 100644 --- a/src/dotnetbyexample/Nocco.cs +++ b/src/dotnetbyexample/Nocco.cs @@ -150,6 +150,7 @@ private static async Task GenerateHtml(string source, Dictionary { @@ -160,10 +161,12 @@ private static async Task GenerateHtml(string source, Dictionary