Skip to content

Commit

Permalink
feat: spread mutiple pseudo-elements for correct variant handling
Browse files Browse the repository at this point in the history
  • Loading branch information
MellowCo committed Dec 7, 2024
1 parent a911303 commit 2074203
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 52 deletions.
2 changes: 1 addition & 1 deletion src/variants/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function variants(options: PresetWeappOptions): Variant<Theme>[] {
...variantCombinators,
variantSpaceAndDivide,

variantPseudoClassesAndElements(),
...variantPseudoClassesAndElements(),
variantPseudoClassFunctions(),
...variantTaggedPseudoClasses(options),

Expand Down
126 changes: 84 additions & 42 deletions src/variants/pseudo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ const PseudoClasses: Record<string, string> = Object.fromEntries([
['placeholder', '::placeholder'],
['before', '::before'],
['after', '::after'],
['selection', ' ::selection'],
['marker', '::marker'],
['file', '::file-selector-button'],
].map(key => Array.isArray(key) ? key : [key, `:${key}`]))

Expand All @@ -88,6 +86,11 @@ const PseudoClassFunctions = [
'has',
]

const PseudoClassesMulti: Record<string, string[]> = Object.fromEntries([
['selection', ['::selection', ' *::selection']],
['marker', ['::marker', ' *::marker']],
])

const PseudoClassesStr = Object.entries(PseudoClasses)
.filter(([, pseudo]) => !pseudo.startsWith('::'))
.map(([key]) => key)
Expand All @@ -99,6 +102,7 @@ const PseudoClassesColonStr = Object.entries(PseudoClassesColon)
.sort((a, b) => b.length - a.length)
.join('|')
const PseudoClassFunctionsStr = PseudoClassFunctions.join('|')
const PseudoClassesMultiStr = Object.keys(PseudoClassesMulti).sort((a, b) => b.length - a.length).join('|')

function taggedPseudoClassMatcher(tag: string, parent: string, combinator: string): VariantObject {
const rawRE = new RegExp(`^(${escapeRegExp(parent)}:)(\\S+)${escapeRegExp(combinator)}\\1`)
Expand Down Expand Up @@ -193,6 +197,17 @@ function 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)
.sort((a, b) => b.length - a.length)
Expand All @@ -202,53 +217,80 @@ const PseudoClassesAndElementsColonStr = Object.entries(PseudoClassesColon)
.sort((a, b) => b.length - a.length)
.join('|')

export function variantPseudoClassesAndElements(): VariantObject<Theme> {
export function variantPseudoClassesAndElements(): VariantObject[] {
let PseudoClassesAndElementsRE: RegExp
let PseudoClassesAndElementsColonRE: RegExp
return {
name: 'pseudo',
match(input, ctx) {
if (!(PseudoClassesAndElementsRE && PseudoClassesAndElementsRE)) {
PseudoClassesAndElementsRE = new RegExp(`^(${PseudoClassesAndElementsStr})(?:${ctx.generator.config.separators.join('|')})`)
PseudoClassesAndElementsColonRE = new RegExp(`^(${PseudoClassesAndElementsColonStr})(?:${ctx.generator.config.separators.filter(x => x !== '-').join('|')})`)
}
let PseudoClassesMultiRE: RegExp

input = cacheRestoreSelector(input, ctx.theme.transformRules)
const match = input.match(PseudoClassesAndElementsRE) || input.match(PseudoClassesAndElementsColonRE)
if (match) {
const pseudo = PseudoClasses[match[1]] || PseudoClassesColon[match[1]] || `:${match[1]}`
return [
{
name: 'pseudo',
match(input, ctx) {
if (!(PseudoClassesAndElementsRE && PseudoClassesAndElementsColonRE)) {
PseudoClassesAndElementsRE = new RegExp(`^(${PseudoClassesAndElementsStr})(?:${ctx.generator.config.separators.join('|')})`)
PseudoClassesAndElementsColonRE = new RegExp(`^(${PseudoClassesAndElementsColonStr})(?:${ctx.generator.config.separators.filter(x => x !== '-').join('|')})`)
}

// order of pseudo classes
let index: number | undefined = PseudoClassesKeys.indexOf(match[1])
if (index === -1)
index = PseudoClassesColonKeys.indexOf(match[1])
if (index === -1)
index = undefined
const match = input.match(PseudoClassesAndElementsRE) || input.match(PseudoClassesAndElementsColonRE)
if (match) {
const pseudo = PseudoClasses[match[1]] || PseudoClassesColon[match[1]] || `:${match[1]}`

// order of pseudo classes
let index: number | undefined = PseudoClassesKeys.indexOf(match[1])
if (index === -1)
index = PseudoClassesColonKeys.indexOf(match[1])
if (index === -1)
index = undefined

return {
matcher: input.slice(match[0].length),
handle: (input, next) => {
const selectors = (pseudo.includes('::') && !excludedPseudo.includes(pseudo))
? {
pseudo: `${input.pseudo}${pseudo}`,
}
: {
selector: `${input.selector}${pseudo}`,
}

return next({
...input,
...selectors,
sort: index,
noMerge: true,
})
},
}
}
},
multiPass: true,
autocomplete: `(${PseudoClassesAndElementsStr}|${PseudoClassesAndElementsColonStr}):`,
},
{
name: 'pseudo:multi',
match(input, ctx) {
if (!PseudoClassesMultiRE) {
PseudoClassesMultiRE = new RegExp(`^(${PseudoClassesMultiStr})(?:${ctx.generator.config.separators.join('|')})`)
}

return {
matcher: input.slice(match[0].length),
handle: (input, next) => {
const selectors = pseudo.startsWith('::')
? {
pseudo: `${input.pseudo}${pseudo}`,
}
: {
selector: `${input.selector}${pseudo}`,
}

return next({
...input,
...selectors,
sort: index,
noMerge: true,
})
},
const match = input.match(PseudoClassesMultiRE)
if (match) {
const pseudos = PseudoClassesMulti[match[1]]
return pseudos.map((pseudo) => {
return {
matcher: input.slice(match[0].length),
handle: (input, next) => next({
...input,
pseudo: `${input.pseudo}${pseudo}`,
}),
}
})
}
}
},
multiPass: false,
autocomplete: `(${PseudoClassesMultiStr}):`,
},
multiPass: true,
autocomplete: `(${PseudoClassesAndElementsStr}|${PseudoClassesAndElementsColonStr}):`,
}
]
}

export function variantPseudoClassFunctions(): VariantObject {
Expand Down
8 changes: 5 additions & 3 deletions test/assets/output/preset-mini/targets.css
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,8 @@ unocss .scope-\[unocss\]\:block{display:block;}
.bg-teal-400\/\[\.55\]{background-color:rgb(45 212 191 / .55);}
.bg-teal-500\/\[55\%\]{background-color:rgb(20 184 166 / 55%);}
.first-letter\:bg-green-400::first-letter{--licl-bg-opacity:1;background-color:rgb(74 222 128 / var(--licl-bg-opacity));}
.marker\:bg-violet-200 *::marker,
.marker\:bg-violet-200::marker{--licl-bg-opacity:1;background-color:rgb(221 214 254 / var(--licl-bg-opacity));}
.first-line\:bg-green-400::first-line{--licl-bg-opacity:1;background-color:rgb(74 222 128 / var(--licl-bg-opacity));}
.peer-aria:checked~.peer-aria-checked\:bg-blue-500,
.peer:checked~.peer-checked\:bg-blue-500{--licl-bg-opacity:1;background-color:rgb(59 130 246 / var(--licl-bg-opacity));}
Expand All @@ -686,11 +688,10 @@ unocss .scope-\[unocss\]\:block{display:block;}
.bg-\[--css-bg\,theme\(spacing\.sm\)\]{background-color:var(--css-bg,28rpx);}
.focus-within\:has-first\:checked\:bg-gray\/20:checked:has(:first-child):focus-within{background-color:rgb(156 163 175 / 0.2);}
.focus-within\:where-first\:checked\:bg-gray\/20:checked:where(:first-child):focus-within{background-color:rgb(156 163 175 / 0.2);}
.hover\:file\:bg-violet-100:hover::file-selector-button{--licl-bg-opacity:1;background-color:rgb(237 233 254 / var(--licl-bg-opacity));}
.hover\:file\:bg-violet-100::file-selector-button:hover{--licl-bg-opacity:1;background-color:rgb(237 233 254 / var(--licl-bg-opacity));}
.hover\:is-first\:checked\:bg-true-gray\/10:checked:is(:first-child):hover{background-color:rgb(163 163 163 / 0.1);}
.hover\:not-first\:checked\:bg-red\/10:checked:not(:first-child):hover{background-color:rgb(248 113 113 / 0.1);}
.hover\:not-first\:checked\:bg-true-gray\/10:checked:not(:first-child):hover{background-color:rgb(163 163 163 / 0.1);}
.marker\:bg-violet-200::marker{--licl-bg-opacity:1;background-color:rgb(221 214 254 / var(--licl-bg-opacity));}
.file\:bg-violet-50::file-selector-button{--licl-bg-opacity:1;background-color:rgb(245 243 255 / var(--licl-bg-opacity));}
.bg-opacity-\[--opacity-variable\],
.bg-opacity-\$opacity-variable{--licl-bg-opacity:var(--opacity-variable);}
Expand Down Expand Up @@ -973,14 +974,15 @@ unocss .scope-\[unocss\]\:block{display:block;}
.color-blue-gray\/10,
.color-bluegray-400\/10,
.color-bluegray\/10{color:rgb(148 163 184 / 0.1);}
.selection\:color-\[var\(--select-color\)\] *::selection,
.selection\:color-\[var\(--select-color\)\]::selection{color:var(--select-color);}
.open\:color-pink-100[open]{--licl-text-opacity:1;color:rgb(252 231 243 / var(--licl-text-opacity));}
.c-\[theme\(colors\.red\.500\/50\%\)\]{color:rgb(239 68 68 / 50%);}
.placeholder-shown-color-transparent:placeholder-shown{color:transparent;}
.in-range\:color-pink-100:in-range{--licl-text-opacity:1;color:rgb(252 231 243 / var(--licl-text-opacity));}
.out-of-range\:color-pink-100:out-of-range{--licl-text-opacity:1;color:rgb(252 231 243 / var(--licl-text-opacity));}
.placeholder-color-red-1::placeholder{--licl-text-opacity:1;color:rgb(254 226 226 / var(--licl-text-opacity));}
.placeholder\:color-transparent::placeholder{color:transparent;}
.selection\:color-\[var\(--select-color\)\] ::selection{color:var(--select-color);}
.text-opacity-\[13\.3333333\%\]{--licl-text-opacity:13.3333333%;}
.text-opacity-\$opacity-variable{--licl-text-opacity:var(--opacity-variable);}
.placeholder-color-opacity-60::placeholder{--licl-text-opacity:0.6;}
Expand Down
8 changes: 5 additions & 3 deletions test/assets/output/preset-weapp/targets-custom-rules.css
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,8 @@ unocss .scope-_lfl11_unocss_lfr11__cl11_block{display:block;}
.bg-teal-400_sl11__lfl11__dl11_55_lfr11_{background-color:rgb(45 212 191 / .55);}
.bg-teal-500_sl11__lfl11_55_pes11__lfr11_{background-color:rgb(20 184 166 / 55%);}
.first-letter_cl11_bg-green-400::first-letter{--un-bg-opacity:1;background-color:rgb(74 222 128 / var(--un-bg-opacity));}
.marker_cl11_bg-violet-200 *::marker,
.marker_cl11_bg-violet-200::marker{--un-bg-opacity:1;background-color:rgb(221 214 254 / var(--un-bg-opacity));}
.first-line_cl11_bg-green-400::first-line{--un-bg-opacity:1;background-color:rgb(74 222 128 / var(--un-bg-opacity));}
.peer-aria:checked~.peer-aria-checked_cl11_bg-blue-500,
.peer:checked~.peer-checked_cl11_bg-blue-500{--un-bg-opacity:1;background-color:rgb(59 130 246 / var(--un-bg-opacity));}
Expand All @@ -684,11 +686,10 @@ unocss .scope-_lfl11_unocss_lfr11__cl11_block{display:block;}
.bg-_lfl11_--css-bg_lco11_theme_lbl11_spacing_dl11_sm_lbr11__lfr11_{background-color:var(--css-bg,28rpx);}
.focus-within_cl11_has-first_cl11_checked_cl11_bg-gray_sl11_20:checked:has(:first-child):focus-within{background-color:rgb(156 163 175 / 0.2);}
.focus-within_cl11_where-first_cl11_checked_cl11_bg-gray_sl11_20:checked:where(:first-child):focus-within{background-color:rgb(156 163 175 / 0.2);}
.hover_cl11_file_cl11_bg-violet-100:hover::file-selector-button{--un-bg-opacity:1;background-color:rgb(237 233 254 / var(--un-bg-opacity));}
.hover_cl11_file_cl11_bg-violet-100::file-selector-button:hover{--un-bg-opacity:1;background-color:rgb(237 233 254 / var(--un-bg-opacity));}
.hover_cl11_is-first_cl11_checked_cl11_bg-true-gray_sl11_10:checked:is(:first-child):hover{background-color:rgb(163 163 163 / 0.1);}
.hover_cl11_not-first_cl11_checked_cl11_bg-red_sl11_10:checked:not(:first-child):hover{background-color:rgb(248 113 113 / 0.1);}
.hover_cl11_not-first_cl11_checked_cl11_bg-true-gray_sl11_10:checked:not(:first-child):hover{background-color:rgb(163 163 163 / 0.1);}
.marker_cl11_bg-violet-200::marker{--un-bg-opacity:1;background-color:rgb(221 214 254 / var(--un-bg-opacity));}
.file_cl11_bg-violet-50::file-selector-button{--un-bg-opacity:1;background-color:rgb(245 243 255 / var(--un-bg-opacity));}
.bg-opacity-_do11_opacity-variable,
.bg-opacity-_lfl11_--opacity-variable_lfr11_{--un-bg-opacity:var(--opacity-variable);}
Expand Down Expand Up @@ -974,14 +975,15 @@ unocss .scope-_lfl11_unocss_lfr11__cl11_block{display:block;}
.color-blue-gray-400_sl11_10,
.color-bluegray_sl11_10,
.color-bluegray-400_sl11_10{color:rgb(148 163 184 / 0.1);}
.selection_cl11_color-_lfl11_var_lbl11_--select-color_lbr11__lfr11_ *::selection,
.selection_cl11_color-_lfl11_var_lbl11_--select-color_lbr11__lfr11_::selection{color:var(--select-color);}
.open_cl11_color-pink-100[open]{--un-text-opacity:1;color:rgb(252 231 243 / var(--un-text-opacity));}
.c-_lfl11_theme_lbl11_colors_dl11_red_dl11_500_sl11_50_pes11__lbr11__lfr11_{color:rgb(239 68 68 / 50%);}
.placeholder-shown-color-transparent:placeholder-shown{color:transparent;}
.in-range_cl11_color-pink-100:in-range{--un-text-opacity:1;color:rgb(252 231 243 / var(--un-text-opacity));}
.out-of-range_cl11_color-pink-100:out-of-range{--un-text-opacity:1;color:rgb(252 231 243 / var(--un-text-opacity));}
.placeholder_cl11_color-transparent::placeholder{color:transparent;}
.placeholder-color-red-1::placeholder{--un-text-opacity:1;color:rgb(254 226 226 / var(--un-text-opacity));}
.selection_cl11_color-_lfl11_var_lbl11_--select-color_lbr11__lfr11_ ::selection{color:var(--select-color);}
.text-opacity-_do11_opacity-variable{--un-text-opacity:var(--opacity-variable);}
.text-opacity-_lfl11_13_dl11_3333333_pes11__lfr11_{--un-text-opacity:13.3333333%;}
.placeholder-color-opacity-60::placeholder{--un-text-opacity:0.6;}
Expand Down
8 changes: 5 additions & 3 deletions test/assets/output/preset-weapp/targets.css
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,8 @@ unocss .scope-_lfl_unocss_lfr__cl_block{display:block;}
.bg-teal-500_sl__lfl_55_pes__lfr_{background-color:rgb(20 184 166 / 55%);}
.dark .dark_cl_bg-white{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity));}
.first-letter_cl_bg-green-400::first-letter{--un-bg-opacity:1;background-color:rgb(74 222 128 / var(--un-bg-opacity));}
.marker_cl_bg-violet-200 *::marker,
.marker_cl_bg-violet-200::marker{--un-bg-opacity:1;background-color:rgb(221 214 254 / var(--un-bg-opacity));}
.first-line_cl_bg-green-400::first-line{--un-bg-opacity:1;background-color:rgb(74 222 128 / var(--un-bg-opacity));}
.peer-aria:checked~.peer-aria-checked_cl_bg-blue-500,
.peer:checked~.peer-checked_cl_bg-blue-500{--un-bg-opacity:1;background-color:rgb(59 130 246 / var(--un-bg-opacity));}
Expand All @@ -687,11 +689,10 @@ unocss .scope-_lfl_unocss_lfr__cl_block{display:block;}
.bg-_lfl_--css-bg_lco_theme_lbl_spacing_dl_sm_lbr__lfr_{background-color:var(--css-bg,28rpx);}
.focus-within_cl_has-first_cl_checked_cl_bg-gray_sl_20:checked:has(:first-child):focus-within{background-color:rgb(156 163 175 / 0.2);}
.focus-within_cl_where-first_cl_checked_cl_bg-gray_sl_20:checked:where(:first-child):focus-within{background-color:rgb(156 163 175 / 0.2);}
.hover_cl_file_cl_bg-violet-100:hover::file-selector-button{--un-bg-opacity:1;background-color:rgb(237 233 254 / var(--un-bg-opacity));}
.hover_cl_file_cl_bg-violet-100::file-selector-button:hover{--un-bg-opacity:1;background-color:rgb(237 233 254 / var(--un-bg-opacity));}
.hover_cl_is-first_cl_checked_cl_bg-true-gray_sl_10:checked:is(:first-child):hover{background-color:rgb(163 163 163 / 0.1);}
.hover_cl_not-first_cl_checked_cl_bg-red_sl_10:checked:not(:first-child):hover{background-color:rgb(248 113 113 / 0.1);}
.hover_cl_not-first_cl_checked_cl_bg-true-gray_sl_10:checked:not(:first-child):hover{background-color:rgb(163 163 163 / 0.1);}
.marker_cl_bg-violet-200::marker{--un-bg-opacity:1;background-color:rgb(221 214 254 / var(--un-bg-opacity));}
.file_cl_bg-violet-50::file-selector-button{--un-bg-opacity:1;background-color:rgb(245 243 255 / var(--un-bg-opacity));}
.bg-opacity-_do_opacity-variable,
.bg-opacity-_lfl_--opacity-variable_lfr_{--un-bg-opacity:var(--opacity-variable);}
Expand Down Expand Up @@ -977,14 +978,15 @@ unocss .scope-_lfl_unocss_lfr__cl_block{display:block;}
.color-blue-gray-400_sl_10,
.color-bluegray_sl_10,
.color-bluegray-400_sl_10{color:rgb(148 163 184 / 0.1);}
.selection_cl_color-_lfl_var_lbl_--select-color_lbr__lfr_ *::selection,
.selection_cl_color-_lfl_var_lbl_--select-color_lbr__lfr_::selection{color:var(--select-color);}
.open_cl_color-pink-100[open]{--un-text-opacity:1;color:rgb(252 231 243 / var(--un-text-opacity));}
.c-_lfl_theme_lbl_colors_dl_red_dl_500_sl_50_pes__lbr__lfr_{color:rgb(239 68 68 / 50%);}
.placeholder-shown-color-transparent:placeholder-shown{color:transparent;}
.in-range_cl_color-pink-100:in-range{--un-text-opacity:1;color:rgb(252 231 243 / var(--un-text-opacity));}
.out-of-range_cl_color-pink-100:out-of-range{--un-text-opacity:1;color:rgb(252 231 243 / var(--un-text-opacity));}
.placeholder_cl_color-transparent::placeholder{color:transparent;}
.placeholder-color-red-1::placeholder{--un-text-opacity:1;color:rgb(254 226 226 / var(--un-text-opacity));}
.selection_cl_color-_lfl_var_lbl_--select-color_lbr__lfr_ ::selection{color:var(--select-color);}
.text-opacity-_do_opacity-variable{--un-text-opacity:var(--opacity-variable);}
.text-opacity-_lfl_13_dl_3333333_pes__lfr_{--un-text-opacity:13.3333333%;}
.placeholder-color-opacity-60::placeholder{--un-text-opacity:0.6;}
Expand Down

0 comments on commit 2074203

Please sign in to comment.