mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-19 06:21:46 +01:00
152 lines
4.5 KiB
TypeScript
152 lines
4.5 KiB
TypeScript
const colorsToExclude = [
|
|
'inherit',
|
|
'transparent',
|
|
'current',
|
|
'white',
|
|
'black',
|
|
'slate',
|
|
'gray',
|
|
'zinc',
|
|
'neutral',
|
|
'stone',
|
|
'cool'
|
|
]
|
|
|
|
const omit = (obj: object, keys: string[]) => {
|
|
return Object.fromEntries(
|
|
Object.entries(obj).filter(([key]) => !keys.includes(key))
|
|
)
|
|
}
|
|
|
|
const kebabCase = (str: string) => {
|
|
return str
|
|
?.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
|
|
?.map(x => x.toLowerCase())
|
|
?.join('-')
|
|
}
|
|
|
|
const safelistByComponent = {
|
|
avatar: (colorsAsRegex) => [{
|
|
pattern: new RegExp(`bg-(${colorsAsRegex}|gray)-500`)
|
|
}, {
|
|
pattern: new RegExp(`bg-(${colorsAsRegex}|gray)-400`),
|
|
variants: ['dark']
|
|
}],
|
|
badge: (colorsAsRegex) => [{
|
|
pattern: new RegExp(`bg-(${colorsAsRegex})-50`)
|
|
}, {
|
|
pattern: new RegExp(`bg-(${colorsAsRegex})-400`),
|
|
variants: ['dark']
|
|
}, {
|
|
pattern: new RegExp(`text-(${colorsAsRegex})-500`)
|
|
}, {
|
|
pattern: new RegExp(`text-(${colorsAsRegex})-400`),
|
|
variants: ['dark']
|
|
}, {
|
|
pattern: new RegExp(`ring-(${colorsAsRegex})-500`)
|
|
}, {
|
|
pattern: new RegExp(`ring-(${colorsAsRegex})-400`),
|
|
variants: ['dark']
|
|
}],
|
|
button: (colorsAsRegex) => [{
|
|
pattern: new RegExp(`bg-(${colorsAsRegex})-50`),
|
|
variants: ['hover']
|
|
}, {
|
|
pattern: new RegExp(`bg-(${colorsAsRegex})-100`),
|
|
variants: ['hover']
|
|
}, {
|
|
pattern: new RegExp(`bg-(${colorsAsRegex})-400`),
|
|
variants: ['dark', 'dark:disabled']
|
|
}, {
|
|
pattern: new RegExp(`bg-(${colorsAsRegex})-500`),
|
|
variants: ['disabled', 'dark:hover']
|
|
}, {
|
|
pattern: new RegExp(`bg-(${colorsAsRegex})-600`),
|
|
variants: ['hover']
|
|
}, {
|
|
pattern: new RegExp(`bg-(${colorsAsRegex})-900`),
|
|
variants: ['dark:hover']
|
|
}, {
|
|
pattern: new RegExp(`bg-(${colorsAsRegex})-950`),
|
|
variants: ['dark', 'dark:hover']
|
|
}, {
|
|
pattern: new RegExp(`text-(${colorsAsRegex})-400`),
|
|
variants: ['dark']
|
|
}, {
|
|
pattern: new RegExp(`text-(${colorsAsRegex})-500`),
|
|
variants: ['dark:hover']
|
|
}, {
|
|
pattern: new RegExp(`text-(${colorsAsRegex})-600`),
|
|
variants: ['hover']
|
|
}, {
|
|
pattern: new RegExp(`outline-(${colorsAsRegex})-400`),
|
|
variants: ['dark:focus-visible']
|
|
}, {
|
|
pattern: new RegExp(`outline-(${colorsAsRegex})-500`),
|
|
variants: ['focus-visible']
|
|
}, {
|
|
pattern: new RegExp(`ring-(${colorsAsRegex})-400`),
|
|
variants: ['dark:focus-visible']
|
|
}, {
|
|
pattern: new RegExp(`ring-(${colorsAsRegex})-500`),
|
|
variants: ['focus-visible']
|
|
}],
|
|
input: (colorsAsRegex) => [{
|
|
pattern: new RegExp(`ring-(${colorsAsRegex})-400`),
|
|
variants: ['dark', 'dark:focus']
|
|
}, {
|
|
pattern: new RegExp(`ring-(${colorsAsRegex})-500`),
|
|
variants: ['focus']
|
|
}],
|
|
notification: (colorsAsRegex) => [{
|
|
pattern: new RegExp(`bg-(${colorsAsRegex}|gray)-500`)
|
|
}, {
|
|
pattern: new RegExp(`bg-(${colorsAsRegex}|gray)-400`),
|
|
variants: ['dark']
|
|
}, {
|
|
pattern: new RegExp(`text-(${colorsAsRegex}|gray)-500`)
|
|
}, {
|
|
pattern: new RegExp(`text-(${colorsAsRegex}|gray)-400`),
|
|
variants: ['dark']
|
|
}]
|
|
}
|
|
|
|
const colorsAsRegex = (colors: string[]): string => colors.join('|')
|
|
|
|
export const excludeColors = (colors: object) => Object.keys(omit(colors, colorsToExclude)).map(color => kebabCase(color)) as string[]
|
|
|
|
export const generateSafelist = (colors: string[]) => ['avatar', 'badge', 'button', 'input', 'notification'].flatMap(component => safelistByComponent[component](colorsAsRegex(colors)))
|
|
|
|
export const customSafelistExtractor = (prefix, content: string) => {
|
|
const classes = []
|
|
const regex = /<(\w+)\s+[^>:]*color=["']([^"']+)["'][^>]*>/gs
|
|
const matches = [...content.matchAll(regex)]
|
|
|
|
for (const match of matches) {
|
|
const [, component, color] = match
|
|
|
|
if (colorsToExclude.includes(color)) {
|
|
continue
|
|
}
|
|
|
|
if (Object.keys(safelistByComponent).map(component => `${prefix}${component.charAt(0).toUpperCase() + component.slice(1)}`).includes(component)) {
|
|
const name = component.replace(prefix, '').toLowerCase()
|
|
|
|
const matchClasses = safelistByComponent[name](color).flatMap(group => {
|
|
return ['', ...(group.variants || [])].flatMap(variant => {
|
|
const matches = group.pattern.source.match(/\(([^)]+)\)/g)
|
|
|
|
return matches.map(match => {
|
|
const colorOptions = match.substring(1, match.length - 1).split('|')
|
|
return colorOptions.map(color => `${variant ? variant + ':' : ''}` + group.pattern.source.replace(match, color))
|
|
}).flat()
|
|
})
|
|
})
|
|
|
|
classes.push(...matchClasses)
|
|
}
|
|
}
|
|
|
|
return classes
|
|
}
|