From 8ac9ca49789a9a7281f7a40926e7e9a8068cc395 Mon Sep 17 00:00:00 2001 From: Yu Zhuohao <124545526+yuzh2001@users.noreply.github.com> Date: Sat, 3 Aug 2024 01:02:39 +0800 Subject: [PATCH] fix(module): reduce css bundle size by fixing safelist regex (#2005) Co-authored-by: Benjamin Canac --- src/runtime/utils/colors.ts | 142 +++++++++++++++++++----------------- test/colors.spec.ts | 6 +- 2 files changed, 78 insertions(+), 70 deletions(-) diff --git a/src/runtime/utils/colors.ts b/src/runtime/utils/colors.ts index b6519d053f..f8a8c19a78 100644 --- a/src/runtime/utils/colors.ts +++ b/src/runtime/utils/colors.ts @@ -19,193 +19,193 @@ const colorsToExclude = [ const safelistByComponent: Record TWConfig['safelist']> = { alert: (colorsAsRegex) => [{ - pattern: new RegExp(`bg-(${colorsAsRegex})-50`) + pattern: RegExp(`^bg-(${colorsAsRegex})-50$`) }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-400`), + pattern: RegExp(`^bg-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-500`) + pattern: RegExp(`^bg-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`text-(${colorsAsRegex})-400`), + pattern: RegExp(`^text-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-500`) + pattern: RegExp(`^text-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-400`), + pattern: RegExp(`^ring-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-500`) + pattern: RegExp(`^ring-(${colorsAsRegex})-500$`) }], avatar: (colorsAsRegex) => [{ - pattern: new RegExp(`bg-(${colorsAsRegex})-400`), + pattern: RegExp(`^bg-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-500`) + pattern: RegExp(`^bg-(${colorsAsRegex})-500$`) }], badge: (colorsAsRegex) => [{ - pattern: new RegExp(`bg-(${colorsAsRegex})-50`) + pattern: RegExp(`^bg-(${colorsAsRegex})-50$`) }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-400`), + pattern: RegExp(`^bg-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-500`) + pattern: RegExp(`^bg-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`text-(${colorsAsRegex})-400`), + pattern: RegExp(`^text-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-500`) + pattern: RegExp(`^text-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-400`), + pattern: RegExp(`^ring-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-500`) + pattern: RegExp(`^ring-(${colorsAsRegex})-500$`) }], button: (colorsAsRegex) => [{ - pattern: new RegExp(`bg-(${colorsAsRegex})-50`), + pattern: RegExp(`^bg-(${colorsAsRegex})-50$`), variants: ['hover', 'disabled'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-100`), + pattern: RegExp(`^bg-(${colorsAsRegex})-100$`), variants: ['hover'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-400`), + pattern: RegExp(`^bg-(${colorsAsRegex})-400$`), variants: ['dark', 'dark:disabled'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-500`), + pattern: RegExp(`^bg-(${colorsAsRegex})-500$`), variants: ['disabled', 'dark:hover'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-600`), + pattern: RegExp(`^bg-(${colorsAsRegex})-600$`), variants: ['hover'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-900`), + pattern: RegExp(`^bg-(${colorsAsRegex})-900$`), variants: ['dark:hover'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-950`), + pattern: RegExp(`^bg-(${colorsAsRegex})-950$`), variants: ['dark', 'dark:hover', 'dark:disabled'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-400`), + pattern: RegExp(`^text-(${colorsAsRegex})-400$`), variants: ['dark', 'dark:disabled'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-500`), + pattern: RegExp(`^text-(${colorsAsRegex})-500$`), variants: ['dark:hover', 'disabled'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-600`), + pattern: RegExp(`^text-(${colorsAsRegex})-600$`), variants: ['hover'] }, { - pattern: new RegExp(`outline-(${colorsAsRegex})-400`), + pattern: RegExp(`^outline-(${colorsAsRegex})-400$`), variants: ['dark:focus-visible'] }, { - pattern: new RegExp(`outline-(${colorsAsRegex})-500`), + pattern: RegExp(`^outline-(${colorsAsRegex})-500$`), variants: ['focus-visible'] }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-400`), + pattern: RegExp(`^ring-(${colorsAsRegex})-400$`), variants: ['dark:focus-visible'] }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-500`), + pattern: RegExp(`^ring-(${colorsAsRegex})-500$`), variants: ['focus-visible'] }], input: (colorsAsRegex) => [{ - pattern: new RegExp(`text-(${colorsAsRegex})-400`), + pattern: RegExp(`^text-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-500`) + pattern: RegExp(`^text-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-400`), + pattern: RegExp(`^ring-(${colorsAsRegex})-400$`), variants: ['dark', 'dark:focus'] }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-500`), + pattern: RegExp(`^ring-(${colorsAsRegex})-500$`), variants: ['focus'] }], radio: (colorsAsRegex) => [{ - pattern: new RegExp(`text-(${colorsAsRegex})-400`), + pattern: RegExp(`^text-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-500`) + pattern: RegExp(`^text-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-400`), + pattern: RegExp(`^ring-(${colorsAsRegex})-400$`), variants: ['dark:focus-visible'] }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-500`), + pattern: RegExp(`^ring-(${colorsAsRegex})-500$`), variants: ['focus-visible'] }], checkbox: (colorsAsRegex) => [{ - pattern: new RegExp(`text-(${colorsAsRegex})-400`), + pattern: RegExp(`^text-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-500`) + pattern: RegExp(`^text-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-400`), + pattern: RegExp(`^ring-(${colorsAsRegex})-400$`), variants: ['dark:focus-visible'] }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-500`), + pattern: RegExp(`^ring-(${colorsAsRegex})-500$`), variants: ['focus-visible'] }], toggle: (colorsAsRegex) => [{ - pattern: new RegExp(`bg-(${colorsAsRegex})-400`), + pattern: RegExp(`^bg-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-500`) + pattern: RegExp(`^bg-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`text-(${colorsAsRegex})-400`), + pattern: RegExp(`^text-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-500`) + pattern: RegExp(`^text-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-400`), + pattern: RegExp(`^ring-(${colorsAsRegex})-400$`), variants: ['dark:focus-visible'] }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-500`), + pattern: RegExp(`^ring-(${colorsAsRegex})-500$`), variants: ['focus-visible'] }], range: (colorsAsRegex) => [{ - pattern: new RegExp(`bg-(${colorsAsRegex})-400`), + pattern: RegExp(`^bg-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-500`) + pattern: RegExp(`^bg-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`text-(${colorsAsRegex})-400`), + pattern: RegExp(`^text-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-500`) + pattern: RegExp(`^text-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-400`), + pattern: RegExp(`^ring-(${colorsAsRegex})-400$`), variants: ['dark:focus-visible'] }, { - pattern: new RegExp(`ring-(${colorsAsRegex})-500`), + pattern: RegExp(`^ring-(${colorsAsRegex})-500$`), variants: ['focus-visible'] }], progress: (colorsAsRegex) => [{ - pattern: new RegExp(`text-(${colorsAsRegex})-400`), + pattern: RegExp(`^text-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-500`) + pattern: RegExp(`^text-(${colorsAsRegex})-500$`) }], meter: (colorsAsRegex) => [{ - pattern: new RegExp(`bg-(${colorsAsRegex})-400`), + pattern: RegExp(`^bg-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-500`) + pattern: RegExp(`^bg-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`text-(${colorsAsRegex})-400`), + pattern: RegExp(`^text-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-500`) + pattern: RegExp(`^text-(${colorsAsRegex})-500$`) }], notification: (colorsAsRegex) => [{ - pattern: new RegExp(`bg-(${colorsAsRegex})-400`), + pattern: RegExp(`^bg-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-500`) + pattern: RegExp(`^bg-(${colorsAsRegex})-500$`) }, { - pattern: new RegExp(`text-(${colorsAsRegex})-400`), + pattern: RegExp(`^text-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`text-(${colorsAsRegex})-500`) + pattern: RegExp(`^text-(${colorsAsRegex})-500$`) }], chip: (colorsAsRegex) => [{ - pattern: new RegExp(`bg-(${colorsAsRegex})-400`), + pattern: RegExp(`^bg-(${colorsAsRegex})-400$`), variants: ['dark'] }, { - pattern: new RegExp(`bg-(${colorsAsRegex})-500`) + pattern: RegExp(`^bg-(${colorsAsRegex})-500$`) }] } @@ -324,7 +324,15 @@ export const customSafelistExtractor = (prefix: string, content: string, colors: 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)) + return colorOptions.map( + color => { + const classesExtracted = group.pattern.source.replace(match, color).replace('^', '').replace('$', '') + if (variant) { + return `${variant}:${classesExtracted}` + } + return classesExtracted + } + ) }).flat() }) }) diff --git a/test/colors.spec.ts b/test/colors.spec.ts index c86df16747..917d29a82a 100644 --- a/test/colors.spec.ts +++ b/test/colors.spec.ts @@ -24,17 +24,17 @@ describe('generateSafelist', () => { [ 'default safelist', {}, [], - ['bg-(primary)-50', 'bg-(red)-500'] // these both should be in the safelist + ['^bg-(primary)-50$', '^bg-(red)-500$'] // these both should be in the safelist ], [ 'safelisting single new color', {}, ['myColor'], - 'bg-(myColor|primary)-50' + '^bg-(myColor|primary)-50$' ], [ 'reducing amount of theme colors', { theme: { colors: { plainBlue: '#00F' } } }, ['plainBlue'], - ['bg-(plainBlue|primary)-50', '!', /orange/] // the word "orange" should _not_ be found in any safelist pattern + ['^bg-(plainBlue|primary)-50$', '!', /orange/] // the word "orange" should _not_ be found in any safelist pattern ] ])('%s', async (_description, tailwindConfig: Partial, safelistColors, safelistPatterns) => { safelistColors.push('primary')