Skip to content

fix(defaults): repair class attributes mangled by a class sorter - #2210

Merged
glennmichael123 merged 1 commit into
mainfrom
fix/2209-mangled-class-interpolations
Aug 4, 2026
Merged

fix(defaults): repair class attributes mangled by a class sorter#2210
glennmichael123 merged 1 commit into
mainfrom
fix/2209-mangled-class-interpolations

Conversation

@glennmichael123

Copy link
Copy Markdown
Member

Closes #2209.

It's 61 attributes across 23 files, not one view

The issue found blog/category.stx and noted it may already be gone upstream. It is — but the same corruption is sitting in 23 other files that are still shipped.

storage/framework/defaults/resources/ is live (frameworkPath('defaults/resources/…'), path/src/index.ts:416) and buddy new copies the repo wholesale, so all 61 reached every scaffolded app. One of them is in resources/components/InputGroup.stx — this repo's own app code.

Root cause: 9e06583afc

git log -S pins it to 9e06583afc "chore: fix lint errors" (2026-04-14, 542 files). It ran a Tailwind-style class sorter over class="..." that split on whitespace without respecting {{ }} boundaries, so {{, the expression, and }} sorted as if they were class names:

before  class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 {{ className }}"
after   class="mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl {{ }} className"

The tell is that the classes really are in sort order. stx then throws on the orphaned operators, aborting the build once the route scanner reaches the file.

Not a live regression. I verified both pickier --fix and buddy format --write leave {{ ternary }}-in-class intact today. This is committed damage.

Repaired mechanically, not by rewriting intent

A sort permutes but preserves the token multiset, so each mangled value matches exactly one pre-commit value under tokens.sort(). 61/61 matched, 0 ambiguous.

That mattered at this volume — hand-reconstructing 61 ternaries invites fresh bugs, and the nested cases are genuinely unreadable:

": : ? ? '' 'bg-blue-100 'bg-gray-100 'ring-2 {{ {{ }} }} <= == currentStep currentStep loop.index loop.index"

recovers to two separate expressions in one attribute:

"flex items-center justify-center w-8 h-8 rounded-full {{ loop.index <= currentStep ? 'bg-blue-100 text-blue-600' : 'bg-gray-100 text-gray-500' }} {{ loop.index == currentStep ? 'ring-2 ring-blue-600 ring-offset-2' : '' }}"

Deliberately untouched

ModelRecordsDashboard.stx has two {{ }} hits that are prose in comments, explaining that a placeholder in a class attribute is not reactively bound. The repair skips it, and the audit grep excludes it.

Verification

  • 0 mangled attributes remain outside that comment
  • 23 repaired files parse clean under lintStxStrict (0 parse errors)
  • pickier clean

Follow-up

The issue's second ask — "audit for other similarly-mangled {{ … }}-in-attribute default views" — is what found these. To stop it recurring, an empty-interpolation-inside-an-attribute check belongs in buddy lint --stx (#2208), scoped to attribute values so the comment case above stays legal. I'll add it there rather than widening this PR.

🤖 Generated with Claude Code

`9e06583afc` ("chore: fix lint errors", 542 files) ran a Tailwind-style class
sorter over `class="..."` values. It split them on whitespace without
respecting `{{ }}` boundaries, so `{{`, the expression, and `}}` were sorted as
if they were class names:

  before  class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 {{ className }}"
  after   class="mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl {{ }} className"

stx then throws on the orphaned operators, which aborts the build once the
route scanner reaches the file.

61 attributes across 23 files, not the single view #2209 reported. That one is
gone from the tree already, but `storage/framework/defaults/resources/` is live
(`frameworkPath('defaults/resources/…')`, path/src/index.ts:416) and `buddy new`
copies the repo wholesale, so every one of these shipped into scaffolded apps.

Repaired mechanically rather than by rewriting intent. A sort permutes but
preserves the token multiset, so each mangled value matches exactly one
pre-commit value under `tokens.sort()` - 61/61 matched, 0 ambiguous. That
matters at this volume: hand-reconstructing 61 ternaries invites new bugs, and
the nested cases are genuinely hard to read, e.g.

  ": : ? ? '' 'bg-blue-100 'bg-gray-100 'ring-2 {{ {{ }} }} <= == currentStep
   currentStep loop.index loop.index"

recovers to two separate expressions in one attribute.

`ModelRecordsDashboard.stx` is deliberately untouched: its two `{{ }}` hits are
prose in comments explaining that a placeholder in a class attribute is not
reactively bound.

The current formatter no longer does this - verified `pickier --fix` and
`buddy format --write` both leave `{{ ternary }}`-in-class intact - so this is
committed damage, not a live regression.

Closes #2209
@glennmichael123
glennmichael123 merged commit 9470b64 into main Aug 4, 2026
7 of 10 checks passed
@glennmichael123
glennmichael123 deleted the fix/2209-mangled-class-interpolations branch August 4, 2026 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@stacksjs/defaults scaffolds a corrupted blog/category.stx that fails stx compilation

1 participant