Skip to content

Commit

Permalink
feat: pseudo-class function for custom arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
MellowCo committed Jun 15, 2023
1 parent 58f8a46 commit 4eac42a
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 9 deletions.
3 changes: 1 addition & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@
"unocss",
"Weapp",
"whitespaces"
],
"testing.automaticallyOpenPeekView": "never"
]
}
35 changes: 28 additions & 7 deletions src/variants/pseudo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { escapeRegExp, escapeSelector, warnOnce } from '@unocss/core'

import { restoreSelector } from 'unplugin-transform-class/utils'
import type { PresetWeappOptions } from '..'
import { handler as h, variantGetBracket } from '../utils'
import { getBracket, h, variantGetBracket } from '../utils'
import type { Theme } from '../theme'

const PseudoClasses: Record<string, string> = Object.fromEntries([
Expand Down Expand Up @@ -94,8 +94,9 @@ function taggedPseudoClassMatcher(tag: string, parent: string, combinator: strin
let splitRE: RegExp
let pseudoRE: RegExp
let pseudoColonRE: RegExp
let pseudoVarRE: RegExp

const matchBracket = (input: string) => {
const matchBracket = (input: string): [label: string, rest: string, prefix: string] | undefined => {
const body = variantGetBracket(`${tag}-`, input, [])
if (!body)
return
Expand All @@ -114,7 +115,7 @@ function taggedPseudoClassMatcher(tag: string, parent: string, combinator: strin
]
}

const matchPseudo = (input: string) => {
const matchPseudo = (input: string): [label: string, rest: string, prefix: string, pseudoKey: string] | undefined => {
const match = input.match(pseudoRE) || input.match(pseudoColonRE)
if (!match)
return
Expand All @@ -133,23 +134,39 @@ function taggedPseudoClassMatcher(tag: string, parent: string, combinator: strin
]
}

const matchPseudoVar = (input: string): [label: string, rest: string, prefix: string] | undefined => {
const match = input.match(pseudoVarRE)
if (!match)
return
const [original, fn, pseudoValue] = match
const label = match[3] ?? ''
const pseudo = `:${fn}(${pseudoValue})`

return [
label,
input.slice(original.length),
`${parent}${escapeSelector(label)}${pseudo}`,
]
}

return {
name: `pseudo:${tag}`,
match(input, ctx) {
if (!(splitRE && pseudoRE && pseudoColonRE)) {
splitRE = new RegExp(`(?:${ctx.generator.config.separators.join('|')})`)
pseudoRE = new RegExp(`^${tag}-(?:(?:(${PseudoClassFunctionsStr})-)?(${PseudoClassesStr}))(?:(/\\w+))?(?:${ctx.generator.config.separators.join('|')})`)
pseudoColonRE = new RegExp(`^${tag}-(?:(?:(${PseudoClassFunctionsStr})-)?(${PseudoClassesColonStr}))(?:(/\\w+))?(?:${ctx.generator.config.separators.filter(x => x !== '-').join('|')})`)
pseudoVarRE = new RegExp(`^${tag}-(?:(${PseudoClassFunctionsStr})-)?\\[(.+)\\](?:(/\\w+))?(?:${ctx.generator.config.separators.filter(x => x !== '-').join('|')})`)
}

if (!input.startsWith(tag))
return

const result = matchBracket(input) || matchPseudo(input)
const result = matchBracket(input) || matchPseudo(input) || matchPseudoVar(input)
if (!result)
return

const [label, matcher, prefix, pseudoName = ''] = result as [string, string, string, string | undefined]
const [label, matcher, prefix, pseudoName = ''] = result

if (label !== '')
warnOnce('The labeled variant is experimental and may not follow semver.')
Expand Down Expand Up @@ -222,17 +239,21 @@ export function variantPseudoClassesAndElements(): VariantObject<Theme> {
export function variantPseudoClassFunctions(): VariantObject {
let PseudoClassFunctionsRE: RegExp
let PseudoClassColonFunctionsRE: RegExp
let PseudoClassVarFunctionRE: RegExp

return {
match(input, ctx) {
if (!(PseudoClassFunctionsRE && PseudoClassColonFunctionsRE)) {
PseudoClassFunctionsRE = new RegExp(`^(${PseudoClassFunctionsStr})-(${PseudoClassesStr})(?:${ctx.generator.config.separators.join('|')})`)
PseudoClassColonFunctionsRE = new RegExp(`^(${PseudoClassFunctionsStr})-(${PseudoClassesColonStr})(?:${ctx.generator.config.separators.filter(x => x !== '-').join('|')})`)
PseudoClassVarFunctionRE = new RegExp(`^(${PseudoClassFunctionsStr})-(\\[.+\\])(?:${ctx.generator.config.separators.filter(x => x !== '-').join('|')})`)
}

const match = input.match(PseudoClassFunctionsRE) || input.match(PseudoClassColonFunctionsRE)
const match = input.match(PseudoClassFunctionsRE) || input.match(PseudoClassColonFunctionsRE) || input.match(PseudoClassVarFunctionRE)
if (match) {
const fn = match[1]
const pseudo = PseudoClasses[match[2]] || PseudoClassesColon[match[2]] || `:${match[2]}`
const fnVal = getBracket(match[2], '[', ']')
const pseudo = fnVal ? h.bracket(match[2]) : (PseudoClasses[match[2]] || PseudoClassesColon[match[2]] || `:${match[2]}`)
return {
matcher: input.slice(match[0].length),
selector: s => `${s}:${fn}(${pseudo})`,
Expand Down

0 comments on commit 4eac42a

Please sign in to comment.