🐛 tailwind template

This commit is contained in:
Timothy Yin 2024-11-18 15:47:26 +08:00
parent 7906e2f19c
commit 0cef7ba436
5 changed files with 100 additions and 1 deletions

View File

@ -25,4 +25,5 @@ export default createConfigForNuxt({
'@typescript-eslint/no-empty-object-type': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'regexp/no-super-linear-backtracking': 'off',
})

View File

@ -33,6 +33,7 @@
"@nuxtjs/tailwindcss": "^6.12.2",
"defu": "^6.1.4",
"pathe": "^1.1.2",
"scule": "^1.3.0",
"tailwind-merge": "^2.5.4",
"tailwindcss": "^3.4.15"
},

3
pnpm-lock.yaml generated
View File

@ -20,6 +20,9 @@ importers:
pathe:
specifier: ^1.1.2
version: 1.1.2
scule:
specifier: ^1.3.0
version: 1.3.0
tailwind-merge:
specifier: ^2.5.4
version: 2.5.4

View File

@ -1,5 +1,6 @@
import type { Config as TwConfig } from 'tailwindcss'
import defaultColors from 'tailwindcss/colors.js'
import { camelCase, upperFirst } from 'scule'
import { omit } from './objectUtils'
const colorsToRegex = (colors: string[]): string => colors.join('|')
@ -139,3 +140,76 @@ export const generateSafelist = (colors: string[], globalColors: string[]) => {
return [...safelist]
}
type SafelistFn = Exclude<
NonNullable<Extract<TwConfig['content'], { extract?: unknown }>['extract']>,
Record<string, unknown>
>
export const customSafelistExtractor = (
prefix: string,
content: string,
colors: string[],
safelistColors: string[],
): ReturnType<SafelistFn> => {
const classes: string[] = []
const regex
= /<([A-Za-z][A-Za-z0-9]*(?:-[A-Za-z][A-Za-z0-9]*)*)\s+(?![^>]*:color\b)[^>]*\bcolor=["']([^"']+)["'][^>]*>/g
const matches = content.matchAll(regex)
const components = Object.keys(safelistForComponent).map(
component =>
`${prefix}${component.charAt(0).toUpperCase() + component.slice(1)}`,
)
for (const match of matches) {
const [, component, color] = match
const camelComponent = upperFirst(camelCase(component))
if (!colors.includes(color) || safelistColors.includes(color)) {
continue
}
let name = camelComponent as string
if (!components.includes(name)) {
continue
}
name = name.replace(prefix, '').toLowerCase()
const matchClasses = safelistForComponent[name](color)?.flatMap((group) => {
return typeof group === 'string'
? ''
: ['', ...(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) => {
const classesExtracted = group.pattern.source
.replace(match, color)
.replace('^', '')
.replace('$', '')
if (variant) {
return `${variant}:${classesExtracted}`
}
return classesExtracted
})
})
.flat() || []
)
})
})
classes.push(...(matchClasses as string[]))
}
return classes
}

View File

@ -31,10 +31,13 @@ export const installTailwind = (
filename: 'ray-tailwind.config.cjs',
write: true,
getContents: ({ nuxt }) => `
const { generateSafelist } = require(${JSON.stringify(
const { defaultExtractor: createDefaultExtractor } = require('tailwindcss/lib/lib/defaultExtractor.js')
const { customSafelistExtractor, generateSafelist } = require(${JSON.stringify(
resolve(runtimePath, 'utils', 'colors'),
)})
const defaultExtractor = createDefaultExtractor({ tailwindConfig: { separator: ':' } })
module.exports = {
content: {
files: [
@ -46,6 +49,23 @@ export const installTailwind = (
)}
],
},
transform: {
vue: (content) => {
return content.replaceAll(/(?:\\r\\n|\\r|\\n)/g, ' ')
}
},
extract: {
vue: (content) => {
return [
...defaultExtractor(content),
...customSafelistExtractor(${JSON.stringify(
moduleOptions.prefix,
)}, content, ${JSON.stringify(
nuxt.options.appConfig.rayui.colors,
)}, ${JSON.stringify(moduleOptions.safelistColors)})
]
}
}
safelist: generateSafelist(${JSON.stringify(
moduleOptions.safeColors || [],
)}, ${JSON.stringify(nuxt.options.appConfig.rayui.colors)}),