主要利用unocss的preset,制定自定义rule,配合正则表达式实现简单类名
import type { Preset } from 'unocss
const directionAbbr = {
col: 'column',
colr: 'column-reverse',
row: 'row',
rowr: 'row-reverse',
}
//主轴方向
const justifyAbbr = {
center: 'center',
start: 'flex-start',
end: 'flex-end',
between: 'space-between',
around: 'space-around',
evenly: 'space-evenly',
}
//交叉轴方向
const alignAbbr = {
center: 'center',
start: 'flex-start',
end: 'flex-end',
baseline: 'baseline'
}
export function presetFlex( config?: { prefix?:string } ):Preset {
const _config = { prefix: config?.prefix || 'sm' }
const direction = Reflect.ownKeys(directionAbbr).join('|')
const justify = Reflect.ownKeys(justifyAbbr).join('|')
const align = Reflect.ownKeys(alignAbbr).join('|')
const reg1 = new RegExp(
`^${_config.prefix}-flex-(${direction})$`
)
const reg2 = new RegExp(
`^${_config.prefix}-flex-(${direction})-(${justify})-(${align})$`
)
return {
name: 'unocss-preset-flex',
rules: [
[
`${_config.prefix}-flex`, {
display: 'flex',
}
],
[
reg1,
(_,d)=>{
return {
display: 'flex',
'flex-direction': directionAbbr[d]
}
}
],
[
reg2,
(_,d,j,a) => {
return {
display: 'flex',
'flex-direction': directionAbbr[d],
'justify-content': justifyAbbr[j],
'align-items': alignAbbr[a]
}
}
]
]
}
}
import type { Preset } from 'unocss'
interface Theme {
xs: string,
s: string,
m: string,
l: string,
xl: string,
[x:string]: any
}
export function presetFont (config?: {
varPrefix?: string,
theme?: Partial<Theme>,
}):Preset {
const _config = {
prefix: config?.varPrefix || 'f',
theme: {},
...config
}
const theme = {
xs: '0.8rem',
s: '0.9rem',
m: '1rem',
l: '1.1rem',
xl: '1.2rem'
}
const resolveVar = (name:string) => {
const prefix = _config.prefix
return `--${prefix? `${prefix}-`: ''}${name}`
}
return {
name: 'unocss-preset-font',
theme,
preflights: [
{
getCSS() {
let ruleStr = ''
for(const key in theme){
if(Object.prototype.hasOwnproperty.call(theme,key)){
ruleStr += _config.prefix+ ':' + theme[key] + ';'
}
}
return `:root{
${ruleStr}
}`
}
}
],
rules: [
[
/^f-(\d?([A-Za-z])+)$/,
([,w]) => {
return {
'font-size': `var(${resolveVar(w)})`
}
}
],
[
/^f-(\d?)$/,
([,d]) => {
return {
'font-size': `${d}rem`
}
}
]
]
}
}
const acronym = {
ml: 'margin-left',
mr: 'margin-right',
mt: 'margin-top',
mb: 'margin-bottom',
ma: 'margin',
mtb: [ 'margin-top', 'margin-bottom' ],
mlr: [ 'margin-left', 'margin-right'],
pl: 'padding-left',
pr: 'padding-right',
pt: 'padding-top',
pb: 'padding-bottom',
pa: 'padding',
ptb: [ 'padding-top', 'padding-bottom' ],
plr: [ 'padding-left', 'padding-right'],
} as const
export function presetGap(config?: {
varPrefix?: string,
theme?: Partial<Theme>,
}):Preset {
const _config = {
prefix: config?.varPrefix || 'f',
theme: {},
...config
}
const theme = {
xs: '0.8rem',
s: '0.9rem',
m: '1rem',
l: '1.1rem',
xl: '1.2rem'
}
const resolveVar = (name:string) => {
const prefix = _config.prefix
return `--${prefix? `${prefix}-`: ''}${name}`
}
return {
name: 'unocss-preset-gap',
theme,
preflights: [
{
getCSS () {
let ruleStr = ''
for (const key in theme) {
if (Object.prototype.hasOwnProperty.call(theme, key)) {
ruleStr += resolveVar(key) + ':' + theme[key] + ';'
}
}
return `:root{
${ruleStr}
}`
},
},
],
variants: [
(matcher) => {
if(!(matcher.startWith('sub-')||matcher.startWith('sub:') )){
return matcher
}
return {
matcher: matcher.slice(4),
selector: s => `${s} > * + * `
}
}
],
rules: [
[
/^(mt|mb|mr|ml|ma|pt|pb|pr|pl|pa|mtb|mlr|ptb|plr)-(\d?([A-Za-z]|-)+)$/,
([,a, w]) => {
const props = acronym[a]
const rule = `${resolveVar(w)}`,
if(Array.isArray(props)){
return props.reduce((p,c)=>(p[c]=rule,p),{})
}
return {
[props]: rule
}
}
]
]
}
}