|
| 1 | +import type { Theme } from '../../theme' |
1 | 2 | import { escapeSelector } from '@unocss/core' |
2 | 3 | import { globalKeywords } from '../mappings' |
| 4 | +import { themeTracking } from '../track' |
| 5 | +import { getThemeByKey } from '../utilities' |
3 | 6 | import { bracketTypeRe, numberRE, numberWithUnitRE, unitOnlyMap, unitOnlyRE } from './regex' |
4 | 7 |
|
5 | 8 | // Not all, but covers most high frequency attributes |
@@ -147,7 +150,23 @@ export function fraction(str: string) { |
147 | 150 | } |
148 | 151 | } |
149 | 152 |
|
150 | | -function bracketWithType(str: string, requiredType?: string) { |
| 153 | +function processThemeVariable(name: string, key: keyof Theme, paths: string[], theme: Theme) { |
| 154 | + const valOrObj = getThemeByKey(theme, key, paths) |
| 155 | + const hasDefault = typeof valOrObj === 'object' && 'DEFAULT' in valOrObj |
| 156 | + |
| 157 | + if (hasDefault) |
| 158 | + paths.push('DEFAULT') |
| 159 | + |
| 160 | + const val = hasDefault ? valOrObj.DEFAULT : valOrObj |
| 161 | + const varKey = hasDefault && key !== 'spacing' ? `${name}.DEFAULT` : name |
| 162 | + |
| 163 | + if (val != null) |
| 164 | + themeTracking(key, paths.length ? paths : undefined) |
| 165 | + |
| 166 | + return { val, varKey } |
| 167 | +} |
| 168 | + |
| 169 | +function bracketWithType(str: string, requiredType?: string, theme?: Theme) { |
151 | 170 | if (str && str.startsWith('[') && str.endsWith(']')) { |
152 | 171 | let base: string | undefined |
153 | 172 | let hintedType: string | undefined |
@@ -175,8 +194,33 @@ function bracketWithType(str: string, requiredType?: string) { |
175 | 194 | return |
176 | 195 |
|
177 | 196 | if (base.startsWith('--')) { |
178 | | - const [name, defaultValue] = base.slice(2).split(',') |
179 | | - base = `var(--${escapeSelector(name)}${defaultValue ? `, ${defaultValue}` : ''})` |
| 197 | + const calcMatch = base.match(/^--([\w.-]+)\(([^)]+)\)$/) |
| 198 | + if (calcMatch != null && theme) { |
| 199 | + // Handle theme function with calculation: --theme.key(factor) |
| 200 | + const [, name, factor] = calcMatch |
| 201 | + const [key, ...paths] = name.split('.') as [keyof Theme, ...string[]] |
| 202 | + const { val, varKey } = processThemeVariable(name, key, paths, theme) |
| 203 | + |
| 204 | + if (val != null) |
| 205 | + base = `calc(var(--${escapeSelector(varKey.replaceAll('.', '-'))}) * ${factor})` |
| 206 | + } |
| 207 | + else { |
| 208 | + // Handle regular CSS variable: --name or --theme.key with optional default |
| 209 | + const [name, defaultValue] = base.slice(2).split(',') |
| 210 | + const suffix = defaultValue ? `, ${defaultValue}` : '' |
| 211 | + const escapedName = escapeSelector(name) |
| 212 | + |
| 213 | + if (theme) { |
| 214 | + const [key, ...paths] = name.split('.') as [keyof Theme, ...string[]] |
| 215 | + const { val, varKey } = processThemeVariable(name, key, paths, theme) |
| 216 | + base = val != null |
| 217 | + ? `var(--${escapeSelector(varKey.replaceAll('.', '-'))}${suffix})` |
| 218 | + : `var(--${escapedName}${suffix})` |
| 219 | + } |
| 220 | + else { |
| 221 | + base = `var(--${escapedName}${suffix})` |
| 222 | + } |
| 223 | + } |
180 | 224 | } |
181 | 225 |
|
182 | 226 | let curly = 0 |
@@ -222,28 +266,28 @@ function bracketWithType(str: string, requiredType?: string) { |
222 | 266 | } |
223 | 267 | } |
224 | 268 |
|
225 | | -export function bracket(str: string) { |
226 | | - return bracketWithType(str) |
| 269 | +export function bracket(str: string, theme?: Theme) { |
| 270 | + return bracketWithType(str, undefined, theme) |
227 | 271 | } |
228 | 272 |
|
229 | | -export function bracketOfColor(str: string) { |
230 | | - return bracketWithType(str, 'color') |
| 273 | +export function bracketOfColor(str: string, theme?: Theme) { |
| 274 | + return bracketWithType(str, 'color', theme) |
231 | 275 | } |
232 | 276 |
|
233 | | -export function bracketOfLength(str: string) { |
234 | | - return bracketWithType(str, 'length') || bracketWithType(str, 'size') |
| 277 | +export function bracketOfLength(str: string, theme?: Theme) { |
| 278 | + return bracketWithType(str, 'length', theme) || bracketWithType(str, 'size', theme) |
235 | 279 | } |
236 | 280 |
|
237 | | -export function bracketOfPosition(str: string) { |
238 | | - return bracketWithType(str, 'position') |
| 281 | +export function bracketOfPosition(str: string, theme?: Theme) { |
| 282 | + return bracketWithType(str, 'position', theme) |
239 | 283 | } |
240 | 284 |
|
241 | | -export function bracketOfFamily(str: string) { |
242 | | - return bracketWithType(str, 'family') |
| 285 | +export function bracketOfFamily(str: string, theme?: Theme) { |
| 286 | + return bracketWithType(str, 'family', theme) |
243 | 287 | } |
244 | 288 |
|
245 | | -export function bracketOfNumber(str: string) { |
246 | | - return bracketWithType(str, 'number') |
| 289 | +export function bracketOfNumber(str: string, theme?: Theme) { |
| 290 | + return bracketWithType(str, 'number', theme) |
247 | 291 | } |
248 | 292 |
|
249 | 293 | export function cssvar(str: string) { |
|
0 commit comments