diff --git a/packages/core/src/core/postprocess/important.ts b/packages/core/src/core/postprocess/important.ts new file mode 100644 index 0000000..bd33a1e --- /dev/null +++ b/packages/core/src/core/postprocess/important.ts @@ -0,0 +1,32 @@ +import type { Postprocessor } from '@unocss/core' +import type { FilterPattern, ImportantOptions } from '../../types' +import { toArray } from '@unocss/core' + +function createFilter( + include: FilterPattern, + exclude: FilterPattern, +): (id: string) => boolean { + const includePattern = toArray(include || []) + const excludePattern = toArray(exclude || []) + return (id: string) => { + if (excludePattern.some(p => id.match(p))) + return false + return includePattern.some(p => id.match(p)) + } +} + +export function importantProcess(importantOptions: ImportantOptions): Postprocessor { + console.log(importantOptions) + + const keyFilter = createFilter(importantOptions.includes || [], importantOptions.excludes || []) + + return (util) => { + for (const item of util.entries) { + console.log(item[0], keyFilter(item[0])) + + if (keyFilter(item[0]) && item[1] != null && !String(item[1]).includes('!important')) { + item[1] += ' !important' + } + } + } +} diff --git a/packages/core/src/core/postprocess/index.ts b/packages/core/src/core/postprocess/index.ts new file mode 100644 index 0000000..29cd468 --- /dev/null +++ b/packages/core/src/core/postprocess/index.ts @@ -0,0 +1,13 @@ +import type { Postprocessor } from '@unocss/core' +import type { ImportantOptions, ResolvedOptions } from '../../types' +import { importantProcess } from './important' +import { postprocessWithUnColor } from './uncolor' + +export function postprocess(options: ResolvedOptions): Postprocessor[] { + const { unColor, important } = options + + return [ + unColor ? postprocessWithUnColor(unColor as string) : undefined, + important ? importantProcess(important as ImportantOptions) : undefined, + ].filter(Boolean) as Postprocessor[] +} diff --git a/packages/core/src/core/postprocess.ts b/packages/core/src/core/postprocess/uncolor.ts similarity index 77% rename from packages/core/src/core/postprocess.ts rename to packages/core/src/core/postprocess/uncolor.ts index d577e74..d0b8bbe 100644 --- a/packages/core/src/core/postprocess.ts +++ b/packages/core/src/core/postprocess/uncolor.ts @@ -3,7 +3,6 @@ import type { Postprocessor } from '@unocss/core' const rgbRE = /rgb\(([\d\s]+?)\s*\/\s*([^)]+)\)/ const rgbaRE = /rgba\(([\d\s,]+),\s*([^)]+)\)/ -// IN-README-START // https://github.com/unocss/unocss/discussions/2816 // Extract rgba color in css variable. export function postprocessWithUnColor(unColor: string): Postprocessor { @@ -27,13 +26,3 @@ export function postprocessWithUnColor(unColor: string): Postprocessor { }) } } - -export function importantProcess(): Postprocessor { - return (util) => { - util.entries.forEach((i) => { - if (i[1] != null && !String(i[1]).includes('!important')) - i[1] += ' !important' - }) - } -} -// IN-README-END diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 6c35a15..f75f5d5 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,8 +1,7 @@ -import type { Postprocessor, Shortcut, UserConfig } from '@unocss/core' +import type { Shortcut, UserConfig } from '@unocss/core' import type { UsefulOptions, UsefulTheme } from './types' import { definePreset, mergeConfigs } from '@unocss/core' -import { extractors, preflights, rules, shortcuts, variants } from './core' -import { importantProcess, postprocessWithUnColor } from './core/postprocess' +import { extractors, postprocess, preflights, rules, shortcuts, variants } from './core' import { PRESET_NAME } from './meta' import { resolveOptions } from './resolve' @@ -12,7 +11,7 @@ export type { UsefulOptions, UsefulTheme } export const presetUseful = definePreset(async (options) => { const resolvedOptions = await resolveOptions(options ?? {}) - const { enableDefaultShortcuts, unColor, theme, meta, important } = resolvedOptions + const { enableDefaultShortcuts, theme, meta } = resolvedOptions return { name: `unocss-preset-${PRESET_NAME}`, @@ -24,10 +23,7 @@ export const presetUseful = definePreset(async (opti variants: variants(resolvedOptions), shortcuts: [...enableDefaultShortcuts ? shortcuts : [], ...meta.shortcuts] as Shortcut[], extractors, - postprocess: [ - unColor ? postprocessWithUnColor(unColor as string) : undefined, - important ? importantProcess() : undefined, - ].filter(Boolean) as Postprocessor[], + postprocess: postprocess(resolvedOptions), presets: meta.presets, transformers: meta.transformers, preflights: preflights(resolvedOptions), diff --git a/packages/core/src/resolve.ts b/packages/core/src/resolve.ts index c4941f4..96222c2 100644 --- a/packages/core/src/resolve.ts +++ b/packages/core/src/resolve.ts @@ -48,44 +48,10 @@ export async function resolveOptions(options: UsefulOptions) { ? optionsWithDefault.unColor : optionsWithDefault.unColor ? '--un-color' : false - const presets = [] - const transformers = [] - const presetMap = { - uno: import('@unocss/preset-uno').then(m => m.presetUno), - attributify: import('@unocss/preset-attributify').then(m => m.presetAttributify), - icons: import('@unocss/preset-icons').then(m => m.presetIcons), - webFonts: import('@unocss/preset-web-fonts').then(m => m.presetWebFonts), - typography: import('@unocss/preset-typography').then(m => m.presetTypography), - tagify: import('@unocss/preset-tagify').then(m => m.presetTagify), - remToPx: import('@unocss/preset-rem-to-px').then(m => m.default), - scrollbar: import('unocss-preset-scrollbar').then(m => m.presetScrollbar), - magicss: import('unocss-preset-magicss').then(m => m.presetMagicss), - } - const transformerMap = { - directives: import('unocss').then(m => m.transformerDirectives), - variantGroup: import('unocss').then(m => m.transformerVariantGroup), - compileClass: import('unocss').then(m => m.transformerCompileClass), - } - - for (const [key, preset] of Object.entries(presetMap)) { - const option = optionsWithDefault[key as keyof typeof presetMap] - if (option) { - const p = await preset as any - const presetOptions = defaultPresetOptions[key as keyof typeof defaultPresetOptions] - if (typeof option === 'object') - presets.push(p({ ...presetOptions, ...option })) - else - presets.push(p(presetOptions ?? {})) - } - } - for (const [key, transformer] of Object.entries(transformerMap)) { - const option = optionsWithDefault[key as keyof typeof transformerMap] - if (option) { - const t = await transformer as any - transformers.push(t(typeof option === 'boolean' ? {} as any : option)) - } - } + optionsWithDefault.important = optionsWithDefault.important === true ? { excludes: [] } : optionsWithDefault.important + const presets = await resolvePresets(optionsWithDefault) + const transformers = await resolveTransformers(optionsWithDefault) const { theme: t_theme, shortcuts } = resolveExtend(optionsWithDefault.theme.extend ?? {}) const _theme = deepMerge(optionsWithDefault.theme, t_theme) @@ -100,7 +66,7 @@ export async function resolveOptions(options: UsefulOptions) { } as ResolvedOptions } -export function resolveExtend(extend: UsefulTheme['extend']) { +function resolveExtend(extend: UsefulTheme['extend']) { const _shortcuts: CustomStaticShortcuts = [] const { animation, keyframes } = extend! @@ -118,3 +84,51 @@ export function resolveExtend(extend: UsefulTheme['extend']) { shortcuts: _shortcuts, } } + +async function resolvePresets(options: Required) { + const presets = [] + const presetMap = { + uno: import('@unocss/preset-uno').then(m => m.presetUno), + attributify: import('@unocss/preset-attributify').then(m => m.presetAttributify), + icons: import('@unocss/preset-icons').then(m => m.presetIcons), + webFonts: import('@unocss/preset-web-fonts').then(m => m.presetWebFonts), + typography: import('@unocss/preset-typography').then(m => m.presetTypography), + tagify: import('@unocss/preset-tagify').then(m => m.presetTagify), + remToPx: import('@unocss/preset-rem-to-px').then(m => m.default), + scrollbar: import('unocss-preset-scrollbar').then(m => m.presetScrollbar), + magicss: import('unocss-preset-magicss').then(m => m.presetMagicss), + } + + for (const [key, preset] of Object.entries(presetMap)) { + const option = options[key as keyof typeof presetMap] + if (option) { + const p = await preset as any + const presetOptions = defaultPresetOptions[key as keyof typeof defaultPresetOptions] + if (typeof option === 'object') + presets.push(p({ ...presetOptions, ...option })) + else + presets.push(p(presetOptions ?? {})) + } + } + + return presets +} + +async function resolveTransformers(options: Required) { + const transformers = [] + const transformerMap = { + directives: import('unocss').then(m => m.transformerDirectives), + variantGroup: import('unocss').then(m => m.transformerVariantGroup), + compileClass: import('unocss').then(m => m.transformerCompileClass), + } + + for (const [key, transformer] of Object.entries(transformerMap)) { + const option = options[key as keyof typeof transformerMap] + if (option) { + const t = await transformer as any + transformers.push(t(typeof option === 'boolean' ? {} as any : option)) + } + } + + return transformers +} diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 45fefff..f5ba7a8 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -44,13 +44,29 @@ interface PreflightOptions { reset?: boolean } +export type FilterPattern = Array | string | RegExp | null + +export interface ImportantOptions { + /** + * Make all unitilities important. + * + */ + includes?: FilterPattern + + /** + * Make all unitilities important. + * + */ + excludes?: FilterPattern +} + export interface UsefulOptions { /** * Make all unitilities important. * * @default false */ - important?: boolean + important?: boolean | ImportantOptions /** * Enable default shortcuts diff --git a/test/postprocess.test.ts b/test/postprocess.test.ts index 51d4d2a..9052604 100644 --- a/test/postprocess.test.ts +++ b/test/postprocess.test.ts @@ -69,8 +69,7 @@ describe('presetUseful postprocess with unColor', () => { }) describe('presetUseful postprocess with important', () => { - const withOutImport = ['bg-red', 'text-blue'] - const withInImport = ['!text-xl', 'sm:text-sm!', 'important-ma'] + const tokens = ['bg-red', 'text-blue', '!text-xl', 'sm:text-sm!', 'important-ma'] it('base', async () => { const uno = await generateUno({ @@ -78,7 +77,7 @@ describe('presetUseful postprocess with important', () => { preflights: false, }) - const { css } = await uno.generate([...withInImport, ...withOutImport]) + const { css } = await uno.generate(tokens) expect(css).toMatchInlineSnapshot(` "/* layer: default */