Skip to content

Commit

Permalink
feat(core,presets)!: update to use the recursive callback
Browse files Browse the repository at this point in the history
  • Loading branch information
chu121su12 committed Jun 21, 2022
1 parent ef0d9be commit 91ea249
Show file tree
Hide file tree
Showing 25 changed files with 254 additions and 97 deletions.
15 changes: 11 additions & 4 deletions packages/core/src/generator/index.ts
Expand Up @@ -322,7 +322,7 @@ export class UnoGenerator {
if (typeof handler === 'string')
handler = { matcher: handler }
processed = handler.matcher
handlers.unshift(handler)
handlers.push(handler)
variants.add(v)
applied = true
break
Expand Down Expand Up @@ -352,6 +352,7 @@ export class UnoGenerator {
? (Array.isArray(v.parent) ? v.parent : [v.parent ?? '', undefined])
: [input.parent, input.parentOrder]
return (v.handler ?? defaultHandler)({
...input,
entries,
selector: v.selector?.(input.selector, entries) || input.selector,
parent: parents[0],
Expand All @@ -364,16 +365,22 @@ export class UnoGenerator {
)

const variantContextResult = handler({
entries: parsed[2],
prefix: '',
selector: toEscapedSelector(raw),
pseudo: '',
entries: parsed[2],
})

const { parent, parentOrder, selector } = variantContextResult
const { parent, parentOrder } = variantContextResult
if (parent != null && parentOrder != null)
this.parentOrders.set(parent, parentOrder)

const obj: UtilObject = {
selector: movePseudoElementsEnd(selector),
selector: movePseudoElementsEnd([
variantContextResult.prefix,
variantContextResult.selector,
variantContextResult.pseudo,
].join('')),
entries: variantContextResult.entries,
parent,
layer: variantContextResult.layer,
Expand Down
10 changes: 9 additions & 1 deletion packages/core/src/types.ts
Expand Up @@ -191,9 +191,17 @@ export type BlocklistRule = string | RegExp

export interface VariantHandlerContext {
/**
* Rewrite the output selector. Often be used to append pesudo classes or parents.
* Rewrite the output selector. Often be used to append parents.
*/
prefix: string
/**
* Rewrite the output selector. Often be used to append pesudo classes.
*/
selector: string
/**
* Rewrite the output selector. Often be used to append pesudo elements.
*/
pseudo: string
/**
* Rewrite the output css body. The input come in [key,value][] pairs.
*/
Expand Down
14 changes: 10 additions & 4 deletions packages/preset-mini/src/utils/variants.ts
@@ -1,7 +1,7 @@
import type { VariantHandler, VariantObject } from '@unocss/core'
import type { VariantHandler, VariantHandlerContext, VariantObject } from '@unocss/core'
import { escapeRegExp } from '@unocss/core'

export const variantMatcher = (name: string, selector?: (input: string) => string | undefined): VariantObject => {
export const variantMatcher = (name: string, handler: (input: VariantHandlerContext) => Record<string, any>): VariantObject => {
const re = new RegExp(`^${escapeRegExp(name)}[:-]`)
return {
name,
Expand All @@ -10,7 +10,10 @@ export const variantMatcher = (name: string, selector?: (input: string) => strin
if (match) {
return {
matcher: input.slice(match[0].length),
selector,
handler: (input, next) => next({
...input,
...handler(input),
}),
}
}
},
Expand All @@ -27,7 +30,10 @@ export const variantParentMatcher = (name: string, parent: string): VariantObjec
if (match) {
return {
matcher: input.slice(match[0].length),
parent,
handler: (input, next) => next({
...input,
parent,
}),
}
}
},
Expand Down
18 changes: 15 additions & 3 deletions packages/preset-mini/src/variants/breakpoints.ts
Expand Up @@ -42,7 +42,11 @@ export const variantBreakpoints: Variant<Theme> = {
order -= (idx + 1)
return {
matcher: m,
parent: [`@media (max-width: ${calcMaxWidthBySize(size)})`, order],
handler: (input, next) => next({
...input,
parent: `@media (max-width: ${calcMaxWidthBySize(size)})`,
parentOrder: order,
}),
}
}

Expand All @@ -52,13 +56,21 @@ export const variantBreakpoints: Variant<Theme> = {
if (isAtPrefix && idx < variantEntries.length - 1) {
return {
matcher: m,
parent: [`@media (min-width: ${size}) and (max-width: ${calcMaxWidthBySize(variantEntries[idx + 1][1])})`, order],
handler: (input, next) => next({
...input,
parent: `@media (min-width: ${size}) and (max-width: ${calcMaxWidthBySize(variantEntries[idx + 1][1])})`,
parentOrder: order,
}),
}
}

return {
matcher: m,
parent: [`@media (min-width: ${size})`, order],
handler: (input, next) => next({
...input,
parent: `@media (min-width: ${size})`,
parentOrder: order,
}),
}
}
},
Expand Down
5 changes: 4 additions & 1 deletion packages/preset-mini/src/variants/combinators.ts
Expand Up @@ -11,7 +11,10 @@ const scopeMatcher = (strict: boolean, name: string, template: string): VariantO
if (match) {
return {
matcher: matcher.slice(match[0].length),
selector: s => template.replace('&&-s', s).replace('&&-c', match[1] ?? '*'),
handler: (input, next) => next({
...input,
selector: template.replace('&&-s', input.selector).replace('&&-c', match[1] ?? '*'),
}),
}
}
},
Expand Down
4 changes: 2 additions & 2 deletions packages/preset-mini/src/variants/dark.ts
Expand Up @@ -5,8 +5,8 @@ import { variantMatcher, variantParentMatcher } from '../utils'
export const variantColorsMediaOrClass = (options: PresetMiniOptions = {}): Variant[] => {
if (options?.dark === 'class') {
return [
variantMatcher('dark', input => `.dark $$ ${input}`),
variantMatcher('light', input => `.light $$ ${input}`),
variantMatcher('dark', input => ({ prefix: `${input.prefix}.dark $$ ` })),
variantMatcher('light', input => ({ prefix: `${input.prefix}.light $$ ` })),
]
}

Expand Down
4 changes: 2 additions & 2 deletions packages/preset-mini/src/variants/directions.ts
Expand Up @@ -2,6 +2,6 @@ import type { Variant } from '@unocss/core'
import { variantMatcher } from '../utils'

export const variantLanguageDirections: Variant[] = [
variantMatcher('rtl', input => `[dir="rtl"] $$ ${input}`),
variantMatcher('ltr', input => `[dir="ltr"] $$ ${input}`),
variantMatcher('rtl', input => ({ prefix: `${input.prefix}[dir="rtl"] $$ ` })),
variantMatcher('ltr', input => ({ prefix: `${input.prefix}[dir="ltr"] $$ ` })),
]
6 changes: 3 additions & 3 deletions packages/preset-mini/src/variants/important.ts
Expand Up @@ -14,12 +14,12 @@ export const variantImportant: Variant = {
if (base) {
return {
matcher: base,
body: (body) => {
body.forEach((v) => {
handler: (input, next) => {
input.entries.forEach((v) => {
if (v[1])
v[1] += ' !important'
})
return body
return next(input)
},
}
}
Expand Down
5 changes: 4 additions & 1 deletion packages/preset-mini/src/variants/media.ts
Expand Up @@ -12,7 +12,10 @@ export const variantCustomMedia: VariantObject = {
const media = theme.media?.[match[1]] ?? `(--${match[1]})`
return {
matcher: matcher.slice(match[0].length),
parent: `@media ${media}`,
handler: (input, next) => next({
...input,
parent: `@media ${media}`,
}),
}
}
},
Expand Down
20 changes: 16 additions & 4 deletions packages/preset-mini/src/variants/misc.ts
Expand Up @@ -7,7 +7,10 @@ export const variantSelector: Variant = {
if (match) {
return {
matcher: matcher.slice(match[0].length),
selector: () => match[1],
handler: (input, next) => next({
...input,
selector: match[1],
}),
}
}
},
Expand All @@ -20,7 +23,10 @@ export const variantCssLayer: Variant = {
if (match) {
return {
matcher: matcher.slice(match[0].length),
parent: `@layer ${match[1]}`,
handler: (input, next) => next({
...input,
parent: `@layer ${match[1]}`,
}),
}
}
},
Expand All @@ -33,7 +39,10 @@ export const variantInternalLayer: Variant = {
if (match) {
return {
matcher: matcher.slice(match[0].length),
layer: match[1],
handler: (input, next) => next({
...input,
layer: match[1],
}),
}
}
},
Expand All @@ -46,7 +55,10 @@ export const variantScope: Variant = {
if (match) {
return {
matcher: matcher.slice(match[0].length),
selector: s => `.${match[1]} $$ ${s}`,
handler: (input, next) => next({
...input,
prefix: `${input.prefix}.${match[1]} $$ `,
}),
}
}
},
Expand Down
39 changes: 23 additions & 16 deletions packages/preset-mini/src/variants/negative.ts
Expand Up @@ -15,24 +15,31 @@ export const variantNegative: Variant = {

return {
matcher: matcher.slice(1),
body: (body) => {
if (body.find(v => v[0] === CONTROL_MINI_NO_NEGATIVE))
return
let changed = false
body.forEach((v) => {
const value = v[1]?.toString()
if (!value || value === '0')
handler: (input, next) => {
const body = ((body) => {
if (body.find(v => v[0] === CONTROL_MINI_NO_NEGATIVE))
return
if (ignoreProps.some(i => v[0].match(i)))
return
if (numberRE.test(value)) {
v[1] = value.replace(numberRE, i => `-${i}`)
changed = true
}
let changed = false
body.forEach((v) => {
const value = v[1]?.toString()
if (!value || value === '0')
return
if (ignoreProps.some(i => v[0].match(i)))
return
if (numberRE.test(value)) {
v[1] = value.replace(numberRE, i => `-${i}`)
changed = true
}
})
if (changed)
return body
return []
})(input.entries)

return next({
...input,
entries: body ?? input.entries,
})
if (changed)
return body
return []
},
}
},
Expand Down
30 changes: 21 additions & 9 deletions packages/preset-mini/src/variants/pseudo.ts
Expand Up @@ -82,7 +82,7 @@ const sortValue = (pseudo: string) => {
}

const taggedPseudoClassMatcher = (tag: string, parent: string, combinator: string): VariantObject => {
const rawRe = new RegExp(`^${escapeRegExp(parent)}:`)
const rawRe = new RegExp(`${escapeRegExp(parent)}:`)
const pseudoRE = new RegExp(`^${tag}-((?:(${PseudoClassFunctionsStr})-)?(${PseudoClassesStr}))[:-]`)
const pseudoColonRE = new RegExp(`^${tag}-((?:(${PseudoClassFunctionsStr})-)?(${PseudoClassesColonStr}))[:]`)
return {
Expand All @@ -95,10 +95,13 @@ const taggedPseudoClassMatcher = (tag: string, parent: string, combinator: strin
pseudo = `:${match[2]}(${pseudo})`
return {
matcher: input.slice(match[0].length),
selector: s => rawRe.test(s)
? s.replace(rawRe, `${parent}${pseudo}:`)
: `${parent}${pseudo}${combinator}${s}`,
sort: sortValue(match[3]),
handler: (input, next) => next({
...input,
prefix: rawRe.test(input.prefix)
? input.prefix.replace(rawRe, `${parent}${pseudo}:`)
: `${input.prefix}${parent}${pseudo}${combinator}`,
sort: sortValue(match[3]),
}),
}
}
},
Expand All @@ -117,8 +120,11 @@ export const variantPseudoClassesAndElements: VariantObject = {
const pseudo = PseudoClasses[match[1]] || PseudoClassesColon[match[1]] || `:${match[1]}`
return {
matcher: input.slice(match[0].length),
selector: s => `${s}${pseudo}`,
sort: sortValue(match[1]),
handler: (input, next) => next({
...input,
selector: `${input.selector}${pseudo}`,
sort: sortValue(match[1]),
}),
}
}
},
Expand All @@ -136,7 +142,10 @@ export const variantPseudoClassFunctions: VariantObject = {
const pseudo = PseudoClasses[match[2]] || PseudoClassesColon[match[2]] || `:${match[2]}`
return {
matcher: input.slice(match[0].length),
selector: s => `${s}:${fn}(${pseudo})`,
handler: (input, next) => next({
...input,
selector: `${input.selector}:${fn}(${pseudo})`,
}),
}
}
},
Expand Down Expand Up @@ -175,7 +184,10 @@ export const partClasses: VariantObject = {
const part = `part(${match[2]})`
return {
matcher: input.slice(match[1].length),
selector: s => `${s}::${part}`,
handler: (input, next) => next({
...input,
selector: `${input.selector}::${part}`,
}),
}
}
},
Expand Down
26 changes: 15 additions & 11 deletions packages/preset-tagify/src/variant.ts
@@ -1,4 +1,4 @@
import type { VariantHandler, VariantObject } from '@unocss/core'
import type { VariantObject } from '@unocss/core'
import type { TagifyOptions } from './types'
import { MARKER } from './extractor'

Expand All @@ -13,19 +13,23 @@ export const variantTagify = (options: TagifyOptions): VariantObject => {
return

const matcher = input.slice(prefix.length)
const handler: VariantHandler = {

return {
matcher,
selector: i => i.slice(MARKER.length + 1),
}
handler: (input, next) => {
if (extraProperties) {
if (typeof extraProperties === 'function')
input.entries.push(...Object.entries(extraProperties(matcher) ?? {}))
else
input.entries.push(...Object.entries(extraProperties))
}

if (extraProperties) {
if (typeof extraProperties === 'function')
handler.body = entries => [...entries, ...Object.entries(extraProperties(matcher) ?? {})]
else
handler.body = entries => [...entries, ...Object.entries(extraProperties)]
return next({
...input,
selector: input.selector.slice(MARKER.length + 1),
})
},
}

return handler
},
}
}

0 comments on commit 91ea249

Please sign in to comment.