From 6e7176363d5ebdccc7fe2cb33635ab07a08b44b7 Mon Sep 17 00:00:00 2001 From: MellowCo <799478052@qq.com> Date: Sat, 27 Jul 2024 08:22:51 +0800 Subject: [PATCH] fix: compatible bracket parse --- src/rules/transition.ts | 113 +++++++++++++----- src/theme/default.ts | 4 +- src/theme/misc.ts | 8 -- src/theme/transition.ts | 21 ++++ src/theme/types.ts | 1 + src/utils/handlers/handlers.ts | 1 + test/assets/output/preset-mini/targets.css | 7 +- .../preset-weapp/targets-custom-rules.css | 7 +- test/assets/output/preset-weapp/targets.css | 7 +- test/assets/preset-mini-targets.ts | 5 + 10 files changed, 132 insertions(+), 42 deletions(-) create mode 100644 src/theme/transition.ts diff --git a/src/rules/transition.ts b/src/rules/transition.ts index 7c1a57d..c349b89 100644 --- a/src/rules/transition.ts +++ b/src/rules/transition.ts @@ -1,45 +1,98 @@ import type { Rule } from '@unocss/core' import type { Theme } from '../theme' -import { globalKeywords, handler as h, makeGlobalStaticRules } from '../utils' - -const transitionPropertyGroup: Record = { - all: 'all', - colors: ['color', 'background-color', 'border-color', 'outline-color', 'text-decoration-color', 'fill', 'stroke'].join(','), - none: 'none', - opacity: 'opacity', - shadow: 'box-shadow', - transform: 'transform', -} +import { globalKeywords, h, makeGlobalStaticRules } from '../utils' + +function resolveTransitionProperty(prop: string, theme: Theme): string | undefined { + let p: string | undefined -function transitionProperty(prop: string): string | undefined { - const props = prop.split(',').flatMap(p => h.properties(p) ?? transitionPropertyGroup[p]) - if (props.length > 0 && props.every(Boolean)) - return props.join(',') + if (h.cssvar(prop) != null) { + p = h.cssvar(prop) + } + else { + if ((prop.startsWith('[') && prop.endsWith(']'))) { + prop = prop.slice(1, -1) + } + const props = prop.split(',').map(p => theme.transitionProperty?.[p] ?? h.properties(p)) + if (props.every(Boolean)) { + p = props.join(',') + } + } + + return p } export const transitions: Rule[] = [ // transition - [/^transition(?:-([a-z-]+(?:,[a-z-]+)*))?(?:-(\d+))?$/, ([, prop, d], { theme }) => { - const p = prop != null - ? transitionProperty(prop) - : [transitionPropertyGroup.colors, 'opacity', 'box-shadow', 'transform', 'filter', 'backdrop-filter'].join(',') - if (p) { - const duration = theme.duration?.[d || 'DEFAULT'] ?? h.time(d || '150') - return { - 'transition-property': p, - 'transition-timing-function': 'cubic-bezier(0.4, 0, 0.2, 1)', - 'transition-duration': duration, + [ + /^transition(?:-(\D+?))?(?:-(\d+))?$/, + ([, prop, d], { theme }) => { + if (!prop && !d) { + return { + 'transition-property': theme.transitionProperty?.DEFAULT, + 'transition-timing-function': theme.easing?.DEFAULT, + 'transition-duration': theme.duration?.DEFAULT ?? h.time('150'), + } } - } - }, { autocomplete: `transition-(${Object.keys(transitionPropertyGroup).join('|')})` }], + + else if (prop != null) { + const p = resolveTransitionProperty(prop, theme) + const duration = theme.duration?.[d || 'DEFAULT'] ?? h.time(d || '150') + + if (p) { + return { + 'transition-property': p, + 'transition-timing-function': theme.easing?.DEFAULT, + 'transition-duration': duration, + } + } + } + + else if (d != null) { + return { + 'transition-property': theme.transitionProperty?.DEFAULT, + 'transition-timing-function': theme.easing?.DEFAULT, + 'transition-duration': theme.duration?.[d] ?? h.time(d), + } + } + }, + { + autocomplete: 'transition-$transitionProperty-$duration', + }, + ], // timings - [/^(?:transition-)?duration-(.+)$/, ([, d], { theme }) => ({ 'transition-duration': theme.duration?.[d || 'DEFAULT'] ?? h.bracket.cssvar.time(d) }), { autocomplete: ['transition-duration-$duration', 'duration-$duration'] }], - [/^(?:transition-)?delay-(.+)$/, ([, d], { theme }) => ({ 'transition-delay': theme.duration?.[d || 'DEFAULT'] ?? h.bracket.cssvar.time(d) }), { autocomplete: ['transition-delay-$duration', 'delay-$duration'] }], - [/^(?:transition-)?ease(?:-(.+))?$/, ([, d], { theme }) => ({ 'transition-timing-function': theme.easing?.[d || 'DEFAULT'] ?? h.bracket.cssvar(d) }), { autocomplete: ['transition-ease-(linear|in|out|in-out|DEFAULT)', 'ease-(linear|in|out|in-out|DEFAULT)'] }], + [ + /^(?:transition-)?duration-(.+)$/, + ([, d], { theme }) => ({ 'transition-duration': theme.duration?.[d || 'DEFAULT'] ?? h.bracket.cssvar.time(d) }), + { autocomplete: ['transition-duration-$duration', 'duration-$duration'] }, + ], + + [ + /^(?:transition-)?delay-(.+)$/, + ([, d], { theme }) => ({ 'transition-delay': theme.duration?.[d || 'DEFAULT'] ?? h.bracket.cssvar.time(d) }), + { autocomplete: ['transition-delay-$duration', 'delay-$duration'] }, + ], + + [ + /^(?:transition-)?ease(?:-(.+))?$/, + ([, d], { theme }) => ({ 'transition-timing-function': theme.easing?.[d || 'DEFAULT'] ?? h.bracket.cssvar(d) }), + { autocomplete: ['transition-ease-(linear|in|out|in-out|DEFAULT)', 'ease-(linear|in|out|in-out|DEFAULT)'] }, + ], // props - [/^(?:transition-)?property-(.+)$/, ([, v]) => ({ 'transition-property': h.bracket.global(v) || transitionProperty(v) }), { autocomplete: [`transition-property-(${[...globalKeywords, ...Object.keys(transitionPropertyGroup)].join('|')})`] }], + [ + /^(?:transition-)?property-(.+)$/, + ([, v], { theme }) => { + const p = h.global(v) || resolveTransitionProperty(v, theme) + if (p) + return { 'transition-property': p } + }, + { autocomplete: [ + `transition-property-(${[...globalKeywords].join('|')})`, + 'transition-property-$transitionProperty', + 'property-$transitionProperty', + ] }, + ], // none ['transition-none', { transition: 'none' }], diff --git a/src/theme/default.ts b/src/theme/default.ts index c7dc8db..e448c2c 100644 --- a/src/theme/default.ts +++ b/src/theme/default.ts @@ -1,12 +1,13 @@ import { colors } from './colors' import { fontFamily, fontSize, fontWeight, letterSpacing, lineHeight, textIndent, textShadow, textStrokeWidth, wordSpacing } from './font' -import { borderRadius, boxShadow, breakpoints, duration, easing, lineWidth, media, ringWidth, spacing, verticalBreakpoints, zIndex } from './misc' +import { borderRadius, boxShadow, breakpoints, duration, lineWidth, media, ringWidth, spacing, verticalBreakpoints, zIndex } from './misc' import { blur, dropShadow } from './filters' import { containers, height, maxHeight, maxWidth, width } from './size' import type { Theme } from './types' import { preflightBase } from './preflight' import { animation } from './animation' import { aria } from './aria' +import { easing, transitionProperty } from './transition' export const theme: Theme = { width, @@ -38,6 +39,7 @@ export const theme: Theme = { blur, dropShadow, easing, + transitionProperty, lineWidth, spacing, duration, diff --git a/src/theme/misc.ts b/src/theme/misc.ts index 60bb999..f07cbc1 100644 --- a/src/theme/misc.ts +++ b/src/theme/misc.ts @@ -68,14 +68,6 @@ export const boxShadow = { 'inner': 'inset 0 2px 4px 0 rgb(0 0 0 / 0.05)', } -export const easing = { - 'DEFAULT': 'cubic-bezier(0.4, 0, 0.2, 1)', - 'linear': 'linear', - 'in': 'cubic-bezier(0.4, 0, 1, 1)', - 'out': 'cubic-bezier(0, 0, 0.2, 1)', - 'in-out': 'cubic-bezier(0.4, 0, 0.2, 1)', -} - export const ringWidth = { DEFAULT: '3px', none: '0', diff --git a/src/theme/transition.ts b/src/theme/transition.ts new file mode 100644 index 0000000..f3a65e9 --- /dev/null +++ b/src/theme/transition.ts @@ -0,0 +1,21 @@ +import type { Theme } from './types' + +export const easing = { + 'DEFAULT': 'cubic-bezier(0.4, 0, 0.2, 1)', + 'linear': 'linear', + 'in': 'cubic-bezier(0.4, 0, 1, 1)', + 'out': 'cubic-bezier(0, 0, 0.2, 1)', + 'in-out': 'cubic-bezier(0.4, 0, 0.2, 1)', +} satisfies Theme['easing'] + +export const transitionProperty = { + none: 'none', + all: 'all', + colors: ['color', 'background-color', 'border-color', 'outline-color', 'text-decoration-color', 'fill', 'stroke'].join(','), + opacity: 'opacity', + shadow: 'box-shadow', + transform: 'transform', + get DEFAULT() { + return [this.colors, 'opacity', 'box-shadow', 'transform', 'filter', 'backdrop-filter'].join(',') + }, +} satisfies Theme['transitionProperty'] diff --git a/src/theme/types.ts b/src/theme/types.ts index e6c576d..0968aff 100644 --- a/src/theme/types.ts +++ b/src/theme/types.ts @@ -56,6 +56,7 @@ export interface Theme { dropShadow?: Record // transitions easing?: Record + transitionProperty?: Record // media queries media?: Record // supports queries diff --git a/src/utils/handlers/handlers.ts b/src/utils/handlers/handlers.ts index 6deae19..fc901b2 100644 --- a/src/utils/handlers/handlers.ts +++ b/src/utils/handlers/handlers.ts @@ -22,6 +22,7 @@ const cssProps = [ 'text-shadow', 'transform', 'box-shadow', + 'border', // positions 'backround-position', diff --git a/test/assets/output/preset-mini/targets.css b/test/assets/output/preset-mini/targets.css index ee90486..d1e5a37 100644 --- a/test/assets/output/preset-mini/targets.css +++ b/test/assets/output/preset-mini/targets.css @@ -1097,6 +1097,10 @@ unocss .scope-\[unocss\]\:block{display:block;} .box-content{box-sizing:content-box;} .box-inherit{box-sizing:inherit;} .transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} +.transition-\[width\,height\,colors\]{transition-property:width,height,color,background-color,border-color,outline-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} +.transition-\[width\,height\,colors\]-200{transition-property:width,height,color,background-color,border-color,outline-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} +.transition-\[width\,height\]{transition-property:width,height;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} +.transition-\$variant{transition-property:var(--variant);transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} .transition-200{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} .transition-background-color\,color-200{transition-property:background-color,color;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} .transition-color\,background-color-200{transition-property:color,background-color;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} @@ -1113,11 +1117,12 @@ unocss .scope-\[unocss\]\:block{display:block;} .ease-linear{transition-timing-function:linear;} .ease-out{transition-timing-function:cubic-bezier(0, 0, 0.2, 1);} .transition-ease-in{transition-timing-function:cubic-bezier(0.4, 0, 1, 1);} +.property-\[padding\,margin\], +.property-padding\,margin{transition-property:padding,margin;} .property-all, .transition-property-all{transition-property:all;} .property-margin\,padding{transition-property:margin,padding;} .property-none{transition-property:none;} -.property-padding\,margin{transition-property:padding,margin;} .property-unset{transition-property:unset;} .transition-property-\[border\]{transition-property:border;} .transition-property-width{transition-property:width;} diff --git a/test/assets/output/preset-weapp/targets-custom-rules.css b/test/assets/output/preset-weapp/targets-custom-rules.css index 8b45485..8efc421 100644 --- a/test/assets/output/preset-weapp/targets-custom-rules.css +++ b/test/assets/output/preset-weapp/targets-custom-rules.css @@ -1098,6 +1098,10 @@ unocss .scope-_lfl11_unocss_lfr11__cl11_block{display:block;} .box-content{box-sizing:content-box;} .box-inherit{box-sizing:inherit;} .transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} +.transition-_do11_variant{transition-property:var(--variant);transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} +.transition-_lfl11_width_lco11_height_lco11_colors_lfr11_{transition-property:width,height,color,background-color,border-color,outline-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} +.transition-_lfl11_width_lco11_height_lco11_colors_lfr11_-200{transition-property:width,height,color,background-color,border-color,outline-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} +.transition-_lfl11_width_lco11_height_lfr11_{transition-property:width,height;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} .transition-200{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} .transition-background-color_lco11_color-200{transition-property:background-color,color;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} .transition-color_lco11_background-color-200{transition-property:color,background-color;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} @@ -1114,11 +1118,12 @@ unocss .scope-_lfl11_unocss_lfr11__cl11_block{display:block;} .ease-linear{transition-timing-function:linear;} .ease-out{transition-timing-function:cubic-bezier(0, 0, 0.2, 1);} .transition-ease-in{transition-timing-function:cubic-bezier(0.4, 0, 1, 1);} +.property-_lfl11_padding_lco11_margin_lfr11_, +.property-padding_lco11_margin{transition-property:padding,margin;} .property-all, .transition-property-all{transition-property:all;} .property-margin_lco11_padding{transition-property:margin,padding;} .property-none{transition-property:none;} -.property-padding_lco11_margin{transition-property:padding,margin;} .property-unset{transition-property:unset;} .transition-property-_lfl11_border_lfr11_{transition-property:border;} .transition-property-width{transition-property:width;} diff --git a/test/assets/output/preset-weapp/targets.css b/test/assets/output/preset-weapp/targets.css index 326c9a3..006dc76 100644 --- a/test/assets/output/preset-weapp/targets.css +++ b/test/assets/output/preset-weapp/targets.css @@ -1101,6 +1101,10 @@ unocss .scope-_lfl_unocss_lfr__cl_block{display:block;} .box-content{box-sizing:content-box;} .box-inherit{box-sizing:inherit;} .transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} +.transition-_do_variant{transition-property:var(--variant);transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} +.transition-_lfl_width_lco_height_lco_colors_lfr_{transition-property:width,height,color,background-color,border-color,outline-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} +.transition-_lfl_width_lco_height_lco_colors_lfr_-200{transition-property:width,height,color,background-color,border-color,outline-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} +.transition-_lfl_width_lco_height_lfr_{transition-property:width,height;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;} .transition-200{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} .transition-background-color_lco_color-200{transition-property:background-color,color;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} .transition-color_lco_background-color-200{transition-property:color,background-color;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:200ms;} @@ -1117,11 +1121,12 @@ unocss .scope-_lfl_unocss_lfr__cl_block{display:block;} .ease-linear{transition-timing-function:linear;} .ease-out{transition-timing-function:cubic-bezier(0, 0, 0.2, 1);} .transition-ease-in{transition-timing-function:cubic-bezier(0.4, 0, 1, 1);} +.property-_lfl_padding_lco_margin_lfr_, +.property-padding_lco_margin{transition-property:padding,margin;} .property-all, .transition-property-all{transition-property:all;} .property-margin_lco_padding{transition-property:margin,padding;} .property-none{transition-property:none;} -.property-padding_lco_margin{transition-property:padding,margin;} .property-unset{transition-property:unset;} .transition-property-_lfl_border_lfr_{transition-property:border;} .transition-property-width{transition-property:width;} diff --git a/test/assets/preset-mini-targets.ts b/test/assets/preset-mini-targets.ts index 286e927..ffef2a9 100644 --- a/test/assets/preset-mini-targets.ts +++ b/test/assets/preset-mini-targets.ts @@ -1005,6 +1005,10 @@ export const presetMiniTargets: string[] = [ 'transition-colors,opacity-200', 'transition-color,background-color-200', 'transition-background-color,color-200', + 'transition-$variant', + 'transition-[width,height]', + 'transition-[width,height,colors]', + 'transition-[width,height,colors]-200', 'transition', 'transition-revert-layer', 'property-none', @@ -1012,6 +1016,7 @@ export const presetMiniTargets: string[] = [ 'property-unset', 'property-margin,padding', 'property-padding,margin', + 'property-[padding,margin]', 'duration-111', // transition - timings