Skip to content

Commit

Permalink
feat: configurable separator
Browse files Browse the repository at this point in the history
  • Loading branch information
MellowCo committed Jun 15, 2023
1 parent 18101dd commit 58f8a46
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 186 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
"unocss",
"Weapp",
"whitespaces"
]
],
"testing.automaticallyOpenPeekView": "never"
}
14 changes: 10 additions & 4 deletions src/utils/variants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import { defaultRules, restoreSelector } from 'unplugin-transform-class/utils'
import { getBracket } from '../utils'

export function variantMatcher(name: string, handler: (input: VariantHandlerContext) => Record<string, any>, transformRules: Record<string, string> = defaultRules): VariantObject {
const re = new RegExp(`^${escapeRegExp(name)}[:-]`)
let re: RegExp

return {
name,
match(input) {
match(input, ctx) {
if (!re)
re = new RegExp(`^${escapeRegExp(name)}(?:${ctx.generator.config.separators.join('|')})`)

input = restoreSelector(input, transformRules)
const match = input.match(re)
if (match) {
Expand All @@ -26,10 +29,13 @@ export function variantMatcher(name: string, handler: (input: VariantHandlerCont
}

export function variantParentMatcher(name: string, parent: string, transformRules: Record<string, string> = defaultRules): VariantObject {
const re = new RegExp(`^${escapeRegExp(name)}[:-]`)
let re: RegExp
return {
name,
match(input) {
match(input, ctx) {
if (!re)
re = new RegExp(`^${escapeRegExp(name)}(?:${ctx.generator.config.separators.join('|')})`)

input = restoreSelector(input, transformRules)
const match = input.match(re)
if (match) {
Expand Down
8 changes: 4 additions & 4 deletions src/variants/aria.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { VariantContext, VariantObject } from '@unocss/core'
import type { Theme } from '../theme'
import { handler as h, variantGetParameter } from '../utils'
import { h, variantGetParameter } from '../utils'

export const variantAria: VariantObject = {
name: 'aria',
match(matcher, { theme }: VariantContext<Theme>) {
const variant = variantGetParameter('aria-', matcher, [':', '-'])
match(matcher, ctx: VariantContext<Theme>) {
const variant = variantGetParameter('aria-', matcher, ctx.generator.config.separators)
if (variant) {
const [match, rest] = variant
const aria = h.bracket(match) ?? theme.aria?.[match] ?? ''
const aria = h.bracket(match) ?? ctx.theme.aria?.[match] ?? ''
if (aria) {
return {
matcher: rest,
Expand Down
106 changes: 53 additions & 53 deletions src/variants/breakpoints.ts
Original file line number Diff line number Diff line change
@@ -1,79 +1,79 @@
import type { Variant } from '@unocss/core'
import type { VariantObject } from '@unocss/core'
import { resolveBreakpoints } from '../utils'
import type { Theme } from '../theme'

const regexCache: Record<string, RegExp> = {}

function calcMaxWidthBySize(size: string) {
export function calcMaxWidthBySize(size: string) {
const value = size.match(/^-?[0-9]+\.?[0-9]*/)?.[0] || ''
const unit = size.slice(value.length)
const maxWidth = (Number.parseFloat(value) - 0.1)
return Number.isNaN(maxWidth) ? size : `${maxWidth}${unit}`
}

export const variantBreakpoints: Variant<Theme> = {
name: 'breakpoints',
match(matcher, context) {
const variantEntries: Array<[string, string, number]>
= Object.entries(resolveBreakpoints(context) ?? {}).map(([point, size], idx) => [point, size, idx])
for (const [point, size, idx] of variantEntries) {
if (!regexCache[point])
regexCache[point] = new RegExp(`^((?:([al]t-|[<~]))?${point}[:-])`)
export function variantBreakpoints(): VariantObject {
const regexCache: Record<string, RegExp> = {}
return {
name: 'breakpoints',
match(matcher, context) {
const variantEntries: Array<[string, string, number]>
= Object.entries(resolveBreakpoints(context) ?? {}).map(([point, size], idx) => [point, size, idx])
for (const [point, size, idx] of variantEntries) {
if (!regexCache[point])
regexCache[point] = new RegExp(`^((?:([al]t-|[<~]))?${point}(?:${context.generator.config.separators.join('|')}))`)

const match = matcher.match(regexCache[point])
if (!match)
continue
const match = matcher.match(regexCache[point])
if (!match)
continue

const [, pre] = match
const [, pre] = match

const m = matcher.slice(pre.length)
// container rule is responsive, but also is breakpoint aware
// it is handled on its own module (container.ts) and so we
// exclude it from here
if (m === 'container')
continue
const m = matcher.slice(pre.length)
// container rule is responsive, but also is breakpoint aware
// it is handled on its own module (container.ts) and so we
// exclude it from here
if (m === 'container')
continue

const isLtPrefix = pre.startsWith('lt-') || pre.startsWith('<')
const isAtPrefix = pre.startsWith('at-') || pre.startsWith('~')
const isLtPrefix = pre.startsWith('lt-') || pre.startsWith('<')
const isAtPrefix = pre.startsWith('at-') || pre.startsWith('~')

let order = 1000 // parseInt(size)
let order = 1000 // parseInt(size)

if (isLtPrefix) {
order -= (idx + 1)
return {
matcher: m,
handle: (input, next) => next({
...input,
parent: `${input.parent ? `${input.parent} $$ ` : ''}@media (max-width: ${calcMaxWidthBySize(size)})`,
parentOrder: order,
}),
if (isLtPrefix) {
order -= (idx + 1)
return {
matcher: m,
handle: (input, next) => next({
...input,
parent: `${input.parent ? `${input.parent} $$ ` : ''}@media (max-width: ${calcMaxWidthBySize(size)})`,
parentOrder: order,
}),
}
}
}

order += (idx + 1)
order += (idx + 1)

// support for windicss @<breakpoint> => last breakpoint will not have the upper bound
if (isAtPrefix && idx < variantEntries.length - 1) {
return {
matcher: m,
handle: (input, next) => next({
...input,
parent: `${input.parent ? `${input.parent} $$ ` : ''}@media (min-width: ${size}) and (max-width: ${calcMaxWidthBySize(variantEntries[idx + 1][1])})`,
parentOrder: order,
}),
}
}

// support for windicss @<breakpoint> => last breakpoint will not have the upper bound
if (isAtPrefix && idx < variantEntries.length - 1) {
return {
matcher: m,
handle: (input, next) => next({
...input,
parent: `${input.parent ? `${input.parent} $$ ` : ''}@media (min-width: ${size}) and (max-width: ${calcMaxWidthBySize(variantEntries[idx + 1][1])})`,
parent: `${input.parent ? `${input.parent} $$ ` : ''}@media (min-width: ${size})`,
parentOrder: order,
}),
}
}

return {
matcher: m,
handle: (input, next) => next({
...input,
parent: `${input.parent ? `${input.parent} $$ ` : ''}@media (min-width: ${size})`,
parentOrder: order,
}),
}
}
},
multiPass: true,
autocomplete: '(at-|lt-|)$breakpoints:',
},
multiPass: true,
autocomplete: '(at-|lt-|)$breakpoints:',
}
}
9 changes: 5 additions & 4 deletions src/variants/combinators.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import type { Variant, VariantObject } from '@unocss/core'
import { handler as h, variantGetBracket } from '../utils'
import { h, variantGetBracket } from '../utils'

function scopeMatcher(name: string, combinator: string): VariantObject {
return {
name: `combinator:${name}`,
match(matcher) {
match(matcher, ctx) {
if (!matcher.startsWith(name))
return

let body = variantGetBracket(`${name}-`, matcher, [':', '-'])
const separators = ctx.generator.config.separators
let body = variantGetBracket(`${name}-`, matcher, separators)
if (!body) {
for (const separator of [':', '-']) {
for (const separator of separators) {
if (matcher.startsWith(`${name}${separator}`)) {
body = ['', matcher.slice(name.length + separator.length)]
break
Expand Down
8 changes: 4 additions & 4 deletions src/variants/container.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type { VariantContext, VariantObject } from '@unocss/core'
import { warnOnce } from '@unocss/core'
import type { Theme } from '../theme'
import { handler as h, variantGetParameter } from '../utils'
import { h, variantGetParameter } from '../utils'

export const variantContainerQuery: VariantObject = {
name: '@',
match(matcher, { theme }: VariantContext<Theme>) {
match(matcher, ctx: VariantContext<Theme>) {
if (matcher.startsWith('@container'))
return

const variant = variantGetParameter('@', matcher, [':', '-'])
const variant = variantGetParameter('@', matcher, ctx.generator.config.separators)
if (variant) {
const [match, rest, label] = variant
const unbracket = h.bracket(match)
Expand All @@ -20,7 +20,7 @@ export const variantContainerQuery: VariantObject = {
container = `(min-width: ${minWidth})`
}
else {
container = theme.containers?.[match] ?? ''
container = ctx.theme.containers?.[match] ?? ''
}

if (container) {
Expand Down
9 changes: 4 additions & 5 deletions src/variants/data.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import type { VariantContext, VariantObject } from '@unocss/core'
import type { Theme } from '../theme'
import { handler as h, variantGetParameter } from '../utils'
import { h, variantGetParameter } from '../utils'

export const variantDataAttribute: VariantObject = {
name: 'data',
match(matcher, { theme }: VariantContext<Theme>) {
const variant = variantGetParameter('data-', matcher, [':', '-'])
match(matcher, ctx: VariantContext<Theme>) {
const variant = variantGetParameter('data-', matcher, ctx.generator.config.separators)
if (variant) {
const [match, rest] = variant
const dataAttribute = h.bracket(match) ?? theme.data?.[match] ?? ''

const dataAttribute = h.bracket(match) ?? ctx.theme.data?.[match] ?? ''
if (dataAttribute) {
return {
matcher: rest,
Expand Down
8 changes: 4 additions & 4 deletions src/variants/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ export function variants(options: PresetWeappOptions): Variant<Theme>[] {
variantSelector,
variantInternalLayer,
variantNegative,
variantImportant,
variantImportant(),
variantSupports,
variantPrint,
variantCustomMedia,
variantBreakpoints,
variantBreakpoints(),
...variantCombinators,
variantSpaceAndDivide,

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

variantPartClasses,
Expand Down
52 changes: 28 additions & 24 deletions src/variants/important.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
import type { Variant, VariantContext } from '@unocss/core'
import type { VariantObject } from '@unocss/core'
import { restoreSelector } from 'unplugin-transform-class/utils'
import type { Theme } from '../theme'

export const variantImportant: Variant = {
name: 'important',
match(matcher, { theme }: VariantContext<Theme>) {
let base: string | undefined
export function variantImportant(): VariantObject<Theme> {
let re: RegExp

matcher = restoreSelector(matcher, theme?.transformRules)
const match = matcher.match(/^(important[:-]|!)/)
return {
name: 'important',
match(matcher, ctx) {
if (!re)
re = new RegExp(`^(important(?:${ctx.generator.config.separators.join('|')})|!)`)

if (match)
base = matcher.slice(match[0].length)
let base: string | undefined
matcher = restoreSelector(matcher, ctx.theme?.transformRules)
const match = matcher.match(re)
if (match)
base = matcher.slice(match[0].length)
else if (matcher.endsWith('!'))
base = matcher.slice(0, -1)

else if (matcher.endsWith('!'))
base = matcher.slice(0, -1)

if (base) {
return {
matcher: base,
body: (body) => {
body.forEach((v) => {
if (v[1])
v[1] += ' !important'
})
return body
},
if (base) {
return {
matcher: base,
body: (body) => {
body.forEach((v) => {
if (v[1])
v[1] += ' !important'
})
return body
},
}
}
}
},
},
}
}
12 changes: 6 additions & 6 deletions src/variants/media.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import type { Variant, VariantContext, VariantObject } from '@unocss/core'
import type { VariantContext, VariantObject } from '@unocss/core'
import type { Theme } from '../theme'
import { handler as h, variantGetParameter, variantParentMatcher } from '../utils'
import { h, variantGetParameter, variantParentMatcher } from '../utils'

export const variantPrint: Variant = variantParentMatcher('print', '@media print')
export const variantPrint: VariantObject = variantParentMatcher('print', '@media print')

export const variantCustomMedia: VariantObject = {
name: 'media',
match(matcher, { theme }: VariantContext<Theme>) {
const variant = variantGetParameter('media-', matcher, [':', '-'])
match(matcher, ctx: VariantContext<Theme>) {
const variant = variantGetParameter('media-', matcher, ctx.generator.config.separators)
if (variant) {
const [match, rest] = variant

let media = h.bracket(match) ?? ''
if (media === '')
media = theme.media?.[match] ?? ''
media = ctx.theme.media?.[match] ?? ''

if (media) {
return {
Expand Down
Loading

0 comments on commit 58f8a46

Please sign in to comment.