Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 0 additions & 62 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,64 +1,2 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
*.sh text eol=lf

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary

###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
1 change: 0 additions & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
# These are supported funding model platforms
70 changes: 11 additions & 59 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,23 @@ jobs:
- name: Restore dependencies
run: dotnet restore ShellUI.slnx

# Generates src/ShellUI.Components/wwwroot/shellui-all.css fresh on every run.
# File is gitignored — the Windows + Linux Tailwind CLI binaries produce
# byte-different output, so drift-checking a committed file failed spuriously.
# Instead we regenerate and validate content properties.
# Regenerated every run: it's gitignored because Windows and Linux Tailwind builds differ byte for byte.
- name: Build precompiled CSS bundle
# Invoke via `bash` (not `./script.sh`) so we don't rely on the file's
# executable bit. Windows contributors can edit and commit without
# remembering `git update-index --chmod=+x`.
# Run through bash so the executable bit doesn't matter.
run: |
set -euxo pipefail
bash scripts/rebuild-precompiled-css.sh
BUNDLE=src/ShellUI.Components/wwwroot/shellui-all.css
test -f "$BUNDLE" || (echo "ERROR: bundle was not produced"; exit 1)

# Content assertions using grep -F (fixed-string, no regex escaping headaches).
# These catch classes of bugs we've actually shipped before — worth the paranoia.
grep -Fq -- '--background' "$BUNDLE" || (echo "ERROR: theme vars not in bundle"; exit 1)
grep -Fq '.bg-background' "$BUNDLE" || (echo "ERROR: core utility rule missing"; exit 1)
grep -Fq 'hover\:bg-accent' "$BUNDLE" || (echo "ERROR: hover: modifier rules missing"; exit 1)
grep -Fq 'state=open' "$BUNDLE" || (echo "ERROR: data-[state=open] arbitrary value not compiled"; exit 1)
grep -Fq 'px-2\.5' "$BUNDLE" || (echo "ERROR: Badge padding class px-2.5 missing (variant .cs helpers not scanned?)"; exit 1)
grep -Fq 'border-transparent' "$BUNDLE" || (echo "ERROR: border-transparent missing (variant .cs helpers not scanned?)"; exit 1)

# Size guard — keep the threshold above the current component bundle,
# but below runaway output (for example, an unminified full Tailwind base).
# Above the current bundle, below an accidental full Tailwind build.
size=$(wc -c < "$BUNDLE")
echo "precompiled bundle size: ${size} bytes"
if [ "$size" -gt 150000 ]; then
Expand All @@ -68,8 +60,7 @@ jobs:
- name: Run tests
run: dotnet test ShellUI.slnx --no-restore --no-build --configuration Release --verbosity normal

# End-to-end build of a scaffolded project — catches anything the in-process
# TemplateCompileTests miss (missing usings, dependency resolution).
# Builds a scaffolded project; catches what TemplateCompileTests can't.
- name: Smoke-test CLI scaffolding
shell: bash
run: |
Expand All @@ -84,8 +75,6 @@ jobs:
cd SmokeApp
shellui init --tailwind standalone --yes

# Assert init produced a working host: App.razor patched with render mode,
# theme bootstrap, and shellui.js script tag.
grep -q 'HeadOutlet @rendermode="InteractiveServer"' Components/App.razor || (echo "init did not patch HeadOutlet @rendermode"; exit 1)
grep -q 'Routes @rendermode="InteractiveServer"' Components/App.razor || (echo "init did not patch Routes @rendermode"; exit 1)
grep -q 'ShellUI theme bootstrap' Components/App.razor || (echo "init did not inject theme bootstrap"; exit 1)
Expand All @@ -95,32 +84,22 @@ jobs:
exit 1
fi

# Assert input.css has the full theme, not just @import "tailwindcss";
grep -q '@theme inline' wwwroot/input.css || (echo "init did not write full theme to input.css"; exit 1)
grep -q ':root' wwwroot/input.css || (echo "init did not write :root variables to input.css"; exit 1)
grep -q '\.dark' wwwroot/input.css || (echo "init did not write .dark variables to input.css"; exit 1)

shellui add chart pie-chart dashboard-02 data-table --force

# NuGet dependencies (Blazor-ApexCharts, System.Linq.Dynamic.Core) should
# now be added automatically by `shellui add`. Assert they appear in the
# project file so a regression in the auto-install fails loudly here.
grep -q 'Blazor-ApexCharts' SmokeApp.csproj || (echo "shellui add chart did not add Blazor-ApexCharts NuGet dep"; exit 1)
grep -q 'System.Linq.Dynamic.Core' SmokeApp.csproj || (echo "shellui add data-table did not add System.Linq.Dynamic.Core NuGet dep"; exit 1)

# And the DataTable models file must land at Components/UI/Models/, not be missing.
test -f Components/UI/Models/DataTableModels.cs || (echo "shellui add data-table did not install data-table-models"; exit 1)

# chart-styles ships the CSS for the custom tooltip + ApexCharts chrome.
# Without it, hovering a chart shows invisible white-on-white text.
# Without charts.css, chart tooltips render white on white.
test -f wwwroot/css/charts.css || (echo "shellui add chart did not install chart-styles CSS"; exit 1)
grep -q '<link href="css/charts.css"' Components/App.razor || (echo "shellui add chart did not link charts.css in App.razor"; exit 1)

# SidebarProvider (pulled in transitively by dashboard-02) must call the
# global ShellUI.initSidebar helper, not dynamically import a separate
# shellui-sidebar.js module — that import resolves against the page URL and
# breaks silently when ShellUI is compiled into a consumer's own Razor Class
# Library, where the file is served from _content/<Library>/, not the root.
# A dynamic import of shellui-sidebar.js 404s once compiled into a consumer's RCL.
grep -q 'ShellUI.initSidebar' Components/UI/SidebarProvider.razor || (echo "SidebarProvider did not call ShellUI.initSidebar"; exit 1)
if grep -Fq 'shellui-sidebar.js' Components/UI/SidebarProvider.razor; then
echo "SidebarProvider still dynamically imports shellui-sidebar.js"
Expand All @@ -134,8 +113,6 @@ jobs:

dotnet build -c Debug

# init --dashboard wires the layout: Routes default, stock MainLayout/NavMenu removed,
# error bar moved to App.razor, sidebar links built from the app's pages.
cd "$TMPDIR/app"
dotnet new blazor -o DashApp --no-restore
cd DashApp
Expand All @@ -147,8 +124,7 @@ jobs:
grep -q '"/counter"' Components/UI/AppSidebar.razor || (echo "AppSidebar links were not built from the pages"; exit 1)
dotnet build -c Debug

# Every direct target must install and compile together; this catches missing
# dependencies and template compile errors that per-template tests can't see.
# Catches missing dependencies that per-template tests can't see.
ALL=$(python3 - "$GITHUB_WORKSPACE" <<'PY'
import os, re, sys
root = sys.argv[1]
Expand All @@ -168,12 +144,7 @@ jobs:
dotnet build -c Debug
done

# Pure-NuGet install path — `dotnet add package ShellUI.Components` without
# the CLI. Uses a one-off NuGet.config that whitelists ONLY the local feed,
# so a missing local package can't silently fall back to nuget.org and pull
# an older version (which would mask whether the current PR's package is
# correct). $GITHUB_WORKSPACE is absolute — relative paths from inside the
# temp consumer dir would resolve to the wrong root.
# Package-only install from a local-only feed, so nuget.org can't mask a broken package.
- name: NuGet-only install — verify safelist ships
shell: bash
run: |
Expand All @@ -182,8 +153,6 @@ jobs:
test -d "$LOCAL_FEED" || (echo "local feed not found at $LOCAL_FEED — did the pack step run?"; exit 1)
ls "$LOCAL_FEED"/*.nupkg | head -3

# DIAGNOSTIC: dump what's actually inside the fresh nupkg. The precompiled
# bundle must ship as a static web asset for consumers to `<link>` it.
echo "---nupkg contents (looking for shellui-all.css):---"
unzip -l "$LOCAL_FEED"/ShellUI.Components*.nupkg | grep -E 'shellui-all|staticwebassets/' | head -10 || echo " (no matches — bundle not in nupkg!)"
echo "---source wwwroot check:---"
Expand All @@ -194,8 +163,6 @@ jobs:
dotnet new blazor -o NuGetSmoke --no-restore
cd NuGetSmoke

# Pin restore to only the local feed; nuget.org explicitly disabled so a
# broken local feed can't be papered over by a public-published older version.
cat > NuGet.config <<EOF
<?xml version="1.0" encoding="utf-8"?>
<configuration>
Expand All @@ -206,19 +173,12 @@ jobs:
</configuration>
EOF

# Evict every cached ShellUI.Components from ~/.nuget/packages before restore.
# The runner-level cache is restored from actions/cache and may contain a
# stale copy of the current version from an earlier CI run (before we added
# the precompiled bundle, .cs scan, etc.). NuGet prefers cached over local
# feeds when version matches, so a stale cache silently masks the fresh
# nupkg. Wildcard covers any version — future-proof.
# A cached copy of the same version would shadow the fresh nupkg.
rm -rf ~/.nuget/packages/shellui.components

dotnet add package ShellUI.Components --prerelease

# The safelist gets copied into wwwroot/ during the consumer's build by
# the package's build/ShellUI.Components.targets — auto-imported by NuGet.
# Need to actually build the project, not just restore, for the Copy to run.
# The package's .targets copies the safelist during build, so restore alone isn't enough.
dotnet build -c Debug

SAFELIST="wwwroot/shellui-classes.txt"
Expand All @@ -229,16 +189,10 @@ jobs:
exit 1
)

# Sanity: the safelist contains real Tailwind classes
grep -q 'bg-background' "$SAFELIST" || (echo "safelist appears malformed — missing core Tailwind class 'bg-background'"; exit 1)
wc -l "$SAFELIST"

# In .NET 10, MapStaticAssets() doesn't physically copy static web assets
# from referenced packages into the consumer's bin/ during `dotnet build`
# — it uses a manifest and reads from the extracted NuGet cache at runtime.
# So the correct assertion is "does the file exist in the extracted package
# cache after restore", which proves it'll be served at
# `_content/ShellUI.Components/shellui-all.css` in the running app.
# .NET 10 serves package assets from the NuGet cache, not bin/, so check the extracted package.
BUNDLE="$(find ~/.nuget/packages/shellui.components -name 'shellui-all.css' -type f | head -1)"
if [ -z "$BUNDLE" ]; then
echo "ERROR: shellui-all.css not in consumer's extracted NuGet cache — the pure-NuGet install path is broken."
Expand All @@ -250,8 +204,6 @@ jobs:
BUNDLE_SIZE=$(wc -c < "$BUNDLE")
echo "bundle size: $BUNDLE_SIZE bytes"

# Spot-check a handful of representative rules using fixed-string grep
# (no regex escaping headaches). These catch classes of bugs we've hit.
grep -Fq -- '--background' "$BUNDLE" || (echo "ERROR: bundle missing --background theme var"; exit 1)
grep -Fq '.bg-background' "$BUNDLE" || (echo "ERROR: bundle missing .bg-background utility"; exit 1)
grep -Fq 'hover\:bg-accent' "$BUNDLE" || (echo "ERROR: bundle missing hover:bg-accent modifier rule"; exit 1)
Expand Down
9 changes: 3 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,14 @@ jobs:
- name: Restore dependencies
run: dotnet restore ShellUI.slnx

# Generate the precompiled CSS bundle before build so releases always ship
# a fresh one. File is gitignored — regenerated on every CI/release run.
# shellui-all.css is gitignored, so every release regenerates it.
- name: Build precompiled CSS bundle
run: |
set -euxo pipefail
bash scripts/rebuild-precompiled-css.sh
BUNDLE=src/ShellUI.Components/wwwroot/shellui-all.css
test -f "$BUNDLE" || (echo "ERROR: bundle was not produced"; exit 1)
# Content sanity — same assertions ci.yml runs.
# Same checks as ci.yml.
grep -q -- '--background:' "$BUNDLE" || (echo "ERROR: theme vars missing"; exit 1)
grep -q '\.bg-background' "$BUNDLE" || (echo "ERROR: utilities missing"; exit 1)
echo "release bundle size: $(wc -c < "$BUNDLE") bytes"
Expand All @@ -75,9 +74,7 @@ jobs:
- name: Pack NuGet packages
run: dotnet pack ShellUI.slnx --no-build --configuration Release -p:ContinuousIntegrationBuild=true

# ShellUI.Core and ShellUI.Templates are internal-only — they have no public API
# surface that consumers reference. Only the CLI tool and the Components runtime
# library are pushed to NuGet.
# Core and Templates are internal; only the CLI and Components are published.
- name: Publish to NuGet
run: |
dotnet nuget push src/ShellUI.CLI/bin/Release/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
Expand Down
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,5 @@ shellui-installation-tests/

# Preview publish output (testing artifacts)
preview-publish/
# Generated Tailwind bundle — regenerated in CI, not committed.
# Windows and Linux Tailwind CLI produce byte-different output; committing
# would cause spurious drift-check failures. Local devs: run
# `bash scripts/rebuild-precompiled-css.sh` before running Path A tests.
# Regenerated in CI; run scripts/rebuild-precompiled-css.sh locally.
src/ShellUI.Components/wwwroot/shellui-all.css
4 changes: 1 addition & 3 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<!-- Centralized ShellUI Version - Update this single file to version all components -->
<!-- One version for every ShellUI package -->
<PropertyGroup>
<ShellUIVersion>0.4.0</ShellUIVersion>
<ShellUIVersionSuffix>alpha.1</ShellUIVersionSuffix>
</PropertyGroup>

<!-- Common properties for all ShellUI projects -->
<PropertyGroup>
<Version>$(ShellUIVersion)</Version>
<Version Condition="'$(ShellUIVersionSuffix)' != ''">$(ShellUIVersion)-$(ShellUIVersionSuffix)</Version>
Expand All @@ -15,7 +14,6 @@
<InformationalVersion>$(Version)</InformationalVersion>
</PropertyGroup>

<!-- Common package metadata -->
<PropertyGroup>
<Authors>ShellUI</Authors>
<Company>ShellUI</Company>
Expand Down
5 changes: 0 additions & 5 deletions NET10/BlazorInteractiveServer/BlazorInteractiveServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@
<PackageReference Include="Blazor-ApexCharts" Version="6.0.2" />
</ItemGroup>

<!-- Removed NuGet/Project reference - using CLI-installed components instead -->
<!-- <ItemGroup>
<ProjectReference Include="..\..\src\ShellUI.Components\ShellUI.Components.csproj" />
</ItemGroup> -->

<Import Project="Build\ShellUI.targets" />

</Project>
11 changes: 2 additions & 9 deletions NET10/BlazorInteractiveServer/Components/App.razor
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,30 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />

<!-- Google Fonts - Kode Mono -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Kode+Mono:ital,wght@0,400..700;1,400..700&display=swap" rel="stylesheet">

<!-- Material Icons -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />

<!-- Font Awesome Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />

<!-- ShellUI - Tailwind CSS (compiled by standalone CLI, no Node.js!) -->
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["BlazorInteractiveServer.styles.css"]" />

<!-- Dark Mode Toggle Script -->
<script>
// Initialize dark mode (default to dark to save your eyes!)
// Dark by default
if (!localStorage.getItem('theme')) {
localStorage.setItem('theme', 'dark');
}

// Apply theme on load
const theme = localStorage.getItem('theme');
if (theme === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}

// Toggle function
function toggleTheme() {
const html = document.documentElement;
const isDark = html.classList.contains('dark');
Expand All @@ -54,7 +47,7 @@
<ImportMap />
<HeadOutlet @rendermode="InteractiveServer" />
<style>
/* Blazor adds .show only when an unhandled error occurs - hidden otherwise */
/* Blazor adds .show on an unhandled error */
#blazor-error-ui { display: none !important; position: fixed; bottom: 0; left: 0; right: 0; z-index: 9999; background: hsl(var(--destructive)); color: hsl(var(--destructive-foreground)); padding: 1rem; text-align: center; box-shadow: 0 -4px 6px -1px rgb(0 0 0/0.2); }
#blazor-error-ui.show { display: block !important; }
#blazor-error-ui a { color: inherit; text-decoration: underline; }
Expand Down
Loading
Loading