Repository navigation
Expand file tree
/
Copy pathServiceCollectionExtensions.cs
More file actions
75 lines (67 loc) · 3.4 KB
/
Copy pathServiceCollectionExtensions.cs
File metadata and controls
75 lines (67 loc) · 3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ShellDocs.Components.Chrome;
using ShellDocs.Components.Content;
using ShellDocs.Components.Llms;
using ShellDocs.Core;
using ShellDocs.Markdown;
namespace ShellDocs.Components;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddShellDocs(this IServiceCollection services, Action<ShellDocsOptions>? configure = null)
{
var options = new ShellDocsOptions();
configure?.Invoke(options);
services.AddSingleton(options);
services.AddScoped<ThemeState>();
services.AddScoped<CodeGroupSyncState>();
services.AddScoped<DocsPageState>();
/* Built-in content primitives are always available to markdown. Render
machinery (MarkdownContent, PreviewFrame) opts out via [ShellDocsIgnore]. */
options.AddBuiltInComponents(typeof(Callout).Assembly, t => t.Namespace == "ShellDocs.Components.Content");
services.AddSingleton<TypeRegistry>(sp =>
{
var registry = options.BuildTypeRegistry();
LogCollisions(registry, options, sp.GetService<ILoggerFactory>()?.CreateLogger("ShellDocs"));
return registry;
});
services.AddSingleton<MarkdownRenderer>(sp => new MarkdownRenderer(sp.GetRequiredService<TypeRegistry>()));
services.AddSingleton<NavigationGraph>(_ =>
{
if (!Directory.Exists(options.ContentRoot))
{
return new NavigationGraph(new NavigationNode { Url = "/", Kind = NodeKind.Section });
}
return NavigationGraphBuilder.Build(options.ContentRoot);
});
services.AddSingleton<SearchIndex>(sp => SearchIndex.FromGraph(sp.GetRequiredService<NavigationGraph>()));
services.AddSingleton<DocsVersionResolver>();
// Before the redirects, so a page's .md is never redirected.
if (options.LlmsTxt is not null)
{
services.AddSingleton(sp => new LlmsTxtFiles(options, sp.GetRequiredService<NavigationGraph>(),
sp.GetRequiredService<TypeRegistry>(), sp.GetRequiredService<DocsVersionResolver>(), sp.GetService<IWebHostEnvironment>()));
services.AddTransient<IStartupFilter, LlmsTxtStartupFilter>();
}
services.AddSingleton<DocsRedirects>();
if (options.EnableRedirects)
services.AddTransient<IStartupFilter, DocsRedirectStartupFilter>();
services.AddSingleton<DocsSearchIndexFile>();
services.AddTransient<IStartupFilter, DocsSearchStartupFilter>();
return services;
}
private static void LogCollisions(TypeRegistry registry, ShellDocsOptions options, ILogger? logger)
{
if (logger is null) return;
foreach (var c in registry.Collisions)
{
if (options.BuiltInComponents.Contains(c.Replaced))
logger.LogInformation("ShellDocs: <{Tag}> renders {Winner}; the built-in stays available as <{Alias}>.",
c.TagName, c.Winner.FullName, ShellDocsOptions.BuiltInAliasPrefix + c.Replaced.Name);
else
logger.LogWarning("ShellDocs: <{Tag}> is registered by both {Replaced} and {Winner}; the later one wins. Use RegisterComponent<T>(\"Alias\") to expose the other.",
c.TagName, c.Replaced.FullName, c.Winner.FullName);
}
}
}