diff --git a/Directory.Build.props b/Directory.Build.props
index d87b4bc..03e8e89 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,7 +2,7 @@
- 0.3.5
+ 0.3.6
@@ -24,5 +24,10 @@
blazor;ui;components;tailwindcss;shadcn
https://github.com/shellui-dev/shellui
git
+ icon.png
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index bf0c27a..c609f1f 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@
| Channel | Version | Notes |
|---|---|---|
-| Latest stable (recommended) | `0.3.5` | Tailwind CSS `4.3.2` |
+| Latest stable (recommended) | `0.3.6` | Tailwind CSS `4.3.2` |
| Previous stable | `0.2.1` | Superseded by `0.3.0` |
The CLI needs the .NET 10 SDK and works in Blazor projects on .NET 8, 9 and 10. The `ShellUI.Components` NuGet package targets .NET 10 only; on .NET 8 or 9, use the CLI.
diff --git a/ShellUI.Tests/SafelistDriftTests.cs b/ShellUI.Tests/SafelistDriftTests.cs
index 3f3ae50..f55f69c 100644
--- a/ShellUI.Tests/SafelistDriftTests.cs
+++ b/ShellUI.Tests/SafelistDriftTests.cs
@@ -39,6 +39,28 @@ public void Safelist_MatchesGeneratedFromCurrentSources()
BuildDiffMessage(addedSinceCommit, removedSinceCommit));
}
+ [Fact]
+ public void Generator_HarvestsClassesInRazorExpressions()
+ {
+ var file = Path.Combine(Path.GetTempPath(), $"safelist-{Guid.NewGuid():N}.razor");
+ File.WriteAllLines(file, new[]
+ {
+ "
",
+ "",
+ "@code { string Tone(string v) => v switch { \"ok\" => \"bg-green-500/20\", _ => \"bg-background\" }; }",
+ });
+ try
+ {
+ var classes = Program.GenerateSafelist(new[] { file });
+ foreach (var expected in new[] { "translate-y-[-50%]", "sm:rounded-lg", "text-destructive", "text-muted-foreground", "bg-green-500/20", "bg-background" })
+ Assert.Contains(expected, classes);
+ }
+ finally
+ {
+ File.Delete(file);
+ }
+ }
+
[Fact]
public void GeneratedTargetsFile_IsValidXml()
{
diff --git a/VERSIONING_STRATEGY.md b/VERSIONING_STRATEGY.md
index e24b6c8..f1cdc40 100644
--- a/VERSIONING_STRATEGY.md
+++ b/VERSIONING_STRATEGY.md
@@ -6,7 +6,7 @@ ShellUI uses one centralized version for the source templates, CLI tool, and pac
| Scope | Value |
|---|---|
-| Version | `0.3.5` |
+| Version | `0.3.6` |
| Target framework | .NET 10 |
| Tailwind version | `4.3.2` |
@@ -18,15 +18,15 @@ The root `Directory.Build.props` supplies the version:
```xml
- 0.3.5
+ 0.3.6
```
`Directory.Build.props` composes the package and assembly metadata:
-- `Version` is `0.3.5`; with a suffix such as `rc.1` it becomes `0.3.5-rc.1`.
-- `AssemblyVersion` and `FileVersion` use the numeric base `0.3.5`.
+- `Version` is `0.3.6`; with a suffix such as `rc.1` it becomes `0.3.6-rc.1`.
+- `AssemblyVersion` and `FileVersion` use the numeric base `0.3.6`.
- `InformationalVersion` includes the prerelease suffix.
- Component metadata reads the centralized properties when running from the repository. `VersionHelper` uses assembly metadata as a fallback when its repository search does not find the solution file.
@@ -57,7 +57,7 @@ The CLI writes the computed version into `shellui.json` for each installed entry
"InstalledComponents": [
{
"Name": "button",
- "Version": "0.3.5",
+ "Version": "0.3.6",
"InstalledAt": "2026-01-01T00:00:00Z",
"IsCustomized": false
}
diff --git a/assets/icon.png b/assets/icon.png
new file mode 100644
index 0000000..322ff62
Binary files /dev/null and b/assets/icon.png differ
diff --git a/assets/icon.svg b/assets/icon.svg
new file mode 100644
index 0000000..dae45b4
--- /dev/null
+++ b/assets/icon.svg
@@ -0,0 +1 @@
+
diff --git a/docs/CLI_INSTALLATION.md b/docs/CLI_INSTALLATION.md
index 777cfc2..4768cac 100644
--- a/docs/CLI_INSTALLATION.md
+++ b/docs/CLI_INSTALLATION.md
@@ -4,7 +4,7 @@
| Context | Version |
|---|---|
-| Latest stable (recommended) | `0.3.5`, needs the .NET 10 runtime |
+| Latest stable (recommended) | `0.3.6`, needs the .NET 10 runtime |
| Previous stable | `0.2.1` |
| Tailwind | `4.3.2` |
@@ -43,7 +43,7 @@ The manifest is `.config/dotnet-tools.json` and uses the installed package versi
"isRoot": true,
"tools": {
"shellui.cli": {
- "version": "0.3.5",
+ "version": "0.3.6",
"commands": ["shellui"]
}
}
diff --git a/docs/CLI_SYNTAX.md b/docs/CLI_SYNTAX.md
index 6942145..64f4507 100644
--- a/docs/CLI_SYNTAX.md
+++ b/docs/CLI_SYNTAX.md
@@ -1,6 +1,6 @@
# ShellUI CLI Syntax
-This reference covers CLI `0.3.5`: it runs on .NET 10, sets up Blazor projects on .NET 8, 9 and 10, uses Tailwind CSS `4.3.2`, and has 76 direct component targets. Older versions, such as `0.2.1`, lack some of these commands.
+This reference covers CLI `0.3.6`: it runs on .NET 10, sets up Blazor projects on .NET 8, 9 and 10, uses Tailwind CSS `4.3.2`, and has 76 direct component targets. Older versions, such as `0.2.1`, lack some of these commands.
## Command prefix
@@ -213,7 +213,7 @@ Representative fields look like this:
"InstalledComponents": [
{
"Name": "button",
- "Version": "0.3.5",
+ "Version": "0.3.6",
"InstalledAt": "2026-01-01T00:00:00Z",
"IsCustomized": false
}
diff --git a/docs/FAQ.md b/docs/FAQ.md
index 2ef4216..b03df97 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -6,7 +6,7 @@ Answers for the current ShellUI source and the currently published packages.
### Which version should I use?
-Use `0.3.5`. It uses Tailwind CSS `4.3.2` and has 76 direct component targets:
+Use `0.3.6`. It uses Tailwind CSS `4.3.2` and has 76 direct component targets:
```bash
dotnet tool install -g ShellUI.CLI
@@ -145,7 +145,7 @@ A representative Tailwind and component record is:
"InstalledComponents": [
{
"Name": "button",
- "Version": "0.3.5",
+ "Version": "0.3.6",
"InstalledAt": "2026-01-01T00:00:00Z",
"IsCustomized": false
}
diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md
index 42af6db..05b4b7d 100644
--- a/docs/QUICKSTART.md
+++ b/docs/QUICKSTART.md
@@ -1,6 +1,6 @@
# ShellUI Quick Start
-This quick start uses ShellUI `0.3.5`: Tailwind CSS `4.3.2` and 76 direct component targets. The CLI needs the .NET 10 SDK and works in Blazor projects on .NET 8, 9 and 10.
+This quick start uses ShellUI `0.3.6`: Tailwind CSS `4.3.2` and 76 direct component targets. The CLI needs the .NET 10 SDK and works in Blazor projects on .NET 8, 9 and 10.
## Prerequisites
diff --git a/docs/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md
index eb8ae65..074fa31 100644
--- a/docs/RELEASE_NOTES.md
+++ b/docs/RELEASE_NOTES.md
@@ -1,5 +1,33 @@
# ShellUI Release Notes
+# ShellUI v0.3.6
+
+> A small patch: both packages now show the ShellUI logo on nuget.org, and the `ShellUI.Components` safelist includes the classes it was missing.
+
+## 🐛 Fixes
+
+- **Safelist:** `shellui-classes.txt`, which apps building their own Tailwind CSS from the package use, was missing 181 classes the components render: every class passed to `Shell.Cn("...")` inside a `class` attribute, plus those in conditional expressions. Among them were the dialog's centring (`translate-x-[-50%]`, `translate-y-[-50%]`), `sm:rounded-lg` and the Sonner variant colours, so in those apps dialogs weren't centred. The precompiled `shellui-all.css` wasn't affected.
+- **Package icon:** `ShellUI.CLI` and `ShellUI.Components` showed nuget.org's default icon. They now use the ShellUI logo.
+
+## ⬆️ Upgrading
+
+- **NuGet package:** update `ShellUI.Components` to `0.3.6`. If you build your own Tailwind CSS from `shellui-classes.txt`, rebuild it afterwards.
+- **CLI:** update the tool to `0.3.6`. Nothing changes in projects it set up.
+
+## 📦 Installation
+
+```bash
+dotnet tool install -g ShellUI.CLI --version 0.3.6
+# or upgrade an existing install
+dotnet tool update -g ShellUI.CLI --version 0.3.6
+```
+
+```bash
+dotnet add package ShellUI.Components --version 0.3.6
+```
+
+**Full Changelog**: https://github.com/shellui-dev/shellui/compare/v0.3.5...v0.3.6
+
# ShellUI v0.3.5
> A patch release that brings the 0.4 prerelease fixes to the stable line. `init` no longer downloads the Tailwind CLI into every project, `update` keeps your changes, `add` never downgrades a NuGet package, a component's `Class` overrides its own classes, overlays keep keyboard focus inside, and several component bugs are fixed. It also adds Razor class library support.
diff --git a/src/ShellUI.CLI/README.md b/src/ShellUI.CLI/README.md
index 15ab087..1424702 100644
--- a/src/ShellUI.CLI/README.md
+++ b/src/ShellUI.CLI/README.md
@@ -68,10 +68,10 @@ dotnet watch
## Documentation
-- [README](https://github.com/shellui-dev/shellui/blob/v0.3.5/README.md)
-- [CLI reference](https://github.com/shellui-dev/shellui/blob/v0.3.5/docs/CLI_SYNTAX.md)
-- [Release notes](https://github.com/shellui-dev/shellui/blob/v0.3.5/docs/RELEASE_NOTES.md)
+- [README](https://github.com/shellui-dev/shellui/blob/v0.3.6/README.md)
+- [CLI reference](https://github.com/shellui-dev/shellui/blob/v0.3.6/docs/CLI_SYNTAX.md)
+- [Release notes](https://github.com/shellui-dev/shellui/blob/v0.3.6/docs/RELEASE_NOTES.md)
## License
-[MIT](https://github.com/shellui-dev/shellui/blob/v0.3.5/LICENSE.txt)
+[MIT](https://github.com/shellui-dev/shellui/blob/v0.3.6/LICENSE.txt)
diff --git a/src/ShellUI.Components/README.md b/src/ShellUI.Components/README.md
index 899f0eb..497bb34 100644
--- a/src/ShellUI.Components/README.md
+++ b/src/ShellUI.Components/README.md
@@ -77,10 +77,10 @@ shellui theme apply https://tweakcn.com/themes/THEME_ID --emit-override wwwroot/
## Documentation
-- [README](https://github.com/shellui-dev/shellui/blob/v0.3.5/README.md)
-- [Tailwind setup](https://github.com/shellui-dev/shellui/blob/v0.3.5/docs/tailwind-setup.md)
-- [Release notes](https://github.com/shellui-dev/shellui/blob/v0.3.5/docs/RELEASE_NOTES.md)
+- [README](https://github.com/shellui-dev/shellui/blob/v0.3.6/README.md)
+- [Tailwind setup](https://github.com/shellui-dev/shellui/blob/v0.3.6/docs/tailwind-setup.md)
+- [Release notes](https://github.com/shellui-dev/shellui/blob/v0.3.6/docs/RELEASE_NOTES.md)
## License
-[MIT](https://github.com/shellui-dev/shellui/blob/v0.3.5/LICENSE.txt)
+[MIT](https://github.com/shellui-dev/shellui/blob/v0.3.6/LICENSE.txt)
diff --git a/src/ShellUI.Components/build/ShellUI.Components.targets b/src/ShellUI.Components/build/ShellUI.Components.targets
index 4552cf9..05668ce 100644
--- a/src/ShellUI.Components/build/ShellUI.Components.targets
+++ b/src/ShellUI.Components/build/ShellUI.Components.targets
@@ -1,62 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -64,12 +112,22 @@
+
+
+
+
+
+
+
+
+
+
@@ -99,14 +157,21 @@
+
+
+
+
+
+
+
@@ -120,19 +185,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -146,11 +228,15 @@
+
+
+
+
@@ -158,16 +244,21 @@
+
+
+
+
+
@@ -181,29 +272,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -212,11 +328,14 @@
+
+
+
@@ -231,27 +350,38 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -263,6 +393,7 @@
+
@@ -270,12 +401,21 @@
+
+
+
+
+
+
+
+
+
@@ -297,25 +437,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -324,6 +478,7 @@
+
@@ -331,42 +486,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ShellUI.Components/icon.svg b/src/ShellUI.Components/icon.svg
deleted file mode 100644
index 19e1eaf..0000000
--- a/src/ShellUI.Components/icon.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-
diff --git a/src/ShellUI.Components/wwwroot/shellui-classes.txt b/src/ShellUI.Components/wwwroot/shellui-classes.txt
index a610327..b557c9c 100644
--- a/src/ShellUI.Components/wwwroot/shellui-classes.txt
+++ b/src/ShellUI.Components/wwwroot/shellui-classes.txt
@@ -1,59 +1,107 @@
+active:scale-[0.98]
+after:-inset-2
+after:absolute
+after:md:hidden
align-middle
+animate-bounce
animate-in
animate-pulse
animate-spin
appearance-none
aspect-square
+backdrop-blur
backdrop-blur-md
backdrop-blur-sm
+bars-pulse
+bars-vertical
bg-accent
+bg-accent/30
+bg-accent/50
bg-background
bg-background/80
bg-background/95
bg-black/80
bg-blue-500
+bg-blue-500/20
bg-border
bg-card
bg-destructive
+bg-green-50
bg-green-500
+bg-green-500/20
+bg-input
bg-muted
bg-muted/30
bg-popover
bg-primary
+bg-primary/10
bg-secondary
bg-sidebar
+bg-sidebar-accent
+bg-sidebar-border
bg-sidebar-primary
bg-transparent
bg-yellow-500
+bg-yellow-500/20
border-0
border-2
+border-4
border-b
border-border
border-border/40
+border-dashed
border-destructive
+border-green-500
border-input
border-l
+border-muted
+border-primary
border-primary/20
border-r
+border-r-primary/50
+border-ring
+border-sidebar-border
border-t
+border-t-primary
border-transparent
bottom-0
bottom-4
bottom-full
+bottom-left
+bottom-right
+break-words
caption-bottom
cursor-default
+cursor-not-allowed
cursor-pointer
+dark:bg-blue-900/30
+dark:bg-green-900/20
+dark:bg-green-900/30
+dark:bg-yellow-900/30
+dark:text-blue-100
+dark:text-green-100
+dark:text-yellow-100
+data-[disabled]:opacity-50
+data-[disabled]:pointer-events-none
data-[selected]:bg-accent
data-[selected]:text-accent-foreground
data-[state=closed]:animate-out
data-[state=closed]:duration-300
data-[state=closed]:fade-out-0
+data-[state=closed]:slide-out-to-left-1/2
+data-[state=closed]:slide-out-to-top-[48%]
+data-[state=closed]:zoom-out-95
data-[state=open]:animate-in
data-[state=open]:bg-accent
data-[state=open]:duration-500
data-[state=open]:fade-in-0
data-[state=open]:grid-rows-[1fr]
+data-[state=open]:opacity-100
+data-[state=open]:slide-in-from-left-1/2
+data-[state=open]:slide-in-from-top-[48%]
data-[state=open]:text-muted-foreground
+data-[state=open]:zoom-in-95
+data-[state=selected]:bg-muted
disabled:cursor-not-allowed
disabled:opacity-50
disabled:pointer-events-none
@@ -61,12 +109,22 @@ duration-200
duration-300
ease-[cubic-bezier(0.4,0,0.2,1)]
ease-in-out
+ease-linear
fa-bell
+fa-book
+fa-bullhorn
fa-chevron-right
fa-circle-check
fa-circle-plus
+fa-code
fa-credit-card
fa-ellipsis
+fa-gear
+fa-life-ring
+fa-location-dot
+fa-microchip
+fa-paper-plane
+fa-pen-ruler
fa-right-from-bracket
fa-solid
fa-sort
@@ -96,14 +154,21 @@ focus-visible:ring-1
focus-visible:ring-2
focus-visible:ring-destructive
focus-visible:ring-offset-2
+focus-visible:ring-offset-background
focus-visible:ring-ring
+focus-within:ring-2
+focus-within:ring-offset-2
+focus-within:ring-ring
focus:bg-accent
+focus:bg-primary
+focus:border-ring
focus:outline-none
focus:ring-1
focus:ring-2
focus:ring-offset-2
focus:ring-ring
focus:text-accent-foreground
+focus:text-primary-foreground
font-bold
font-medium
font-mono
@@ -117,19 +182,36 @@ gap-2
gap-3
gap-4
grid-cols-2
+grid-cols-3
grid-cols-7
grid-rows-[0fr]
+group-content
+group-data-[collapsible=icon]:!bg-sidebar-primary
group-data-[collapsible=icon]:!flex
group-data-[collapsible=icon]:!items-center
group-data-[collapsible=icon]:!justify-center
group-data-[collapsible=icon]:!p-0
group-data-[collapsible=icon]:!rounded-full
group-data-[collapsible=icon]:!size-8
+group-data-[collapsible=icon]:-mt-8
group-data-[collapsible=icon]:hidden
+group-data-[collapsible=icon]:opacity-0
+group-data-[collapsible=icon]:overflow-hidden
+group-data-[collapsible=icon]:text-sidebar-primary-foreground
+group-data-[collapsible=offcanvas]:after:left-full
+group-data-[collapsible=offcanvas]:hover:bg-sidebar
+group-data-[collapsible=offcanvas]:translate-x-0
+group-data-[side=right]:group-data-[collapsible=offcanvas]:-translate-x-full
group-data-[variant=floating]:border
group-data-[variant=floating]:border-sidebar-border
group-data-[variant=floating]:rounded-lg
group-data-[variant=floating]:shadow
+group-focus-within/menu-item:opacity-100
+group-hover/menu-item:opacity-100
+group-label
+group/menu-item
+group/sidebar-wrapper
+h-1.5
h-1/2
h-10
h-11
@@ -143,11 +225,15 @@ h-3
h-3.5
h-4
h-5
+h-6
h-7
h-8
h-9
+h-[1px]
h-full
h-px
+h-svh
+has-[[data-variant=inset]]:bg-sidebar
hover:bg-accent
hover:bg-accent/50
hover:bg-blue-600
@@ -155,16 +241,21 @@ hover:bg-destructive/80
hover:bg-destructive/90
hover:bg-green-600
hover:bg-muted
+hover:bg-muted/50
+hover:bg-primary
hover:bg-primary/80
hover:bg-primary/90
hover:bg-secondary/80
hover:bg-sidebar-accent
hover:bg-yellow-600
+hover:border-border
+hover:border-primary/50
hover:opacity-100
hover:text-accent-foreground
hover:text-destructive
hover:text-foreground
hover:text-muted-foreground
+hover:text-primary-foreground
hover:text-sidebar-accent-foreground
hover:underline
inline-block
@@ -178,29 +269,54 @@ items-start
justify-between
justify-center
justify-end
+last:border-b-0
leading-none
leading-tight
left-0
left-1/2
left-2
+left-[50%]
+left-full
lg:space-x-8
list-none
max-h-60
max-h-[300px]
+max-h-screen
+max-w-lg
+max-w-max
max-w-sm
mb-1
mb-2
mb-4
mb-6
md:block
+md:flex
+md:max-w-[420px]
+md:opacity-0
+md:peer-data-[variant=inset]:m-2
+md:peer-data-[variant=inset]:ml-0
+md:peer-data-[variant=inset]:rounded-xl
+md:peer-data-[variant=inset]:shadow
+menu-action
+menu-badge
+menu-button
+menu-item
+menu-sub
+menu-sub-button
+menu-sub-item
min-h-0
+min-h-10
min-h-8
min-h-[80px]
+min-h-svh
min-w-0
min-w-24
+min-w-5
min-w-8
min-w-[640px]
min-w-[8rem]
+ml-1
+ml-2
ml-3
ml-auto
motion-reduce:animate-none
@@ -209,11 +325,14 @@ mr-2
mr-3
mt-0.5
mt-1
+mt-10
mt-2
mt-4
mt-6
mt-8
mt-auto
+mx-2
+mx-3.5
mx-auto
my-1
object-cover
@@ -228,27 +347,38 @@ overflow-auto
overflow-hidden
overflow-x-auto
overflow-y-auto
+p-0
p-0.5
p-1
p-2
p-3
p-4
p-6
+p-8
p-[3px]
pb-4
+peer-data-[active=true]/menu-button:text-sidebar-accent-foreground
+peer-data-[variant=inset]:min-h-[calc(100svh-1rem)]
peer-disabled:cursor-not-allowed
peer-disabled:opacity-70
+peer-hover/menu-button:text-sidebar-accent-foreground
peer/menu-button
pl-2
+pl-2.5
+pl-3
pl-4
+pl-8
placeholder:text-muted-foreground
pointer-events-auto
pointer-events-none
pr-2
+pr-2.5
pr-3
pr-6
pr-8
+pr-9
pt-0
+pt-6
px-1
px-1.5
px-2
@@ -260,6 +390,7 @@ px-8
py-0.5
py-1
py-1.5
+py-12
py-2
py-4
py-6
@@ -267,12 +398,21 @@ right-0
right-1
right-2
right-4
+right-full
+ring-0
+ring-2
+ring-offset-2
ring-offset-background
+ring-primary/20
+ring-ring
ring-sidebar-ring
+rotate-180
+rotate-90
rounded-full
rounded-lg
rounded-md
rounded-sm
+scale-[1.02]
select-none
shadow-lg
shadow-md
@@ -294,25 +434,39 @@ slide-in-from-left
slide-in-from-right
slide-in-from-top
slide-in-from-top-2
+sm:flex-col
sm:flex-row
+sm:gap-2.5
sm:items-center
sm:justify-between
+sm:justify-end
sm:max-w-sm
+sm:rounded-lg
+sm:space-x-2
sm:space-x-6
sm:text-left
space-x-1
space-x-2
+space-x-4
+space-y-1.5
space-y-2
space-y-4
+space-y-6
sr-only
+supports-[backdrop-filter]:bg-background/60
+tabular-nums
+text-2xl
text-[10px]
text-[8px]
text-accent-foreground
+text-blue-700
text-card-foreground
text-center
text-destructive-foreground
text-foreground
text-foreground/70
+text-green-700
+text-green-900
text-left
text-lg
text-muted-foreground
@@ -321,6 +475,7 @@ text-primary
text-primary-foreground
text-right
text-secondary-foreground
+text-sidebar-accent-foreground
text-sidebar-foreground
text-sidebar-foreground/70
text-sidebar-primary-foreground
@@ -328,42 +483,68 @@ text-sm
text-white
text-xl
text-xs
+text-yellow-800
top-0
top-2
top-4
top-8
+top-[1px]
+top-[50%]
top-full
+top-right
+touch-none
tracking-tight
transition-[grid-template-rows]
+transition-[left,right,width]
transition-[width,height,padding]
+transition-[width]
transition-all
transition-colors
transition-opacity
transition-transform
+translate-x-0
+translate-x-5
+translate-x-[-50%]
+translate-x-px
+translate-y-[-50%]
underline-offset-4
var(--border
var(--muted
+var(--sidebar-width
+var(--sidebar-width-icon
+w-1
+w-1.5
w-1/2
w-10
+w-11
w-12
w-16
+w-2
w-2.5
+w-20
+w-24
w-3
w-3.5
w-3/4
w-4
w-5
w-56
+w-6
w-64
w-7
+w-72
w-8
w-9
w-[100px]
+w-[1px]
w-[70px]
+w-auto
w-fit
w-full
w-max
whitespace-nowrap
+width:
+z-10
z-40
z-50
zoom-in-95
diff --git a/src/ShellUI.Core/Models/ComponentMetadata.cs b/src/ShellUI.Core/Models/ComponentMetadata.cs
index 38f0d4a..1be9bb8 100644
--- a/src/ShellUI.Core/Models/ComponentMetadata.cs
+++ b/src/ShellUI.Core/Models/ComponentMetadata.cs
@@ -66,7 +66,7 @@ private static string GetCurrentVersion()
if (assemblyVersion != null)
return assemblyVersion.InformationalVersion.Split('+')[0];
- return "0.3.5";
+ return "0.3.6";
}
}
diff --git a/src/ShellUI.Templates/VersionHelper.cs b/src/ShellUI.Templates/VersionHelper.cs
index 52e14d2..4cebe3d 100644
--- a/src/ShellUI.Templates/VersionHelper.cs
+++ b/src/ShellUI.Templates/VersionHelper.cs
@@ -51,7 +51,7 @@ public static string GetCurrentVersion()
return _cachedVersion;
}
- return "0.3.5";
+ return "0.3.6";
}
private static string? FindSolutionRoot()
diff --git a/tools/ShellUI.SafelistGenerator/Program.cs b/tools/ShellUI.SafelistGenerator/Program.cs
index 1ad88ea..c19d33c 100644
--- a/tools/ShellUI.SafelistGenerator/Program.cs
+++ b/tools/ShellUI.SafelistGenerator/Program.cs
@@ -64,6 +64,7 @@ public static SortedSet GenerateSafelist(IEnumerable sourceFileP
if (file.EndsWith(".razor", StringComparison.OrdinalIgnoreCase))
{
ExtractClasses(text, classes);
+ ExtractFromRazorExpressions(text, classes);
}
else if (file.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
{
@@ -86,7 +87,7 @@ private static void ExtractFromCSharp(string content, SortedSet sink)
private static bool LooksLikeClassList(string s)
{
- if (s.Length == 0 || s.Length > 500) return false;
+ if (s.Length == 0 || s.Length > 2000) return false;
// `=` outside `[…]` implies key=value pairs, not class strings.
if (s.Contains("://") || s.Contains('<') || s.Contains('>') || s.Contains('{')
|| s.Contains(';') || s.Contains('=') && !s.Contains('[')
@@ -151,6 +152,20 @@ private static string XmlEscape(string s)
"class\\s*=\\s*\"(?[^\"]*)\"",
RegexOptions.Compiled);
+ // Shell.Cn arguments, ternaries and switch arms, which the class attribute regex cuts off at their first quote.
+ private static readonly Regex RazorExpressionLiteralRegex = new(
+ "(?<=[(,?:=>]\\s*)\"(?[^\"@]*)\"",
+ RegexOptions.Compiled);
+
+ private static void ExtractFromRazorExpressions(string content, SortedSet sink)
+ {
+ foreach (Match lit in RazorExpressionLiteralRegex.Matches(content))
+ {
+ var value = lit.Groups["lit"].Value;
+ if (LooksLikeClassList(value)) HarvestTokens(value, sink);
+ }
+ }
+
private static readonly Regex StringLiteralRegex = new(
"\"(?[^\"]*)\"",
RegexOptions.Compiled);