mirror of
https://github.com/unclshura/BlazorOpenApi.git
synced 2025-12-21 09:51:53 +00:00
Add Table of Contents feature for improved navigation
This commit is contained in:
parent
878a7feded
commit
c1cac17c6b
@ -2,33 +2,39 @@
|
|||||||
{
|
{
|
||||||
@if (Value.Schemas?.Count > 0)
|
@if (Value.Schemas?.Count > 0)
|
||||||
{
|
{
|
||||||
|
<TocMember Title="Schemas">
|
||||||
<h3>Schemas</h3>
|
<h3>Schemas</h3>
|
||||||
@foreach (var (name, val) in Value.Schemas)
|
@foreach (var (name, val) in Value.Schemas)
|
||||||
{
|
{
|
||||||
<h4>@name</h4>
|
<h4>@name</h4>
|
||||||
<SchemaControl Value="@val"/>
|
<SchemaControl Value="@val"/>
|
||||||
}
|
}
|
||||||
|
</TocMember>
|
||||||
}
|
}
|
||||||
|
|
||||||
<ResponsesControl Value="@Value.Responses"/>
|
<ResponsesControl Value="@Value.Responses"/>
|
||||||
|
|
||||||
@if (Value.Parameters?.Count > 0)
|
@if (Value.Parameters?.Count > 0)
|
||||||
{
|
{
|
||||||
|
<TocMember Title="Parameters">
|
||||||
<h3>Parameters</h3>
|
<h3>Parameters</h3>
|
||||||
@foreach (var (name, val) in Value.Parameters)
|
@foreach (var (name, val) in Value.Parameters)
|
||||||
{
|
{
|
||||||
<h4>@name</h4>
|
<h4>@name</h4>
|
||||||
<ParametersControl Value="@ToList(val)" />
|
<ParametersControl Value="@ToList(val)" />
|
||||||
}
|
}
|
||||||
|
</TocMember>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (Value.Examples?.Count > 0)
|
@if (Value.Examples?.Count > 0)
|
||||||
{
|
{
|
||||||
|
<TocMember Title="Examples">
|
||||||
<h3>Examples</h3>
|
<h3>Examples</h3>
|
||||||
@foreach (var (name, val) in Value.Examples)
|
@foreach (var (name, val) in Value.Examples)
|
||||||
{
|
{
|
||||||
<ExampleControl Example="@val" Name="@name"/>
|
<ExampleControl Example="@val" Name="@name"/>
|
||||||
}
|
}
|
||||||
|
</TocMember>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<CascadingValue Name="OpenAPIUI_ExpandoTree_Parent" Value="_anchor">
|
<CascadingValue Name="OpenAPIUI_TOC_Parent" Value="_anchor">
|
||||||
<div class="expander @Class">
|
<div id="@_anchor" class="expander @Class">
|
||||||
<div class="ex-header @HeaderClass">
|
<div class="ex-header @HeaderClass">
|
||||||
@Title
|
@Title
|
||||||
<div onclick="@(() => Toggle())">
|
<div onclick="@(() => Toggle())">
|
||||||
@ -36,9 +36,11 @@
|
|||||||
public string HeaderClass { get; set; } = "";
|
public string HeaderClass { get; set; } = "";
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Class { get; set; } = "";
|
public string Class { get; set; } = "";
|
||||||
|
[Parameter]
|
||||||
|
public bool AddToTOC { get; set; } = false;
|
||||||
|
|
||||||
[CascadingParameter(Name = "OpenAPIUI_ExpandoTree")] public IExpandoTree Tree { get; set; } = null!;
|
[CascadingParameter(Name = "OpenAPIUI_TOC")] public ITableOfContentsTree Tree { get; set; } = null!;
|
||||||
[CascadingParameter(Name = "OpenAPIUI_ExpandoTree_Parent")] public string Parent { get; set; } = "";
|
[CascadingParameter(Name = "OpenAPIUI_TOC_Parent")] public string Parent { get; set; } = "";
|
||||||
|
|
||||||
private string _anchor = $"anc{Random.Shared.Next():X8}";
|
private string _anchor = $"anc{Random.Shared.Next():X8}";
|
||||||
|
|
||||||
@ -47,14 +49,19 @@
|
|||||||
if (!firstRender)
|
if (!firstRender)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (AddToTOC)
|
||||||
|
{
|
||||||
Tree.Add(Title, _anchor, Parent, Collapsed);
|
Tree.Add(Title, _anchor, Parent, Collapsed);
|
||||||
Collapsed = Tree.IsCollapsed(Title);
|
Collapsed = Tree.IsCollapsed(Title);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Toggle()
|
void Toggle()
|
||||||
{
|
{
|
||||||
Collapsed = !Collapsed;
|
Collapsed = !Collapsed;
|
||||||
|
if ( AddToTOC )
|
||||||
Tree.Collapse(_anchor, Collapsed);
|
Tree.Collapse(_anchor, Collapsed);
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
@if (Value != null)
|
@if (Value != null)
|
||||||
{
|
{
|
||||||
|
<TocMember Title="Header">
|
||||||
|
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1 class="h-title">@Value.Title <span class="h-version">@Value.Version</span></h1>
|
<h1 class="h-title">@Value.Title <span class="h-version">@Value.Version</span></h1>
|
||||||
<div class="h-contact">
|
<div class="h-contact">
|
||||||
@ -33,6 +35,8 @@
|
|||||||
<h2>Description</h2>
|
<h2>Description</h2>
|
||||||
<MarkdownControl Value="@Value.Description"/>
|
<MarkdownControl Value="@Value.Description"/>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
</TocMember>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
@if (Value != null)
|
<TocMember Title="@TocTitle" Anchor="@_anchor">
|
||||||
|
@if (Value != null)
|
||||||
{
|
{
|
||||||
<div class="op-header @OperationClass" @onclick="Expand">
|
<div id="@_anchor" class="op-header @OperationClass" @onclick="Expand">
|
||||||
<div class="op-type">@Operation</div>
|
<div class="op-type">@Operation</div>
|
||||||
<div class="spacer op-header-text">-</div>
|
<div class="spacer op-header-text">-</div>
|
||||||
<div class="op-header-text" id="@Value.OperationId">@Endpoint</div>
|
<div class="op-header-text" id="@Value.OperationId">@Endpoint</div>
|
||||||
@ -17,7 +18,7 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (_expanded)
|
@if (!Collapsed)
|
||||||
{
|
{
|
||||||
<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M18 15L12 9L6 15" stroke="var(--oa-fg-lighter)" stroke-width="2" />
|
<path d="M18 15L12 9L6 15" stroke="var(--oa-fg-lighter)" stroke-width="2" />
|
||||||
@ -31,7 +32,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@if ( _expanded )
|
@if (!Collapsed)
|
||||||
{
|
{
|
||||||
<div class="operation">
|
<div class="operation">
|
||||||
|
|
||||||
@ -64,6 +65,7 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
</TocMember>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter]
|
[Parameter]
|
||||||
@ -73,13 +75,20 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string Endpoint { get; set; } = "";
|
public string Endpoint { get; set; } = "";
|
||||||
|
|
||||||
|
[CascadingParameter(Name = "OpenAPIUI_TOC")] public ITableOfContentsTree Tree { get; set; } = null!;
|
||||||
|
[CascadingParameter(Name = "OpenAPIUI_TOC_Parent")] public string Parent { get; set; } = "";
|
||||||
|
|
||||||
|
private string _anchor = $"op_anc{Random.Shared.Next():X8}";
|
||||||
|
private string TocTitle => $"{Endpoint} - [{Operation.ToString().ToUpper()}] {Value?.Summary}";
|
||||||
|
|
||||||
private string OperationClass => $"op-{Operation.ToString().ToLower()}";
|
private string OperationClass => $"op-{Operation.ToString().ToLower()}";
|
||||||
|
|
||||||
private bool _expanded = true;
|
private bool Collapsed => Tree.IsCollapsed(_anchor);
|
||||||
|
|
||||||
private void Expand()
|
private void Expand()
|
||||||
{
|
{
|
||||||
_expanded = !_expanded;
|
var collapsed = !Tree.IsCollapsed(_anchor);
|
||||||
|
Tree.Collapse(_anchor, collapsed);
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
@if (!string.IsNullOrWhiteSpace(Key) || Value != null)
|
@if (!string.IsNullOrWhiteSpace(Key) || Value != null)
|
||||||
{
|
{
|
||||||
|
<TocMember Title="@Key">
|
||||||
@if (!string.IsNullOrWhiteSpace(@Value?.Summary) || !string.IsNullOrWhiteSpace(Value?.Description))
|
@if (!string.IsNullOrWhiteSpace(@Value?.Summary) || !string.IsNullOrWhiteSpace(Value?.Description))
|
||||||
{
|
{
|
||||||
<div class="pa-header">
|
<div class="pa-header">
|
||||||
@ -30,6 +31,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
</TocMember>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
@if (Value != null && Value.Count > 0)
|
@if (Value != null && Value.Count > 0)
|
||||||
{
|
{
|
||||||
|
<TocMember Title="Servers">
|
||||||
<h2>Servers</h2>
|
<h2>Servers</h2>
|
||||||
<table class="servers">
|
<table class="servers">
|
||||||
@foreach (var server in Value)
|
@foreach (var server in Value)
|
||||||
@ -57,6 +58,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</table>
|
</table>
|
||||||
|
</TocMember>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|||||||
48
BlazorOpenApi/Controls/TableOfContents.razor
Normal file
48
BlazorOpenApi/Controls/TableOfContents.razor
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
@inject IJSRuntime _js;
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
<div class="@Class">
|
||||||
|
<a @onclick="(async() => await ScrolltoAnchor())">@Title</a>
|
||||||
|
@foreach (var child in Tree.GetChildren(Anchor))
|
||||||
|
{
|
||||||
|
<TableOfContents Title="@child.Name" Anchor="@child.Anchor" class="toc-level" Tree="@Tree"/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code{
|
||||||
|
[Parameter] public string Class { get; set; } = "toc-level";
|
||||||
|
[Parameter] public string Anchor { get; set; } = "";
|
||||||
|
[Parameter] public string Title { get; set; } = "";
|
||||||
|
[Parameter] public ITableOfContentsTree Tree { get; set; } = null!;
|
||||||
|
|
||||||
|
private string AdaptedTitle => string.IsNullOrWhiteSpace(Title) ? "Root" : Title;
|
||||||
|
private bool _initialized;
|
||||||
|
|
||||||
|
protected override void OnParametersSet()
|
||||||
|
{
|
||||||
|
base.OnParametersSet();
|
||||||
|
if (Tree != null && !_initialized)
|
||||||
|
{
|
||||||
|
Tree.Changed += OnTocChanged;
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Tree != null)
|
||||||
|
{
|
||||||
|
Tree.Changed -= OnTocChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTocChanged(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ScrolltoAnchor()
|
||||||
|
{
|
||||||
|
await _js.InvokeVoidAsync("ScrollTo", Anchor);
|
||||||
|
}
|
||||||
|
}
|
||||||
45
BlazorOpenApi/Controls/TocMember.razor
Normal file
45
BlazorOpenApi/Controls/TocMember.razor
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
@if (string.IsNullOrWhiteSpace(Anchor))
|
||||||
|
{
|
||||||
|
<CascadingValue Name="OpenAPIUI_TOC_Parent" Value="@_anchor">
|
||||||
|
<div id="@_anchor">
|
||||||
|
@if (ChildContent != null)
|
||||||
|
{
|
||||||
|
@ChildContent
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</CascadingValue>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<CascadingValue Name="OpenAPIUI_TOC_Parent" Value="@Anchor">
|
||||||
|
<div>
|
||||||
|
@if (ChildContent != null)
|
||||||
|
{
|
||||||
|
@ChildContent
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</CascadingValue>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@code{
|
||||||
|
[Parameter] public string Title { get; set; } = "";
|
||||||
|
[Parameter] public string Anchor { get; set; } = "";
|
||||||
|
[Parameter] public bool Collapsed { get; set; }
|
||||||
|
|
||||||
|
[Parameter] public RenderFragment? ChildContent { get; set; }
|
||||||
|
|
||||||
|
[CascadingParameter(Name = "OpenAPIUI_TOC")] public ITableOfContentsTree Tree { get; set; } = null!;
|
||||||
|
[CascadingParameter(Name = "OpenAPIUI_TOC_Parent")] public string Parent { get; set; } = "";
|
||||||
|
|
||||||
|
private string _anchor = $"anc{Random.Shared.Next():X8}";
|
||||||
|
|
||||||
|
protected override void OnAfterRender(bool firstRender)
|
||||||
|
{
|
||||||
|
if (!firstRender)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Tree.Add(Title, string.IsNullOrWhiteSpace(Anchor) ? _anchor : Anchor, Parent, Collapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -6,21 +6,25 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace BlazorOpenApi;
|
namespace BlazorOpenApi;
|
||||||
|
|
||||||
public class ExpandoTreeNode
|
public class TocTreeNode
|
||||||
{
|
{
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
public string Anchor { get; set; } = string.Empty;
|
public string Anchor { get; set; } = string.Empty;
|
||||||
public string ParentAnchor { get; set; } = string.Empty;
|
public string ParentAnchor { get; set; } = string.Empty;
|
||||||
public bool Collapsed { get; set; }
|
public bool Collapsed { get; set; }
|
||||||
|
|
||||||
|
public override string ToString() => $"Name: {Name}, Anchor: {Anchor}, ParentAnchor: {ParentAnchor}, Collapsed: {Collapsed}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IExpandoTree
|
public interface ITableOfContentsTree
|
||||||
{
|
{
|
||||||
|
public event EventHandler Changed;
|
||||||
|
|
||||||
void Add(string name, string anchor, string parentAnchor, bool collapsed);
|
void Add(string name, string anchor, string parentAnchor, bool collapsed);
|
||||||
void Collapse(string anchor, bool collapsed);
|
void Collapse(string anchor, bool collapsed);
|
||||||
bool IsCollapsed(string anchor);
|
bool IsCollapsed(string anchor);
|
||||||
bool Exists(string anchor);
|
bool Exists(string anchor);
|
||||||
ExpandoTreeNode[] GetChildren(string anchor);
|
TocTreeNode[] GetChildren(string anchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
//implement IExpandoTree
|
//implement IExpandoTree
|
||||||
@ -2,6 +2,7 @@
|
|||||||
@using Microsoft.OpenApi.Models
|
@using Microsoft.OpenApi.Models
|
||||||
@using Microsoft.OpenApi.Readers
|
@using Microsoft.OpenApi.Readers
|
||||||
|
|
||||||
|
<script src="_content/BlazorOpenApi/js/BlazorOpenAPI.js"></script>
|
||||||
|
|
||||||
@if (Palette != null )
|
@if (Palette != null )
|
||||||
{
|
{
|
||||||
@ -10,29 +11,36 @@
|
|||||||
|
|
||||||
<div class="openapi-ui">
|
<div class="openapi-ui">
|
||||||
<CascadingValue Value="@_api" IsFixed="true">
|
<CascadingValue Value="@_api" IsFixed="true">
|
||||||
<CascadingValue Name="OpenAPIUI_ExpandoTree" Value="_tree" IsFixed="true">
|
<CascadingValue Name="OpenAPIUI_TOC" Value="@_tree" IsFixed="true">
|
||||||
|
|
||||||
|
<TableOfContents Tree="@_tree" />
|
||||||
|
|
||||||
<HeaderControl Value="@_api.Info" DownloadUrl="@Url" />
|
<HeaderControl Value="@_api.Info" DownloadUrl="@Url" />
|
||||||
<ServersControl Value="@_api.Servers" />
|
<ServersControl Value="@_api.Servers" />
|
||||||
@if (_api.Paths?.Count > 0)
|
@if (_api.Paths?.Count > 0)
|
||||||
{
|
{
|
||||||
|
<TocMember Title="Endpoints">
|
||||||
<h2>Endpoints</h2>
|
<h2>Endpoints</h2>
|
||||||
foreach (var path in _api.Paths)
|
@foreach (var path in _api.Paths)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(path.Key) || path.Value != null)
|
if (!string.IsNullOrWhiteSpace(path.Key) || path.Value != null)
|
||||||
{
|
{
|
||||||
<PathControl Key="@path.Key" Value="@path.Value" />
|
<PathControl Key="@path.Key" Value="@path.Value" />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
</TocMember>
|
||||||
}
|
}
|
||||||
@if (_api.Components != null)
|
@if (_api.Components != null)
|
||||||
{
|
{
|
||||||
|
<TocMember Title="Components">
|
||||||
<h2>Components</h2>
|
<h2>Components</h2>
|
||||||
<ComponentsControl Value="@_api.Components" />
|
<ComponentsControl Value="@_api.Components" />
|
||||||
|
</TocMember>
|
||||||
}
|
}
|
||||||
|
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
@ -44,10 +52,17 @@
|
|||||||
private string _loadedFor = "";
|
private string _loadedFor = "";
|
||||||
|
|
||||||
private OpenApiDocument _api = new();
|
private OpenApiDocument _api = new();
|
||||||
private IExpandoTree _tree = new ExpandoTree();
|
private ITableOfContentsTree _tree = new TableOfContentsTree();
|
||||||
|
|
||||||
private MarkupString PaletteStr => Palette?.AsMarkupString ?? new();
|
private MarkupString PaletteStr => Palette?.AsMarkupString ?? new();
|
||||||
|
|
||||||
|
protected override void OnAfterRender(bool firstRender)
|
||||||
|
{
|
||||||
|
if (!firstRender)
|
||||||
|
return;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
var loadedFromUrl = _loadedFor == Url && !string.IsNullOrWhiteSpace(Url);
|
var loadedFromUrl = _loadedFor == Url && !string.IsNullOrWhiteSpace(Url);
|
||||||
|
|||||||
@ -4,19 +4,26 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace BlazorOpenApi;
|
namespace BlazorOpenApi;
|
||||||
|
|
||||||
internal class ExpandoTree : IExpandoTree
|
internal class TableOfContentsTree : ITableOfContentsTree
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, ExpandoTreeNode> _nodes = new();
|
private readonly Dictionary<string, TocTreeNode> _nodes = new();
|
||||||
private readonly List<string> _order = new();
|
private readonly List<string> _order = new();
|
||||||
|
|
||||||
|
public event EventHandler Changed;
|
||||||
|
|
||||||
public void Add(string name, string anchor, string parentAnchor, bool collapsed)
|
public void Add(string name, string anchor, string parentAnchor, bool collapsed)
|
||||||
{
|
{
|
||||||
if (_nodes.ContainsKey(anchor))
|
if (_nodes.ContainsKey(anchor))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"A node with anchor '{anchor}' already exists.");
|
throw new InvalidOperationException($"A node with anchor '{anchor}' already exists for {name}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var node = new ExpandoTreeNode
|
if ( parentAnchor != "" && !_nodes.ContainsKey(parentAnchor))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"A parent anchor '{parentAnchor}' is not registered for {name}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var node = new TocTreeNode
|
||||||
{
|
{
|
||||||
Name = name,
|
Name = name,
|
||||||
Anchor = anchor,
|
Anchor = anchor,
|
||||||
@ -26,6 +33,11 @@ internal class ExpandoTree : IExpandoTree
|
|||||||
|
|
||||||
_nodes[anchor] = node;
|
_nodes[anchor] = node;
|
||||||
_order.Add(anchor);
|
_order.Add(anchor);
|
||||||
|
|
||||||
|
if ( Changed != null )
|
||||||
|
{
|
||||||
|
Changed(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Collapse(string anchor, bool collapsed)
|
public void Collapse(string anchor, bool collapsed)
|
||||||
@ -47,7 +59,7 @@ internal class ExpandoTree : IExpandoTree
|
|||||||
|
|
||||||
public bool Exists(string anchor) => _nodes.ContainsKey(anchor);
|
public bool Exists(string anchor) => _nodes.ContainsKey(anchor);
|
||||||
|
|
||||||
public ExpandoTreeNode[] GetChildren(string anchor) => _order
|
public TocTreeNode[] GetChildren(string anchor) => _order
|
||||||
.Where(x => _nodes[x].ParentAnchor == anchor)
|
.Where(x => _nodes[x].ParentAnchor == anchor)
|
||||||
.Select(x => _nodes[x])
|
.Select(x => _nodes[x])
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@ -1,4 +1,9 @@
|
|||||||
.descriminator {}
|
.toc-level {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.descriminator {
|
||||||
|
}
|
||||||
|
|
||||||
.example {}
|
.example {}
|
||||||
.e-item {}
|
.e-item {}
|
||||||
|
|||||||
10
BlazorOpenApi/wwwroot/js/BlazorOpenAPI.js
Normal file
10
BlazorOpenApi/wwwroot/js/BlazorOpenAPI.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
function ScrollTo(elementId) {
|
||||||
|
var element = document.getElementById(elementId);
|
||||||
|
if (element != null) {
|
||||||
|
element.scrollIntoView({
|
||||||
|
block: "start"
|
||||||
|
// behavior: 'smooth'
|
||||||
|
});
|
||||||
|
window.scrollBy(0, -64); // Adjust scrolling with a negative value here
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -20,13 +20,13 @@
|
|||||||
<MudSwitch @bind-Value="@IsDarkMode" Color="MudBlazor.Color.Primary" Class="ma-4" T="bool" Label="Dark Mode" />
|
<MudSwitch @bind-Value="@IsDarkMode" Color="MudBlazor.Color.Primary" Class="ma-4" T="bool" Label="Dark Mode" />
|
||||||
</div>
|
</div>
|
||||||
</MudDrawer>
|
</MudDrawer>
|
||||||
<MudMainContent>
|
|
||||||
<CascadingValue Value="@IsDarkMode">
|
<CascadingValue Value="@IsDarkMode">
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="pt-2">
|
<MudMainContent>
|
||||||
|
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge">
|
||||||
@Body
|
@Body
|
||||||
</MudContainer>
|
</MudContainer>
|
||||||
</CascadingValue>
|
|
||||||
</MudMainContent>
|
</MudMainContent>
|
||||||
|
</CascadingValue>
|
||||||
</MudLayout>
|
</MudLayout>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user