Skip to content

Commit 436f9e3

Browse files
committed
POC rendering separate .main.html pages for use with htmx
(cherry picked from commit baa0e4f)
1 parent d387acc commit 436f9e3

File tree

7 files changed

+173
-13
lines changed

7 files changed

+173
-13
lines changed

src/Elastic.Markdown/DocumentationGenerator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ private async Task CopyFileFsAware(DocumentationFile file, IFileInfo outputFile,
252252
public async Task<string?> RenderLayout(MarkdownFile markdown, Cancel ctx)
253253
{
254254
await DocumentationSet.Tree.Resolve(ctx);
255-
return await HtmlWriter.RenderLayout(markdown, ctx);
255+
var pageHtml = await HtmlWriter.RenderPageHtml(markdown, ctx);
256+
return await HtmlWriter.RenderLayout(markdown, pageHtml, ctx);
256257
}
257258
}

src/Elastic.Markdown/Slices/HtmlWriter.cs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,15 @@ private async Task<string> RenderNavigation(MarkdownFile markdown, Cancel ctx =
2323

2424
private string? _renderedNavigation;
2525

26-
public async Task<string> RenderLayout(MarkdownFile markdown, Cancel ctx = default)
26+
public static async Task<string> RenderPageHtml(MarkdownFile markdown, Cancel ctx = default)
2727
{
2828
var document = await markdown.ParseFullAsync(ctx);
2929
var html = MarkdownFile.CreateHtml(document);
30+
return html;
31+
}
32+
33+
public async Task<string> RenderLayout(MarkdownFile markdown, string markdownHtml, Cancel ctx = default)
34+
{
3035
await DocumentationSet.Tree.Resolve(ctx);
3136
_renderedNavigation ??= await RenderNavigation(markdown, ctx);
3237

@@ -42,7 +47,7 @@ public async Task<string> RenderLayout(MarkdownFile markdown, Cancel ctx = defau
4247
{
4348
Title = markdown.Title ?? "[TITLE NOT SET]",
4449
TitleRaw = markdown.TitleRaw ?? "[TITLE NOT SET]",
45-
MarkdownHtml = html,
50+
MarkdownHtml = markdownHtml,
4651
PageTocItems = [.. markdown.TableOfContents.Values],
4752
Tree = DocumentationSet.Tree,
4853
CurrentDocument = markdown,
@@ -57,6 +62,34 @@ public async Task<string> RenderLayout(MarkdownFile markdown, Cancel ctx = defau
5762
return await slice.RenderAsync(cancellationToken: ctx);
5863
}
5964

65+
66+
public async Task<string> RenderPage(MarkdownFile markdown, string markdownHtml, Cancel ctx = default)
67+
{
68+
var previous = DocumentationSet.GetPrevious(markdown);
69+
var next = DocumentationSet.GetNext(markdown);
70+
71+
var remote = DocumentationSet.Context.Git.RepositoryName;
72+
var branch = DocumentationSet.Context.Git.Branch;
73+
var path = Path.Combine(DocumentationSet.RelativeSourcePath, markdown.RelativePath);
74+
var editUrl = $"https://github.com/elastic/{remote}/edit/{branch}/{path}";
75+
76+
var slice = Page.Create(new MainViewModel
77+
{
78+
Title = markdown.Title ?? "[TITLE NOT SET]",
79+
TitleRaw = markdown.TitleRaw ?? "[TITLE NOT SET]",
80+
MarkdownHtml = markdownHtml,
81+
PageTocItems = [.. markdown.TableOfContents.Values],
82+
CurrentDocument = markdown,
83+
PreviousDocument = previous,
84+
NextDocument = next,
85+
UrlPathPrefix = markdown.UrlPathPrefix,
86+
Applies = markdown.YamlFrontMatter?.AppliesTo,
87+
GithubEditUrl = editUrl,
88+
AllowIndexing = DocumentationSet.Context.AllowIndexing && !markdown.Hidden
89+
});
90+
return await slice.RenderAsync(cancellationToken: ctx);
91+
}
92+
6093
public async Task WriteAsync(IFileInfo outputFile, MarkdownFile markdown, Cancel ctx = default)
6194
{
6295
if (outputFile.Directory is { Exists: false })
@@ -78,9 +111,15 @@ public async Task WriteAsync(IFileInfo outputFile, MarkdownFile markdown, Cancel
78111
? Path.GetFileNameWithoutExtension(outputFile.Name) + ".html"
79112
: Path.Combine(dir, "index.html");
80113
}
114+
var mainPath = Path.ChangeExtension(path, ".main.html");
115+
116+
var pageHtml = await RenderPageHtml(markdown, ctx);
81117

82-
var rendered = await RenderLayout(markdown, ctx);
118+
var rendered = await RenderLayout(markdown, pageHtml, ctx);
83119
await writeFileSystem.File.WriteAllTextAsync(path, rendered, ctx);
120+
121+
var renderedPage = await RenderPage(markdown, pageHtml, ctx);
122+
await writeFileSystem.File.WriteAllTextAsync(mainPath, renderedPage, ctx);
84123
}
85124

86125
}

src/Elastic.Markdown/Slices/Layout/_Breadcrumbs.cshtml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
@using Elastic.Markdown.Helpers
2-
@inherits RazorSlice<LayoutViewModel>
2+
@inherits RazorSlice<IBreadCrumbModel>
33
<ol id="breadcrumbs" class="block w-full" itemscope="" itemtype="https://schema.org/BreadcrumbList">
44
<li class="inline text-ink text-sm hover:text-ink leading-[1.2em] tracking-[-0.02em]" itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem">
5-
<a
5+
<a
66
itemprop="item"
77
href="@Model.UrlPathPrefix/"
88
hx-get="@Model.UrlPathPrefix/"
@@ -21,7 +21,7 @@
2121
<li class="inline text-gray-500 text-sm leading-[1.2em] tracking-[-0.02em]" itemprop="itemListElement" itemscope="" itemtype="https://schema.org/ListItem">
2222
<span class="px-1">/</span>
2323
<a
24-
itemprop="item"
24+
itemprop="item"
2525
href="@item.Url"
2626
hx-get="@item.Url"
2727
hx-select-oob="@Htmx.GetHxSelectOob()"

src/Elastic.Markdown/Slices/Layout/_TableOfContents.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@inherits RazorSlice<LayoutViewModel>
1+
@inherits RazorSlice<ITableOfContentsModel>
22
<aside class="sidebar hidden lg:block order-3 border-l-1 border-l-gray-200 w-80">
33
<nav id="toc-nav" class="sidebar-nav pl-6">
44
<div class="pt-6 pb-20">
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
@using Elastic.Markdown.Helpers
2+
@using Markdig
3+
@inherits RazorSliceHttpResult<MainViewModel>
4+
<div class="flex flex-col items-center px-6">
5+
<div class="container flex">
6+
@await RenderPartialAsync(_PagesNav.Create(Model))
7+
@await RenderPartialAsync(_TableOfContents.Create<ITableOfContentsModel>(Model))
8+
<main class="w-full pt-6 pb-30 px-6 order-2 relative">
9+
<div class="w-full absolute top-0 left-0 right-0 htmx-indicator" id="htmx-indicator" role="status">
10+
<div class="h-[2px] w-full overflow-hidden">
11+
<div class="progress w-full h-full bg-pink-70 left-right"></div>
12+
</div>
13+
<div class="sr-only">Loading</div>
14+
</div>
15+
<div class="content-container">
16+
@await RenderPartialAsync(_Breadcrumbs.Create<IBreadCrumbModel>(Model))
17+
</div>
18+
<article id="markdown-content" class="content-container markdown-content">
19+
@* This way it's correctly rendered as <h1>text</h1> instead of <h1><p>text</p></h1> *@
20+
@(new HtmlString(Markdown.ToHtml("# " + Model.TitleRaw)))
21+
@if (Model.Applies is not null)
22+
{
23+
await RenderPartialAsync(ApplicableTo.Create(Model.Applies));
24+
}
25+
@(new HtmlString(Model.MarkdownHtml))
26+
</article>
27+
<footer id="prev-next-nav" class="content-container mt-20">
28+
<div class="flex flex-wrap lg:flex-nowrap gap-2 mt-2">
29+
<div class="w-full">
30+
@if (Model.PreviousDocument != null)
31+
{
32+
<a
33+
href="@Model.PreviousDocument.Url"
34+
hx-get="@Model.PreviousDocument.Url"
35+
hx-select-oob="@Htmx.GetHxSelectOob()"
36+
hx-swap="none"
37+
hx-push-url="true"
38+
hx-indicator="#htmx-indicator"
39+
preload="mouseover"
40+
class="flex h-full items-center text-ink-light hover:black border-1 border-gray-300 hover:border-gray-500 rounded-lg p-6 shadow-md"
41+
>
42+
<svg class="size-6 mr-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
43+
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5"/>
44+
</svg>
45+
<div>
46+
<div class="text-xs lg:text-sm">Previous</div>
47+
<div class="text-base lg:text-xl text-black">@Model.PreviousDocument.NavigationTitle</div>
48+
</div>
49+
</a>
50+
}
51+
</div>
52+
<div class="w-full">
53+
@if (Model.NextDocument != null)
54+
{
55+
<a
56+
href="@Model.NextDocument.Url"
57+
hx-get="@Model.NextDocument.Url"
58+
hx-select-oob="@Htmx.GetHxSelectOob()"
59+
hx-swap="none"
60+
hx-push-url="true"
61+
hx-indicator="#htmx-indicator"
62+
preload="mouseover"
63+
class="flex h-full items-center justify-end text-ink-light hover:black border-1 border-gray-300 hover:border-gray-500 rounded-lg p-6 shadow-md text-right"
64+
>
65+
<div>
66+
<div class="text-xs lg:text-sm">Next</div>
67+
<div class="text-base lg:text-xl text-black">@Model.NextDocument.NavigationTitle</div>
68+
</div>
69+
<svg class="size-6 ml-2" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
70+
<path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5"/>
71+
</svg>
72+
</a>
73+
}
74+
</div>
75+
</div>
76+
</footer>
77+
</main>
78+
</div>
79+
</div>

src/Elastic.Markdown/Slices/_Layout.cshtml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<div class="flex flex-col items-center px-6">
1616
<div class="container flex">
1717
@await RenderPartialAsync(_PagesNav.Create(Model))
18-
@await RenderPartialAsync(_TableOfContents.Create(Model))
18+
@await RenderPartialAsync(_TableOfContents.Create<ITableOfContentsModel>(Model))
1919
<main class="w-full pt-6 pb-30 px-6 order-2 relative">
2020
<div class="w-full absolute top-0 left-0 right-0 htmx-indicator" id="htmx-indicator" role="status">
2121
<div class="h-[2px] w-full overflow-hidden">
@@ -24,7 +24,7 @@
2424
<div class="sr-only">Loading</div>
2525
</div>
2626
<div class="content-container">
27-
@await RenderPartialAsync(_Breadcrumbs.Create(Model))
27+
@await RenderPartialAsync(_Breadcrumbs.Create<IBreadCrumbModel>(Model))
2828
</div>
2929
<article id="markdown-content" class="content-container markdown-content">
3030
@await RenderBodyAsync()
@@ -34,7 +34,7 @@
3434
<div class="w-full">
3535
@if (Model.Previous != null)
3636
{
37-
<a
37+
<a
3838
href="@Model.Previous.Url"
3939
hx-get="@Model.Previous.Url"
4040
hx-select-oob="@Htmx.GetHxSelectOob()"
@@ -57,7 +57,7 @@
5757
<div class="w-full">
5858
@if (Model.Next != null)
5959
{
60-
<a
60+
<a
6161
href="@Model.Next.Url"
6262
hx-get="@Model.Next.Url"
6363
hx-select-oob="@Htmx.GetHxSelectOob()"

src/Elastic.Markdown/Slices/_ViewModels.cs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,47 @@
77

88
namespace Elastic.Markdown.Slices;
99

10+
public interface IBreadCrumbModel
11+
{
12+
MarkdownFile[] Parents { get; }
13+
string? UrlPathPrefix { get; }
14+
}
15+
16+
public interface ITableOfContentsModel
17+
{
18+
IReadOnlyCollection<PageTocItem> PageTocItems { get; }
19+
string? GithubEditUrl { get; }
20+
}
21+
22+
public class MainViewModel : IBreadCrumbModel, ITableOfContentsModel
23+
{
24+
public required string Title { get; init; }
25+
public required string TitleRaw { get; init; }
26+
public required string MarkdownHtml { get; init; }
27+
public required IReadOnlyCollection<PageTocItem> PageTocItems { get; init; }
28+
public required MarkdownFile CurrentDocument { get; init; }
29+
public required MarkdownFile? PreviousDocument { get; init; }
30+
public required MarkdownFile? NextDocument { get; init; }
31+
public required string? UrlPathPrefix { get; init; }
32+
public required string? GithubEditUrl { get; init; }
33+
public required ApplicableTo? Applies { get; init; }
34+
public required bool AllowIndexing { get; init; }
35+
36+
private MarkdownFile[]? _parents;
37+
public MarkdownFile[] Parents
38+
{
39+
get
40+
{
41+
if (_parents is not null)
42+
return _parents;
43+
44+
_parents = [.. CurrentDocument.YieldParents()];
45+
return _parents;
46+
}
47+
}
48+
49+
}
50+
1051
public class IndexViewModel
1152
{
1253
public required string Title { get; init; }
@@ -24,7 +65,7 @@ public class IndexViewModel
2465
public required bool AllowIndexing { get; init; }
2566
}
2667

27-
public class LayoutViewModel
68+
public class LayoutViewModel : IBreadCrumbModel, ITableOfContentsModel
2869
{
2970
/// Used to identify the navigation for the current compilation
3071
/// We want to reset users sessionStorage every time this changes to invalidate

0 commit comments

Comments
 (0)