Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(variant-group): transformer variant group changes regular express… #3211

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion packages/core/src/generator/index.ts
Expand Up @@ -626,7 +626,7 @@ export class UnoGenerator<Theme extends object = object> {

// expand nested shortcuts
if (isString(result))
result = expandVariantGroup(result.trim()).split(/\s+/g)
result = expandVariantGroup(result.trim(), undefined, undefined, 'shortcut').split(/\s+/g)

// expand nested shortcuts with variants
if (!result) {
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/types.ts
Expand Up @@ -654,7 +654,8 @@ export interface SourceCodeTransformer {
transform: (
code: MagicString,
id: string,
ctx: UnocssPluginContext
ctx: UnocssPluginContext,
type?: string
) => Awaitable<{ highlightAnnotations?: HighlightAnnotation[] } | void>
}

Expand Down
23 changes: 17 additions & 6 deletions packages/core/src/utils/variant-group.ts
Expand Up @@ -17,18 +17,29 @@ interface VariantGroup {
items: HighlightAnnotation[]
}

export function parseVariantGroup(str: string | MagicString, separators = ['-', ':'], depth = 5) {
export function parseVariantGroup(str: string | MagicString, separators = ['-', ':'], depth = 5, type?: string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where the type used for, other than checking if it presents? Should be make a literal enum like 'shourtcut' | 'rule' | ...?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it to a boolean type. It seems that I only need to determine whether I need to enable the conversion of attributes. I changed it to a boolean type. It seems that I only need to determine whether I need to enable the conversion of attributes.

const regexClassGroup = makeRegexClassGroup(separators)
let hasChanged
let content = str.toString()
const prefixes = new Set<string>()
const groupsByOffset = new Map<number, VariantGroup>()

const processedStr = (str: string) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
const isAttributor = (matchText: string, offset: number) => {
const reg = new RegExp(`<[\\w_\\-]+[^>\\/]*${processedStr(matchText)}[^>\\/]*\/?>`, 'gm')
Simon-He95 marked this conversation as resolved.
Show resolved Hide resolved
for (const match of content.matchAll(reg)) {
const index = match.index!
if (index < offset && (index + match[0].length > offset))
return true
}
return false
}
do {
hasChanged = false
content = content.replace(
regexClassGroup,
(from, pre: string, sep: string, body: string, groupOffset: number) => {
if (!type && !isAttributor(from, groupOffset))
return from
if (!separators.includes(sep))
return from

Expand Down Expand Up @@ -135,10 +146,10 @@ export function collapseVariantGroup(str: string, prefixes: string[]): string {
.join(' ')
}

export function expandVariantGroup(str: string, separators?: string[], depth?: number): string
export function expandVariantGroup(str: MagicString, separators?: string[], depth?: number): MagicString
export function expandVariantGroup(str: string | MagicString, separators = ['-', ':'], depth = 5) {
const res = parseVariantGroup(str, separators, depth)
export function expandVariantGroup(str: string, separators?: string[], depth?: number, type?: string): string
export function expandVariantGroup(str: MagicString, separators?: string[], depth?: number, type?: string): MagicString
export function expandVariantGroup(str: string | MagicString, separators = ['-', ':'], depth = 5, type?: string) {
const res = parseVariantGroup(str, separators, depth, type)
return typeof str === 'string'
? res.expanded
: str
Expand Down
4 changes: 3 additions & 1 deletion packages/shared-common/src/index.ts
Expand Up @@ -190,9 +190,11 @@ export async function getMatchedPositionsFromCode(uno: UnoGenerator, code: strin

const transformers = uno.config.transformers?.filter(i => !ignoreTransformers.includes(i.name))
const annotations = []
const _isPug = (await isPug(uno, s.toString(), id)).pug

for (const enforce of ['pre', 'default', 'post']) {
for (const i of transformers?.filter(i => (i.enforce ?? 'default') === enforce) || []) {
const result = await i.transform(s, id, ctx)
const result = await i.transform(s, id, ctx, _isPug ? 'pug' : '')
const _annotations = result?.highlightAnnotations
if (_annotations)
annotations.push(..._annotations)
Expand Down
2 changes: 1 addition & 1 deletion packages/shared-integration/src/sort-rules.ts
Expand Up @@ -11,7 +11,7 @@ export async function sortRules(rules: string, uno: UnoGenerator) {
// const hasAttributify = !!uno.config.presets.find(i => i.name === '@unocss/preset-attributify')
// const hasVariantGroup = !!uno.config.transformers?.find(i => i.name === '@unocss/transformer-variant-group')

const expandedResult = parseVariantGroup(rules) // todo read seperators from config
const expandedResult = parseVariantGroup(rules, undefined, undefined, 'sort') // todo read seperators from config
rules = expandedResult.expanded

const result = await Promise.all(rules.split(/\s+/g)
Expand Down
Expand Up @@ -4,7 +4,7 @@ import { expandVariantGroup, warnOnce } from '@unocss/core'
type Writeable<T> = { -readonly [P in keyof T]: T[P] }

export async function getUtils(body: string, uno: UnoGenerator): Promise<StringifiedUtil[]> {
const classNames = expandVariantGroup(body)
const classNames = expandVariantGroup(body, undefined, undefined, 'utils')
.split(/\s+/g)
.map(className => className.trim().replace(/\\/, ''))

Expand Down
Expand Up @@ -13,7 +13,7 @@ export async function processClassBody(
uno: UnoGenerator,
filename: string,
): Promise<Partial<ProcessResult>> {
const expandedBody = expandVariantGroup(body)
const expandedBody = expandVariantGroup(body, undefined, undefined, 'class')

const { rulesToGenerate: rulesFromExpressions, restOfBody, updatedExpressions } = await processExpressions(expandedBody, options, uno, filename)
const { rulesToGenerate: rulesFromRegularClasses, ignore } = await sortClassesIntoCategories(restOfBody, options, uno, filename)
Expand Down
5 changes: 2 additions & 3 deletions packages/transformer-directives/src/apply.ts
Expand Up @@ -37,7 +37,7 @@ export async function parseApply({ code, uno, offset, applyVariable }: Transform
if (!body)
return

const classNames = expandVariantGroup(body)
const classNames = expandVariantGroup(body, undefined, undefined, childNode.type)
.split(/\s+/g)
.map(className => className.trim().replace(/\\/, ''))

Expand All @@ -53,7 +53,7 @@ export async function parseApply({ code, uno, offset, applyVariable }: Transform
if (target)
target[2] += item[2]
else
// use spread operator to prevent reassign to uno internal cache
// use spread operator to prevent reassign to uno internal cache
acc.push([...item] as Writeable<StringifiedUtil>)
return acc
}, [] as Writeable<StringifiedUtil>[])
Expand Down Expand Up @@ -84,7 +84,6 @@ export async function parseApply({ code, uno, offset, applyVariable }: Transform
})
newSelector = generate(prelude)
}

let css = `${newSelector}{${body}}`
if (parent)
css = `${parent}{${css}}`
Expand Down
4 changes: 2 additions & 2 deletions packages/transformer-variant-group/src/index.ts
Expand Up @@ -25,8 +25,8 @@ export default function transformerVariantGroup(
return {
name: '@unocss/transformer-variant-group',
enforce: 'pre',
transform(s) {
const result = parseVariantGroup(s, options.separators)
transform(s, id, ctx, type) {
const result = parseVariantGroup(s, options.separators, undefined, type)
return {
get highlightAnnotations() {
return [...result.groupsByOffset.values()].flatMap(group => group.items)
Expand Down