Skip to content

Commit

Permalink
feat: improving some types (unocss#1851)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
2 people authored and praburangki committed Jan 12, 2023
1 parent 25e3970 commit ca516af
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 66 deletions.
26 changes: 13 additions & 13 deletions packages/core/src/config.ts
Expand Up @@ -3,22 +3,22 @@ import { clone, isStaticRule, mergeDeep, normalizeVariant, toArray, uniq } from
import { extractorSplit } from './extractors'
import { DEFAULT_LAYERS } from './constants'

export function resolveShortcuts(shortcuts: UserShortcuts): Shortcut[] {
export function resolveShortcuts<Theme extends {} = {}>(shortcuts: UserShortcuts<Theme>): Shortcut<Theme>[] {
return toArray(shortcuts).flatMap((s) => {
if (Array.isArray(s))
return [s]
return Object.entries(s)
})
}

export function resolvePreset(preset: Preset): Preset {
export function resolvePreset<Theme extends {} = {}>(preset: Preset<Theme>): Preset<Theme> {
const shortcuts = preset.shortcuts
? resolveShortcuts(preset.shortcuts)
: undefined
preset.shortcuts = shortcuts as any

if (preset.prefix || preset.layer) {
const apply = (i: Rule | Shortcut) => {
const apply = (i: Rule<Theme> | Shortcut) => {
if (!i[2])
i[2] = {}
const meta = i[2]
Expand All @@ -34,11 +34,11 @@ export function resolvePreset(preset: Preset): Preset {
return preset
}

export function resolveConfig(
userConfig: UserConfig = {},
defaults: UserConfigDefaults = {},
): ResolvedConfig {
const config = Object.assign({}, defaults, userConfig) as UserConfigDefaults
export function resolveConfig<Theme extends {} = {}>(
userConfig: UserConfig<Theme> = {},
defaults: UserConfigDefaults<Theme> = {},
): ResolvedConfig<Theme> {
const config = Object.assign({}, defaults, userConfig) as UserConfigDefaults<Theme>
const rawPresets = (config.presets || []).flatMap(toArray).map(resolvePreset)

const sortedPresets = [
Expand All @@ -49,7 +49,7 @@ export function resolveConfig(

const layers = Object.assign(DEFAULT_LAYERS, ...rawPresets.map(i => i.layers), userConfig.layers)

function mergePresets<T extends 'rules' | 'variants' | 'extractors' | 'shortcuts' | 'preflights' | 'preprocess' | 'postprocess' | 'extendTheme' | 'safelist'>(key: T): Required<UserConfig>[T] {
function mergePresets<T extends 'rules' | 'variants' | 'extractors' | 'shortcuts' | 'preflights' | 'preprocess' | 'postprocess' | 'extendTheme' | 'safelist'>(key: T): Required<UserConfig<Theme>>[T] {
return uniq([
...sortedPresets.flatMap(p => toArray(p[key] || []) as any[]),
...toArray(config[key] || []) as any[],
Expand All @@ -62,7 +62,7 @@ export function resolveConfig(
extractors.sort((a, b) => (a.order || 0) - (b.order || 0))

const rules = mergePresets('rules')
const rulesStaticMap: ResolvedConfig['rulesStaticMap'] = {}
const rulesStaticMap: ResolvedConfig<Theme>['rulesStaticMap'] = {}

const rulesSize = rules.length

Expand All @@ -78,12 +78,12 @@ export function resolveConfig(
return [i, ...rule]
})
.filter(Boolean)
.reverse() as ResolvedConfig['rulesDynamic']
.reverse() as ResolvedConfig<Theme>['rulesDynamic']

const theme = clone([
const theme: Theme = clone([
...sortedPresets.map(p => p.theme || {}),
config.theme || {},
].reduce((a, p) => mergeDeep(a, p), {}))
].reduce<Theme>((a, p) => mergeDeep(a, p), {} as Theme))

;(mergePresets('extendTheme') as ThemeExtender<any>[]).forEach(extendTheme => extendTheme(theme))

Expand Down
58 changes: 29 additions & 29 deletions packages/core/src/generator/index.ts
Expand Up @@ -5,25 +5,25 @@ import { CONTROL_SHORTCUT_NO_MERGE, TwoKeyMap, e, entriesToCss, expandVariantGro
import { version } from '../../package.json'
import { LAYER_DEFAULT, LAYER_PREFLIGHTS } from '../constants'

export class UnoGenerator {
export class UnoGenerator<Theme extends {} = {}> {
public version = version
private _cache = new Map<string, StringifiedUtil[] | null>()
public config: ResolvedConfig
private _cache = new Map<string, StringifiedUtil<Theme>[] | null>()
public config: ResolvedConfig<Theme>
public blocked = new Set<string>()
public parentOrders = new Map<string, number>()
public events = createNanoEvents<{
config: (config: ResolvedConfig) => void
config: (config: ResolvedConfig<Theme>) => void
}>()

constructor(
public userConfig: UserConfig = {},
public defaults: UserConfigDefaults = {},
public userConfig: UserConfig<Theme> = {},
public defaults: UserConfigDefaults<Theme> = {},
) {
this.config = resolveConfig(userConfig, defaults)
this.events.emit('config', this.config)
}

setConfig(userConfig?: UserConfig, defaults?: UserConfigDefaults) {
setConfig(userConfig?: UserConfig<Theme>, defaults?: UserConfigDefaults<Theme>) {
if (!userConfig)
return
if (defaults)
Expand Down Expand Up @@ -54,8 +54,8 @@ export class UnoGenerator {
return set
}

makeContext(raw: string, applied: VariantMatchedResult) {
const context: RuleContext = {
makeContext(raw: string, applied: VariantMatchedResult<Theme>) {
const context: RuleContext<Theme> = {
rawSelector: raw,
currentSelector: applied[1],
theme: this.config.theme,
Expand Down Expand Up @@ -141,7 +141,7 @@ export class UnoGenerator {

const layerSet = new Set<string>([LAYER_DEFAULT])
const matched = new Set<string>()
const sheet = new Map<string, StringifiedUtil[]>()
const sheet = new Map<string, StringifiedUtil<Theme>[]>()
let preflightsMap: Record<string, string> = {}

const tokenPromises = Array.from(tokens).map(async (raw) => {
Expand Down Expand Up @@ -170,7 +170,7 @@ export class UnoGenerator {
if (!preflights)
return

const preflightContext: PreflightContext = {
const preflightContext: PreflightContext<Theme> = {
generator: this,
theme: this.config.theme,
}
Expand Down Expand Up @@ -292,14 +292,14 @@ export class UnoGenerator {
}
}

matchVariants(raw: string, current?: string): VariantMatchedResult {
matchVariants(raw: string, current?: string): VariantMatchedResult<Theme> {
// process variants
const variants = new Set<Variant>()
const variants = new Set<Variant<Theme>>()
const handlers: VariantHandler[] = []
let processed = current || raw
let applied = false

const context: VariantContext = {
const context: VariantContext<Theme> = {
rawSelector: raw,
theme: this.config.theme,
generator: this,
Expand Down Expand Up @@ -382,7 +382,7 @@ export class UnoGenerator {
return obj
}

constructCustomCSS(context: Readonly<RuleContext>, body: CSSObject | CSSEntries, overrideSelector?: string) {
constructCustomCSS(context: Readonly<RuleContext<Theme>>, body: CSSObject | CSSEntries, overrideSelector?: string) {
const normalizedBody = normalizeCSSEntries(body)
if (isString(normalizedBody))
return normalizedBody
Expand All @@ -394,7 +394,7 @@ export class UnoGenerator {
return cssBody
}

async parseUtil(input: string | VariantMatchedResult, context: RuleContext, internal = false, shortcutPrefix: string | undefined = undefined): Promise<(ParsedUtil | RawUtil)[] | undefined> {
async parseUtil(input: string | VariantMatchedResult<Theme>, context: RuleContext<Theme>, internal = false, shortcutPrefix: string | undefined = undefined): Promise<(ParsedUtil | RawUtil)[] | undefined> {
const [raw, processed, variantHandlers] = isString(input)
? this.matchVariants(input)
: input
Expand Down Expand Up @@ -453,7 +453,7 @@ export class UnoGenerator {
continue

if (this.config.details)
context.rules!.push([matcher, handler, meta] as DynamicRule)
context.rules!.push([matcher, handler, meta] as DynamicRule<Theme>)

const entries = normalizeCSSValues(result).filter(i => i.length)
if (entries.length) {
Expand All @@ -467,7 +467,7 @@ export class UnoGenerator {
}
}

stringifyUtil(parsed?: ParsedUtil | RawUtil, context?: RuleContext): StringifiedUtil | undefined {
stringifyUtil(parsed?: ParsedUtil | RawUtil, context?: RuleContext<Theme>): StringifiedUtil<Theme> | undefined {
if (!parsed)
return
if (isRawUtil(parsed))
Expand All @@ -488,12 +488,12 @@ export class UnoGenerator {
return [parsed[0], selector, body, parent, ruleMeta, this.config.details ? context : undefined, noMerge]
}

expandShortcut(input: string, context: RuleContext, depth = 5): [ShortcutValue[], RuleMeta | undefined] | undefined {
expandShortcut(input: string, context: RuleContext<Theme>, depth = 5): [ShortcutValue[], RuleMeta | undefined] | undefined {
if (depth === 0)
return

const recordShortcut = this.config.details
? (s: Shortcut) => {
? (s: Shortcut<Theme>) => {
context.shortcuts = context.shortcuts ?? []
context.shortcuts.push(s)
}
Expand Down Expand Up @@ -554,11 +554,11 @@ export class UnoGenerator {
}

async stringifyShortcuts(
parent: VariantMatchedResult,
context: RuleContext,
parent: VariantMatchedResult<Theme>,
context: RuleContext<Theme>,
expanded: ShortcutValue[],
meta: RuleMeta = { layer: this.config.shortcutsLayer },
): Promise<StringifiedUtil[] | undefined> {
): Promise<StringifiedUtil<Theme>[] | undefined> {
const selectorMap = new TwoKeyMap<string, string | undefined, [[CSSEntries, boolean, number][], number]>()
const parsed = (
await Promise.all(uniq(expanded)
Expand All @@ -578,7 +578,7 @@ export class UnoGenerator {
.sort((a, b) => a[0] - b[0])

const [raw, , parentVariants] = parent
const rawStringfieldUtil: StringifiedUtil[] = []
const rawStringfieldUtil: StringifiedUtil<Theme>[] = []
for (const item of parsed) {
if (isRawUtil(item)) {
rawStringfieldUtil.push([item[0], undefined, item[1], undefined, item[2], context, undefined])
Expand All @@ -593,10 +593,10 @@ export class UnoGenerator {
}
return rawStringfieldUtil.concat(selectorMap
.map(([e, index], selector, joinedParents) => {
const stringify = (flatten: boolean, noMerge: boolean, entrySortPair: [CSSEntries, number][]): (StringifiedUtil | undefined)[] => {
const stringify = (flatten: boolean, noMerge: boolean, entrySortPair: [CSSEntries, number][]): (StringifiedUtil<Theme> | undefined)[] => {
const maxSort = Math.max(...entrySortPair.map(e => e[1]))
const entriesList = entrySortPair.map(e => e[0])
return (flatten ? [entriesList.flat(1)] : entriesList).map((entries: CSSEntries): StringifiedUtil | undefined => {
return (flatten ? [entriesList.flat(1)] : entriesList).map((entries: CSSEntries): StringifiedUtil<Theme> | undefined => {
const body = entriesToCss(entries)
if (body)
return [index, selector, body, joinedParents, { ...meta, noMerge, sort: maxSort }, context, undefined]
Expand All @@ -615,16 +615,16 @@ export class UnoGenerator {
])
})
.flat(2)
.filter(Boolean) as StringifiedUtil[])
.filter(Boolean) as StringifiedUtil<Theme>[])
}

isBlocked(raw: string) {
return !raw || this.config.blocklist.some(e => isString(e) ? e === raw : e.test(raw))
}
}

export function createGenerator(config?: UserConfig, defaults?: UserConfigDefaults) {
return new UnoGenerator(config, defaults)
export function createGenerator<Theme extends {} = {}>(config?: UserConfig<Theme>, defaults?: UserConfigDefaults<Theme>) {
return new UnoGenerator<Theme>(config, defaults)
}

export const regexScopePlaceholder = / \$\$ /
Expand Down
36 changes: 18 additions & 18 deletions packages/core/src/types.ts
Expand Up @@ -64,7 +64,7 @@ export interface RuleContext<Theme extends {} = {}> {
/**
* UnoCSS generator instance
*/
generator: UnoGenerator
generator: UnoGenerator<Theme>
/**
* The theme object
*/
Expand All @@ -76,7 +76,7 @@ export interface RuleContext<Theme extends {} = {}> {
/**
* The result of variant matching.
*/
variantMatch: VariantMatchedResult
variantMatch: VariantMatchedResult<Theme>
/**
* Construct a custom CSS rule.
* Variants and selector escaping will be handled automatically.
Expand All @@ -85,15 +85,15 @@ export interface RuleContext<Theme extends {} = {}> {
/**
* Available only when `details` option is enabled.
*/
rules?: Rule[]
rules?: Rule<Theme>[]
/**
* Available only when `details` option is enabled.
*/
shortcuts?: Shortcut[]
shortcuts?: Shortcut<Theme>[]
/**
* Available only when `details` option is enabled.
*/
variants?: Variant[]
variants?: Variant<Theme>[]
}

export interface VariantContext<Theme extends {} = {}> {
Expand All @@ -104,7 +104,7 @@ export interface VariantContext<Theme extends {} = {}> {
/**
* UnoCSS generator instance
*/
generator: UnoGenerator
generator: UnoGenerator<Theme>
/**
* The theme object
*/
Expand All @@ -121,7 +121,7 @@ export interface PreflightContext<Theme extends {} = {}> {
/**
* UnoCSS generator instance
*/
generator: UnoGenerator
generator: UnoGenerator<Theme>
/**
* The theme object
*/
Expand Down Expand Up @@ -616,18 +616,18 @@ export interface PluginOptions {
export interface UserConfig<Theme extends {} = {}> extends ConfigBase<Theme>, UserOnlyOptions<Theme>, GeneratorOptions, PluginOptions, CliOptions {}
export interface UserConfigDefaults<Theme extends {} = {}> extends ConfigBase<Theme>, UserOnlyOptions<Theme> {}

export interface ResolvedConfig extends Omit<
RequiredByKey<UserConfig, 'mergeSelectors' | 'theme' | 'rules' | 'variants' | 'layers' | 'extractors' | 'blocklist' | 'safelist' | 'preflights' | 'sortLayers'>,
export interface ResolvedConfig<Theme extends {} = {}> extends Omit<
RequiredByKey<UserConfig<Theme>, 'mergeSelectors' | 'theme' | 'rules' | 'variants' | 'layers' | 'extractors' | 'blocklist' | 'safelist' | 'preflights' | 'sortLayers'>,
'rules' | 'shortcuts' | 'autocomplete'
> {
presets: Preset[]
shortcuts: Shortcut[]
variants: VariantObject[]
presets: Preset<Theme>[]
shortcuts: Shortcut<Theme>[]
variants: VariantObject<Theme>[]
preprocess: Preprocessor[]
postprocess: Postprocessor[]
rulesSize: number
rulesDynamic: [number, ...DynamicRule][]
rulesStaticMap: Record<string, [number, CSSObject | CSSEntries, RuleMeta | undefined, Rule] | undefined>
rulesDynamic: [number, ...DynamicRule<Theme>][]
rulesStaticMap: Record<string, [number, CSSObject | CSSEntries, RuleMeta | undefined, Rule<Theme>] | undefined>
autocomplete: {
templates: (AutoCompleteFunction | AutoCompleteTemplate)[]
extractors: AutoCompleteExtractor[]
Expand All @@ -642,11 +642,11 @@ export interface GenerateResult {
matched: Set<string>
}

export type VariantMatchedResult = readonly [
export type VariantMatchedResult<Theme extends {} = {}> = readonly [
raw: string,
current: string,
variantHandlers: VariantHandler[],
variants: Set<Variant>,
variants: Set<Variant<Theme>>,
]

export type ParsedUtil = readonly [
Expand All @@ -663,13 +663,13 @@ export type RawUtil = readonly [
meta: RuleMeta | undefined,
]

export type StringifiedUtil = readonly [
export type StringifiedUtil<Theme extends {} = {}> = readonly [
index: number,
selector: string | undefined,
body: string,
parent: string | undefined,
meta: RuleMeta | undefined,
context: RuleContext | undefined,
context: RuleContext<Theme> | undefined,
noMerge: boolean | undefined,
]

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/utils/helpers.ts
Expand Up @@ -13,7 +13,7 @@ export function isValidSelector(selector = ''): selector is string {
return validateFilterRE.test(selector)
}

export function normalizeVariant(variant: Variant): VariantObject {
export function normalizeVariant(variant: Variant<any>): VariantObject<any> {
return typeof variant === 'function'
? { match: variant }
: variant
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/utils/object.ts
Expand Up @@ -98,10 +98,10 @@ export function clone<T>(val: T): T {
return val
}

export function isStaticRule(rule: Rule): rule is StaticRule {
export function isStaticRule(rule: Rule<any>): rule is StaticRule {
return isString(rule[0])
}

export function isStaticShortcut(sc: Shortcut): sc is StaticShortcut {
export function isStaticShortcut(sc: Shortcut<any>): sc is StaticShortcut {
return isString(sc[0])
}

0 comments on commit ca516af

Please sign in to comment.