Skip to content

fix(rule-utils): anchor the part- variant regex - #5313

Merged
zyyv merged 1 commit into
unocss:mainfrom
giaBaoJS:fix/anchor-part-variant-regex
Sep 7, 2026
Merged

zyyv merged 1 commit into
unocss:mainfrom
giaBaoJS:fix/anchor-part-variant-regex

Conversation

@giaBaoJS

@giaBaoJS giaBaoJS commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

The bug

part-[...] stops working as soon as it is combined with a variant that UnoCSS resolves after it. hover:part-[button]:text-red works, but dark:part-[button]:text-red produces no CSS at all. The utility is silently dropped, with no warning.

Also affected: rtl:, *:, scope-[...]:, group-data-[...]:, @container, and the [&...]: variables variant.

Reproduce

const uno = await createGenerator({ presets: [presetMini({ dark: 'class' })] })

await uno.generate(['hover:part-[button]:text-red'])
// .hover\:part-\[button\]\:text-red::part(button):hover{ ... }

await uno.generate(['dark:part-[button]:text-red'])
// "" (nothing)

Root cause

PartClassesRE in packages-presets/rule-utils/src/pseudo.ts is not anchored, but its handler builds the next matcher with input.slice(match[1].length), which assumes the match starts at index 0. For dark:part-[button]:text-red the regex matches at index 5 and the slice yields ton]:text-red, so no rule ever matches it. The variants that do work only work because they are ordered before variantPartClasses and get consumed first.

Anchoring the regex lets those later variants take their turn, after which part- matches at index 0 as it already does today.

Test

packages-presets/rule-utils/test/pseudo.test.ts gains part classes after another variant: it registers createPartClasses() followed by a dark variant and asserts that dark:part-[button]:foo-1 is matched and emits .dark .dark\:part-\[button\]\:foo-1::part(button){color:foo-1;}. Without the anchor result.matched is an empty set and no CSS is produced.

The existing part classes test is unchanged and still passes, as does the rest of the suite.

PartClassesRE had no ^ anchor while the handler slices the matcher from
index 0, so a match found after a leading variant produced a corrupted
matcher and the utility was dropped. dark:part-[button]:text-red emitted
no CSS at all, while hover:part-[button]:text-red worked.
@giaBaoJS
giaBaoJS requested review from antfu and zyyv as code owners September 6, 2026 03:56
@netlify

netlify Bot commented Sep 6, 2026

Copy link
Copy Markdown

Deploy Preview for unocss ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 82653a2
🔍 Latest deploy log https://app.netlify.com/projects/unocss/deploys/6a9ce466872fa300082056d4
😎 Deploy Preview https://deploy-preview-5313--unocss.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@pkg-pr-new

pkg-pr-new Bot commented Sep 6, 2026

Copy link
Copy Markdown

Open in StackBlitz

commit: 82653a2

@zyyv
zyyv added this pull request to the merge queue Sep 7, 2026
Merged via the queue into unocss:main with commit 4d05976 Sep 7, 2026
11 checks passed
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

Sponsor
SponsoredKunjungi sekarang
Promo