Skip to content

feat: generic components, redirects and frontmatter page titles - #30

Merged
Shewart merged 5 commits into
mainfrom
feat/generics-redirects-page-title
Oct 2, 2026
Merged

Shewart merged 5 commits into
mainfrom
feat/generics-redirects-page-title

Conversation

@Shewart

@Shewart Shewart commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes out the ShellDocs backlog from building the ShellUI docs.

Added

  • Generic components in markdown. Generic components register under their bare name. razor:preview, inline tags and <ComponentPreview> close them from a type-parameter attribute, as Razor does (<BarChart TItem="SalesRow" />).

    • Type arguments take C# spellings: aliases, T?, T[], List<T>, simple or full names.
    • Without a type argument, ShellDocs uses object when the constraints allow it, with a warning. Otherwise it renders an inline error.
    • A non-generic component with the same name keeps the tag.
    • <AutoTypeTable> lists type parameters.
  • Redirects. URLs that aren't pages are redirected:

    • content folders and version roots go to their first page;
    • unversioned URLs that exist in the latest version go to that page;
    • o.AddRedirect(from, to, permanent) adds segment-aware prefix rules.

    An IStartupFilter adds middleware that answers before routing, so dotted version roots work. It sends 302 for computed redirects and 301 for rules. shelldocs build writes the same redirects as static redirect pages. o.EnableRedirects = false opts out.

  • o.RenderPageTitle. Renders the frontmatter title and description as the page header when the body has no # Heading. Off by default.

Changed

  • ShellDocs.Components references the ASP.NET Core shared framework, for the middleware, instead of the Components.Web package. It already read content from disk.

Fixed

  • shelldocs build prerendered "Page not found" pages when publish copied meta.json but not the .md files. Build now fills in missing content files, and the example csproj is fixed.

Testing

  • dotnet build: 0 warnings. dotnet test: 303 passing.
  • New test files: GenericComponentTests, RedirectTests, PageTitleTests.
  • Example app: every redirect case returns the expected 302 with its target. Pages are untouched and the query string is kept.
  • Generic previews render with the right closed types.
  • A real shelldocs build wrote 25 pages, none "Page not found", and 14 redirect pages.

…nentPreview

RegisterComponentsFromAssembly skipped generic definitions, so <BarChart TItem="…">, data tables and typed selects couldn't be used from markdown. Generic components now register under their bare name and SlotRenderer.Component closes them per use from attributes named after the type parameters, as Razor does. Type arguments accept C# spellings (aliases, T?, T[], List<T>, simple or full names). Without one, object is used when the constraints allow it, with a warning; otherwise an inline .shelldocs-render-error replaces the component instead of breaking the page. A non-generic component with the same name keeps the tag, and AutoTypeTable lists type parameters.
Folder URLs and version roots go to their first page (/docs prefers unversioned pages, then the latest version), unversioned URLs that exist in the latest version go there, and AddRedirect adds segment-aware prefix rules (301; computed ones are 302). Middleware added through an IStartupFilter answers them before routing, so dotted version roots that {*Path:nonfile} can't match work too, and serves /_shelldocs/redirects.json, which shelldocs build writes out as static redirect pages. EnableRedirects = false opts out. ShellDocs.Components now references the ASP.NET Core shared framework for the middleware; it already read content from disk.
A csproj with <Content Update="content/**/*.md"> publishes meta.json but no markdown, and build only mirrored content/ when the folder was missing entirely, so every page prerendered as "Page not found". Build now merges in any source content file publish didn't copy. The example project had exactly this csproj; it now uses Content Include like the init scaffold.
ShellDocsOptions.RenderPageTitle renders frontmatter title as the page heading and description as a lead paragraph when the markdown body doesn't start with its own # heading, so pages don't need a manual H1. Off by default.
CHANGELOG Unreleased entries; README sections on redirects, generic components and RenderPageTitle; ARCHITECTURE on DocsRedirects, the middleware, generic closing and the build steps; installation and markdown-syntax pages, with a generic ValueBadge example component.
@Shewart
Shewart merged commit 5670eba into main Oct 2, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant