using Markdig; namespace Elternbeirat.Web.Services; /// /// Reads the static content pages from Content/pages/*.md, renders them /// to HTML once at startup and keeps them in memory. Registered as a singleton /// because the content lives in the image and does not change at runtime. /// public sealed class PageService { private readonly IReadOnlyDictionary _pagesBySlug; /// /// Reads every Markdown page from the Content/pages directory below /// the application root and caches it. /// public PageService(IWebHostEnvironment environment) { var pipeline = new MarkdownPipelineBuilder() .UseYamlFrontMatter() .Build(); var directory = Path.Combine(environment.ContentRootPath, "Content", "pages"); var pages = new Dictionary(StringComparer.OrdinalIgnoreCase); if (Directory.Exists(directory)) { foreach (var path in Directory.EnumerateFiles(directory, "*.md")) { var page = Read(path, pipeline); pages[page.Slug] = page; } } _pagesBySlug = pages; } /// /// Returns the page for the given slug, or null if there is none. /// The lookup is case-insensitive. /// public Page? Find(string slug) => _pagesBySlug.GetValueOrDefault(slug); private static Page Read(string path, MarkdownPipeline pipeline) { var slug = Path.GetFileNameWithoutExtension(path); var source = File.ReadAllText(path); var document = Markdown.Parse(source, pipeline); var title = FrontMatter.Read("title", document, source) ?? slug; var html = Markdown.ToHtml(source, pipeline); return new Page { Slug = slug, Title = title, ContentHtml = html }; } }