| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- @page "/docs/{Page}"
- @inject HttpClient Http
- @inject NavigationManager Nav
- @inject IJSRuntime JS
- @using Markdig
- @implements IDisposable
- <PageTitle>Docs: @Page</PageTitle>
- <div class="min-h-screen bg-zinc-950 text-zinc-200 font-mono p-6 space-y-6">
- <!-- Header -->
- <div class="space-y-2">
- <h1 class="text-lg text-zinc-100">
- Docs:
- <span class="text-emerald-400">@Page</span>
- </h1>
- </div>
- @if (_isLoading)
- {
- <div class="text-zinc-500">loading documentation…</div>
- }
- else if (_notFound)
- {
- <div class="text-zinc-500">document not found</div>
- }
- else
- {
- <div class="markdown">
- @((MarkupString)_htmlContent!)
- </div>
- }
- </div>
- @code {
- [Parameter] public string Page { get; set; } = string.Empty;
- private string? _htmlContent;
- private bool _isLoading = true;
- private bool _notFound;
- private static readonly MarkdownPipeline Pipeline =
- new MarkdownPipelineBuilder()
- .UseAdvancedExtensions()
- .UseAutoIdentifiers()
- .Build();
- private bool _pendingScroll;
- protected override void OnInitialized()
- {
- Nav.LocationChanged += HandleLocationChanged;
- }
- private void HandleLocationChanged(object? sender, LocationChangedEventArgs e)
- {
- // Trigger re-render so OnAfterRenderAsync runs again
- _pendingScroll = true;
- InvokeAsync(StateHasChanged);
- }
- protected override async Task OnParametersSetAsync()
- {
- _isLoading = true;
- _notFound = false;
- _pendingScroll = true;
- try
- {
- var decoded = Uri.UnescapeDataString(Page);
- if (!decoded.EndsWith(".md", StringComparison.OrdinalIgnoreCase))
- decoded += ".md";
- var url = $"_content/Shared.Rcl/raw_docs/{decoded}";
- var markdown = await Http.GetStringAsync(url);
- _htmlContent = Markdown.ToHtml(markdown, Pipeline);
- }
- catch
- {
- _notFound = true;
- _htmlContent = null;
- }
- finally
- {
- _isLoading = false;
- }
- }
- protected override async Task OnAfterRenderAsync(bool firstRender)
- {
- if (_pendingScroll && !_isLoading && !_notFound)
- {
- _pendingScroll = false;
- await ScrollToFragmentAsync();
- }
- }
- private async Task ScrollToFragmentAsync()
- {
- var uri = new Uri(Nav.Uri);
- var fragment = uri.Fragment;
- if (!string.IsNullOrWhiteSpace(fragment))
- {
- var anchor = fragment.TrimStart('#');
- await JS.InvokeVoidAsync("scrollToAnchor", anchor);
- }
- }
- public void Dispose()
- {
- Nav.LocationChanged -= HandleLocationChanged;
- }
- }
|