fix(init): bootstrap host with render mode, theme script, full theme CSS#15
Merged
Conversation
Added assertions in the CI workflow to verify that the `shellui init` command correctly patches the `App.razor` file and writes the full theme to `input.css`. This ensures that the initialization process produces a working host with the expected configurations and theme variables, improving the reliability of the scaffolding process.
Introduced a new test class, InitBootstrapTests, to validate the functionality of the InitService's methods for rewriting Razor files. The tests ensure that the `RewriteAppRazor` and `RewriteWasmIndexHtml` methods correctly inject necessary scripts and theme elements, maintain idempotency, and preserve existing render modes. This addition enhances test coverage for the initialization process in ShellUI.
…ndex.html Added the BootstrapHostAsync method to the InitService, which handles the patching of Components/App.razor and wwwroot/index.html for Blazor applications. This method ensures the correct injection of theme bootstrap scripts and the shellui.js script tag, enhancing the initialization process. Updated the status messages to reflect these changes and improved the overall user experience during setup.
…o tests Added a project reference for ShellUI.CLI in the ShellUI.Tests project to facilitate testing. Additionally, made internals of ShellUI.CLI visible to ShellUI.Tests, enabling comprehensive unit testing of internal components and improving test coverage.
Updated the CssTemplates class to replace the InputCss property with FullThemeCss, introducing a new InputCssNpm property. Enhanced TailwindConfigJsNpm with comments for clarity on theme handling and removed unnecessary theme configurations. This refactor improves the overall structure and maintainability of the CSS templates, aligning with Tailwind v4's requirements for theme management.
Updated InitBootstrapTests to include a new test for handling bare Blazor script tags in the RewriteAppRazor method. This ensures compatibility with older templates that do not use the @assets[] wrapper. Additionally, modified the InitService to support both modern and bare script tag formats, improving the robustness of the Razor file rewriting process.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
shellui initproduced a non-functional project: no@rendermodeso interactive components were inert, no theme script so light/dark caused FOUC, only@import "tailwindcss";ininput.cssso component CSS variables were undefined (everything rendered unstyled black/white), and a stalehsl(var(--x))color block in the Tailwind v4 npm config. Users had to manually patch four files before any component worked.This PR makes
shellui initproduce a working app out of the box and adds tests + CI assertions so the next regression here fails fast.Changes
Init now patches the host
src/ShellUI.CLI/Services/InitService.cs— newBootstrapHostAsyncstep between component install and MSBuild targets. Dispatches to one of two patchers based on detected project type:Blazor Web App / Server / SSR (
Components/App.razor):<HeadOutlet />→<HeadOutlet @rendermode="InteractiveServer" /><Routes />→<Routes @rendermode="InteractiveServer" /><script>into<head>that readslocalStorage.themeand setsdocumentElement.classList.add('dark')before paint — prevents the light flash on dark pages<script src="shellui.js"></script>immediately before_framework/blazor.web.jssowindow.ShellUI.*(used byThemeToggle,CopyButton,InputOTP,FileUpload,Command) is defined before Blazor calls into itBlazor WebAssembly standalone (
wwwroot/index.html): same theme bootstrap +shellui.jsinjection (no@rendermodesince WASM uses<Router>not<Routes />).The "remember to add
<script src=\"shellui.js\">" reminder in the success message is gone — it's automatic now.Render-mode injection is conservative
The regex only matches the bare default form (
<HeadOutlet />,<Routes />). If the user (or another tool) already set@rendermode="InteractiveAuto"or any other attribute, the regex doesn't match and the tag is left alone. Idempotent — a secondshellui initis a no-op.shellui-sidebar.jsis never injected as a script tag. It's atype=moduleloaded bySidebarProvider.razorviaJSRuntime.InvokeAsync<IJSObjectReference>("import", "./shellui-sidebar.js")— a<script>tag would either double-load it or fail silently because the file usesexport function. CI now asserts it's absent.Default theme ships, not just
@import "tailwindcss"src/ShellUI.Templates/CssTemplates.cs—InputCssandInputCssNpmnow emit the full default theme::rootlight vars,.darkdark vars,@theme inlinemapping for Tailwind v4,@custom-variant dark (&:is(.dark *));,@layer basedefaults, and the Loading-component animation keyframes. Theme values are tweakcn-compatible — users can paste a new:root/.darkblock over this to retheme.Tailwind v4 npm config no longer carries the v3 wrapper
TailwindConfigJsNpmno longer has thecolors: { primary: { DEFAULT: 'hsl(var(--primary))' } }block. Tailwind v4 reads the palette via@theme inlineininput.css— duplicating it in the config file did nothing useful and was confusing.Tests
New
ShellUI.Tests/InitBootstrapTests.cs— 7 tests covering the rewriter directly:HeadOutletandRoutes<head>(positionally verified, not just "contains")shellui.jsscript tag precedesblazor.web.js(ordering matters)RewriteAppRazortwice produces identical output (idempotent)@rendermode="InteractiveAuto"is preserved — we don't overwriteindex.htmlgets theme bootstrap +shellui.jsordered correctlyPlumbing:
ShellUI.CLI.csprojgetsInternalsVisibleTo("ShellUI.Tests")so the rewriter methods stayinternalinstead of bloating the public CLI API surface.CI smoke step extended
.github/workflows/ci.yml— aftershellui init, the workflow nowgreps the producedComponents/App.razorandwwwroot/input.cssfor the expected markers and fails loudly if any are missing:HeadOutlet @rendermode="InteractiveServer"Routes @rendermode="InteractiveServer"ShellUI theme bootstrap<script src="shellui.js"></script>shellui-sidebar.jsmust not appear in App.razorinput.csscontains@theme inline,:root, and.darkblocksThen proceeds with the existing
shellui add chart pie-chart dashboard-02+dotnet buildend-to-end.Verification
dotnet test ShellUI.Tests— 25/25 passing (7 new bootstrap tests + 18 from previous branches)dotnet new blazor, ran the CLI from this branch'sbin/Release, confirmedApp.razorwas patched,dotnet buildclean, theme toggle flips light/dark and persists across reload, no FOUC on a dark-themed pageTest plan
dotnet new blazor→ install the prerelease CLI tool →shellui init→ diffComponents/App.razoragainst the pre-init version; confirm all four markers landedshellui init --forceon the same project — confirm App.razor is unchanged (idempotency)<HeadOutlet @rendermode="InteractiveAuto" />inApp.razor, runshellui init, confirmInteractiveAutois preserveddotnet new blazorwasm→shellui init→ confirmwwwroot/index.htmlpatched, App.razor untouched