From 28f60c9df6784221937593af64ddb81dec939e7f Mon Sep 17 00:00:00 2001 From: Saya Date: Mon, 13 Feb 2023 12:47:33 +0800 Subject: [PATCH 1/3] feat(core): make select pseudo elements not to be moved around --- packages/core/src/generator/index.ts | 18 +++++++++++++++++- test/__snapshots__/order.test.ts.snap | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/core/src/generator/index.ts b/packages/core/src/generator/index.ts index 099a78e634..c1b962a6a8 100644 --- a/packages/core/src/generator/index.ts +++ b/packages/core/src/generator/index.ts @@ -647,11 +647,27 @@ function applyScope(css: string, scope?: string) { return scope ? `${scope} ${css}` : css } +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', +] export function movePseudoElementsEnd(selector: string) { const pseudoElements = selector.match(/::[\w-]+(\([\w-]+\))?/g) if (pseudoElements) { - for (const e of pseudoElements) + for (let i = pseudoElements.length - 1; i >= 0; --i) { + const e = pseudoElements[i] + if (excludedPseudo.includes(e)) { + pseudoElements.splice(i, 1) + continue + } selector = selector.replace(e, '') + } selector += pseudoElements.join('') } return selector diff --git a/test/__snapshots__/order.test.ts.snap b/test/__snapshots__/order.test.ts.snap index 6bc2b8f784..58ec55cf34 100644 --- a/test/__snapshots__/order.test.ts.snap +++ b/test/__snapshots__/order.test.ts.snap @@ -10,7 +10,7 @@ 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 > movePseudoElementsEnd 1`] = `".part-\\\\[hello-2\\\\]\\\\:marker\\\\:file\\\\:hover\\\\:selection\\\\:mb-4::file-selector-button:hover::part(hello-2)::marker::selection"`; exports[`order > multiple variant sorting 1`] = ` "/* layer: default */ From c5c36cf4ee8fc2f2b0196f24705ce5fa58464a4d Mon Sep 17 00:00:00 2001 From: sibbng Date: Mon, 13 Feb 2023 23:26:37 +0300 Subject: [PATCH 2/3] refactor: pseudo sorting --- packages/core/src/generator/index.ts | 30 ++------------------ packages/preset-mini/src/_variants/pseudo.ts | 12 +++++++- test/__snapshots__/order.test.ts.snap | 8 ++++-- test/__snapshots__/preset-mini.test.ts.snap | 2 +- test/order.test.ts | 18 +++++++++--- 5 files changed, 34 insertions(+), 36 deletions(-) diff --git a/packages/core/src/generator/index.ts b/packages/core/src/generator/index.ts index c1b962a6a8..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,32 +647,6 @@ function applyScope(css: string, scope?: string) { return scope ? `${scope} ${css}` : css } -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', -] -export function movePseudoElementsEnd(selector: string) { - const pseudoElements = selector.match(/::[\w-]+(\([\w-]+\))?/g) - if (pseudoElements) { - for (let i = pseudoElements.length - 1; i >= 0; --i) { - const e = pseudoElements[i] - if (excludedPseudo.includes(e)) { - pseudoElements.splice(i, 1) - continue - } - 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 e02df66e09..306dcf31f0 100644 --- a/packages/preset-mini/src/_variants/pseudo.ts +++ b/packages/preset-mini/src/_variants/pseudo.ts @@ -163,6 +163,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 => { @@ -182,7 +192,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 58ec55cf34..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::file-selector-button:hover::part(hello-2)::marker::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 75b0f128da..ae61d92290 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 () => { From 8a66e456fcd4a0fe566c0c559d7c36c2e98c8d05 Mon Sep 17 00:00:00 2001 From: Saya Date: Wed, 22 Feb 2023 08:50:49 +0800 Subject: [PATCH 3/3] lint --- packages/preset-mini/src/_variants/pseudo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/preset-mini/src/_variants/pseudo.ts b/packages/preset-mini/src/_variants/pseudo.ts index d5507c160d..7b39104296 100644 --- a/packages/preset-mini/src/_variants/pseudo.ts +++ b/packages/preset-mini/src/_variants/pseudo.ts @@ -193,7 +193,7 @@ export const variantPseudoClassesAndElements = (): VariantObject => { return { matcher: input.slice(match[0].length), handle: (input, next) => { - const selectors = pseudo.startsWith('::') && !excludedPseudo.includes(pseudo) + const selectors = (pseudo.startsWith('::') && !excludedPseudo.includes(pseudo)) ? { pseudo: `${input.pseudo}${pseudo}`, }