Skip to content

fix(publisher): stop pruning runtime-toggled state rules from publish… - #541

Open
fortusfederal wants to merge 1 commit into
CoreBunch:mainfrom
fortusfederal:fix/publish-runtime-state-class-pruning
Open

fortusfederal wants to merge 1 commit into
CoreBunch:mainfrom
fortusfederal:fix/publish-runtime-state-class-pruning

Conversation

@fortusfederal

Copy link
Copy Markdown

Summary

A rule such as .drawer.is-open never reaches the published stylesheet, while rendering correctly in the editor canvas.

selectorBindingClassName returns the rightmost class token, so the CSS importer stores the rule as a bindable class named is-open. The publisher's tree-shaker gates class-kind rules on usedIds.has(rule.id), and a class that exists only because a script calls classList.add('is-open') is never in any node's classIds — so the rule is silently dropped at publish time.

The binding was wrong to begin with: assigning that rule to a node writes class="is-open", which alone never matches .drawer.is-open. A subject compound holding two or more classes now has no unambiguous binding, so it is not treated as a bindable class and is no longer subject to usage-based pruning.

Verification

  • bun run build
  • bun test
  • bun run lint
  • Docker/deployment check — not relevant

Checklist

  • Tests cover behavior changes — styleRuleTreeShake.test.ts, cssSelectorClasses.test.ts, cssToStyleRules.test.ts
  • Docs were updated — docs/reference/css-class-registry.md
  • No compatibility shim was added for old pre-release behavior.
  • No secrets, local databases, uploads, or generated artifacts are included.

🤖 Generated with Claude Code

…ed CSS

A rule such as `.drawer.is-open` never reached the published stylesheet.
`selectorBindingClassName` returned the rightmost class token, so the CSS
importer stored the rule as a bindable class named `is-open`. The publisher's
tree-shaker gates class-kind rules on `usedIds.has(rule.id)`, and a class that
only exists because a script calls `classList.add('is-open')` is never in any
node's `classIds` — so the rule was silently dropped at publish time while
still rendering correctly in the editor canvas.

The binding was wrong in the first place: assigning that rule to a node writes
`class="is-open"`, which alone never matches `.drawer.is-open`.

A subject compound holding two or more classes now has no unambiguous binding
and classifies as ambient, where the existing tree-shaker logic already does
the right thing — unknown class tokens do not veto a rule, so the state rule
survives on its used base class. Single-class subjects qualified by an
attribute or pseudo (`.drawer[data-open]`, `.drawer:hover`) still bind, and
Tailwind-style variants (`.group:hover .group-hover\:block`) are unchanged,
including still being tree-shaken when unassigned.

Verified: bun test (10 pre-existing unrelated failures, unchanged),
bun run build, bun run lint.
@fortusfederal
fortusfederal marked this pull request as ready for review September 18, 2026 00:59
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.

2 participants