This commit is contained in:
Jordan Pittman 2024-07-04 19:39:43 -04:00
parent b6426b4f57
commit 103de984eb
2 changed files with 81 additions and 13 deletions

View file

@ -1,14 +1,64 @@
import { expect, test } from 'vitest'
import { test, vi } from 'vitest'
import type { UserConfig } from './config'
import { run } from './test-utils/run'
test('Custom static utilities', () => {
test('Plugins are called', ({ expect }) => {
let fn = vi.fn()
let handler = vi.fn()
let config: UserConfig = {
plugins: [fn, { handler }],
}
run([], config)
expect(fn).toHaveBeenCalledWith(
expect.objectContaining({
addUtility: expect.any(Function),
addUtilities: expect.any(Function),
addVariant: expect.any(Function),
addVariants: expect.any(Function),
}),
)
expect(handler).toHaveBeenCalledWith(
expect.objectContaining({
addUtility: expect.any(Function),
addUtilities: expect.any(Function),
addVariant: expect.any(Function),
addVariants: expect.any(Function),
}),
)
})
test('Asynchronous plugins are waited on', async ({ expect }) => {
let before = vi.fn()
let after = vi.fn()
let config: UserConfig = {
plugins: [
async () => {
before()
await new Promise((resolve) => setTimeout(resolve))
after()
},
],
}
await run([], config)
expect(before).toHaveBeenCalled()
expect(after).toHaveBeenCalled()
})
test('Custom static utilities', ({ expect }) => {
let config: UserConfig = {
plugins: [
({ addUtilities }) => {
addUtilities({
'.my-red': {
color: 'red',
'& > *': {
color: 'lightred',
},
},
'.my-blue': {
color: 'red',
@ -26,7 +76,7 @@ test('Custom static utilities', () => {
expect(run(['-my-red', 'my-red-[--value]'], config)).toEqual('')
})
test('Custom functional utilities', () => {
test('Custom functional utilities', ({ expect }) => {
let config: UserConfig = {
plugins: [
({ addUtilities }) => {
@ -54,7 +104,7 @@ test('Custom functional utilities', () => {
`)
})
test('Custom static variants', () => {
test('Custom static variants', ({ expect }) => {
let config: UserConfig = {
plugins: [
({ addVariant }) => {
@ -72,7 +122,7 @@ test('Custom static variants', () => {
expect(run(['hover/foo:underline', 'hover-[123]:underline'], config)).toEqual('')
})
test('Custom functional variants', () => {
test('Custom functional variants', ({ expect }) => {
let config: UserConfig = {
plugins: [
({ addVariant }) => {

View file

@ -2,27 +2,35 @@ import { decl, rule, type AstNode, type Rule } from './ast'
import type { Candidate } from './candidate'
import type { DesignSystem } from './design-system'
type MatchData = {
export type MatchData = {
value: string | null
modifier: string | null
}
type CssSelectors = string | string[]
export type SelectorFormat = CssSelectors | ((candidate: MatchData) => CssSelectors)
export type UtilityFormat = CssTree | ((value: string | null, candidate: MatchData) => CssTree)
export type CssSelectors = string | string[]
export interface CssTree extends Record<string, string | CssTree> {}
type SelectorFormat = CssSelectors | ((candidate: MatchData) => CssSelectors)
type UtilityFormat = CssTree | ((value: string | null, candidate: MatchData) => CssTree)
export interface PluginAPI {
addVariant(name: string, selector: SelectorFormat): void
addVariant(name: string, format: SelectorFormat): void
addVariants(variants: Record<string, SelectorFormat>): void
addUtility(name: string, format: UtilityFormat): void
addUtilities(utilities: Record<string, UtilityFormat>): void
}
export interface Plugin {
export type Plugin = FunctionalPlugin | ConfigurablePlugin
export interface FunctionalPlugin {
(api: PluginAPI): void | Promise<void>
}
export interface ConfigurablePlugin {
handler(api: PluginAPI): void | Promise<void>
}
/**
* Convert a recursive object structure to an AST
* Leaf nodes are declarations and branches are rules
@ -141,11 +149,21 @@ export function registerPlugins(design: DesignSystem) {
)
}
function addVariants(list: Record<string, SelectorFormat>) {
for (let [name, format] of Object.entries(list)) {
addVariant(name, format)
}
}
for (let plugin of design.plugins) {
plugin({
let handler = typeof plugin === 'function' ? plugin : plugin.handler
handler({
// v3 compatible legacy API
addUtility,
addUtilities,
addVariant,
addVariants,
})
}
}