diff --git a/packages/core/src/generator/index.ts b/packages/core/src/generator/index.ts index 099a78e634..3171eeb978 100644 --- a/packages/core/src/generator/index.ts +++ b/packages/core/src/generator/index.ts @@ -364,11 +364,11 @@ export class UnoGenerator { this.parentOrders.set(parent, parentOrder) const obj: UtilObject = { - selector: movePseudoElementsEnd([ + selector: [ variantContextResult.prefix, variantContextResult.selector, variantContextResult.pseudo, - ].join('')), + ].join(''), entries: variantContextResult.entries, parent, layer: variantContextResult.layer, @@ -647,16 +647,6 @@ function applyScope(css: string, scope?: string) { return scope ? `${scope} ${css}` : css } -export function movePseudoElementsEnd(selector: string) { - const pseudoElements = selector.match(/::[\w-]+(\([\w-]+\))?/g) - if (pseudoElements) { - for (const e of pseudoElements) - selector = selector.replace(e, '') - selector += pseudoElements.join('') - } - return selector -} - const attributifyRe = /^\[(.+?)(~?=)"(.*)"\]$/ export function toEscapedSelector(raw: string) { if (attributifyRe.test(raw)) diff --git a/packages/preset-mini/src/_variants/pseudo.ts b/packages/preset-mini/src/_variants/pseudo.ts index 3322b76387..7b39104296 100644 --- a/packages/preset-mini/src/_variants/pseudo.ts +++ b/packages/preset-mini/src/_variants/pseudo.ts @@ -164,6 +164,16 @@ const taggedPseudoClassMatcher = (tag: string, parent: string, combinator: strin } } +const excludedPseudo = [ + '::-webkit-resizer', + '::-webkit-scrollbar', + '::-webkit-scrollbar-button', + '::-webkit-scrollbar-corner', + '::-webkit-scrollbar-thumb', + '::-webkit-scrollbar-track', + '::-webkit-scrollbar-track-piece', + '::file-selector-button', +] const PseudoClassesAndElementsStr = Object.entries(PseudoClasses).map(([key]) => key).join('|') const PseudoClassesAndElementsColonStr = Object.entries(PseudoClassesColon).map(([key]) => key).join('|') export const variantPseudoClassesAndElements = (): VariantObject => { @@ -183,7 +193,7 @@ export const variantPseudoClassesAndElements = (): VariantObject => { return { matcher: input.slice(match[0].length), handle: (input, next) => { - const selectors = pseudo.startsWith('::') + const selectors = (pseudo.startsWith('::') && !excludedPseudo.includes(pseudo)) ? { pseudo: `${input.pseudo}${pseudo}`, } diff --git a/test/__snapshots__/order.test.ts.snap b/test/__snapshots__/order.test.ts.snap index 6bc2b8f784..c5df5d981c 100644 --- a/test/__snapshots__/order.test.ts.snap +++ b/test/__snapshots__/order.test.ts.snap @@ -10,8 +10,6 @@ exports[`order > fully controlled rules merged and sorted by body 1`] = ` .css{--var:css;}" `; -exports[`order > movePseudoElementsEnd 1`] = `".part-\\\\[hello-2\\\\]\\\\:marker\\\\:file\\\\:hover\\\\:selection\\\\:mb-4:hover::part(hello-2)::marker::file-selector-button::selection"`; - exports[`order > multiple variant sorting 1`] = ` "/* layer: default */ .dark .group:hover:focus-within .dark\\\\:group-hover\\\\:group-focus-within\\\\:bg-blue-600{--un-bg-opacity:1;background-color:rgba(37,99,235,var(--un-bg-opacity));} @@ -20,6 +18,12 @@ exports[`order > multiple variant sorting 1`] = ` .parent:hover>.light .parent:focus-within>.parent-hover\\\\:light\\\\:parent-focus-within\\\\:bg-green-600{--un-bg-opacity:1;background-color:rgba(22,163,74,var(--un-bg-opacity));}" `; +exports[`order > pseudo-elements sorting 1`] = ` +"/* layer: default */ +.dark .dark\\\\:file\\\\:marker\\\\:hover\\\\:bg-red-600:hover::file-selector-button::marker, +.dark .dark\\\\:hover\\\\:file\\\\:marker\\\\:bg-red-600::file-selector-button:hover::marker{--un-bg-opacity:1;background-color:rgba(220,38,38,var(--un-bg-opacity));}" +`; + exports[`order > variant ordering 1`] = ` "/* layer: default */ .group .dark .dark\\\\:group\\\\:foo-3{name:foo-3;} diff --git a/test/__snapshots__/preset-mini.test.ts.snap b/test/__snapshots__/preset-mini.test.ts.snap index 8a450ff550..7646fd6575 100644 --- a/test/__snapshots__/preset-mini.test.ts.snap +++ b/test/__snapshots__/preset-mini.test.ts.snap @@ -184,7 +184,7 @@ unocss .scope-\\\\[unocss\\\\]\\\\:block{display:block;} .first-line\\\\:bg-green-400::first-line{--un-bg-opacity:1;background-color:rgba(74,222,128,var(--un-bg-opacity));} .focus-within\\\\:has-first\\\\:checked\\\\:bg-gray\\\\/20:checked:has(:first-child):focus-within, .focus-within\\\\:where-first\\\\:checked\\\\:bg-gray\\\\/20:checked:where(:first-child):focus-within{background-color:rgba(156,163,175,0.2);} -.hover\\\\:file\\\\:bg-violet-100:hover::file-selector-button{--un-bg-opacity:1;background-color:rgba(237,233,254,var(--un-bg-opacity));} +.hover\\\\:file\\\\:bg-violet-100::file-selector-button:hover{--un-bg-opacity:1;background-color:rgba(237,233,254,var(--un-bg-opacity));} .hover\\\\:is-first\\\\:checked\\\\:bg-true-gray\\\\/10:checked:is(:first-child):hover, .hover\\\\:not-first\\\\:checked\\\\:bg-true-gray\\\\/10:checked:not(:first-child):hover{background-color:rgba(163,163,163,0.1);} .hover\\\\:not-first\\\\:checked\\\\:bg-red\\\\/10:checked:not(:first-child):hover{background-color:rgba(248,113,113,0.1);} diff --git a/test/order.test.ts b/test/order.test.ts index aff1405768..81bd5e26bc 100644 --- a/test/order.test.ts +++ b/test/order.test.ts @@ -1,4 +1,4 @@ -import { createGenerator, movePseudoElementsEnd } from '@unocss/core' +import { createGenerator } from '@unocss/core' import { describe, expect, test } from 'vitest' import { variantMatcher } from '@unocss/preset-mini/utils' import presetMini from '@unocss/preset-mini' @@ -109,9 +109,19 @@ describe('order', () => { expect(css).toMatchSnapshot() }) - test('movePseudoElementsEnd', () => { - expect(movePseudoElementsEnd('.part-\\[hello-2\\]\\:marker\\:file\\:hover\\:selection\\:mb-4::part(hello-2)::marker::file-selector-button:hover::selection')) - .toMatchSnapshot() + test('pseudo-elements sorting', async () => { + const uno = createGenerator({ + presets: [ + presetMini(), + ], + }) + + const { css } = await uno.generate([ + 'dark:hover:file:marker:bg-red-600', + 'dark:file:marker:hover:bg-red-600', + ].join(' '), { preflights: false }) + + expect(css).toMatchSnapshot() }) test('variant sorting', async () => {