import type { StylableMeta } from '../stylable-meta'; import type { InferredSelector, ScopeContext, StylableExports, StylableTransformer, } from '../stylable-transformer'; import type { StylableResolver, MetaResolvedSymbols } from '../stylable-resolver'; import type { StylableEvaluator, EvalValueData } from '../functions'; import type * as postcss from 'postcss'; import type { ImmutableSelectorNode } from '@tokey/css-selector-parser'; import type { Diagnostics } from '../diagnostics'; import type { ParsedValue } from '../types'; export interface FeatureFlags { strictCustomProperty: boolean; } export const defaultFeatureFlags: FeatureFlags = { strictCustomProperty: false, }; export type SelectorNodeContext = [ index: number, nodes: ImmutableSelectorNode[], parents: ImmutableSelectorNode[] ]; export interface FeatureContext { meta: StylableMeta; diagnostics: Diagnostics; } export interface FeatureTransformContext extends FeatureContext { resolver: StylableResolver; evaluator: StylableEvaluator; getResolvedSymbols: (meta: StylableMeta) => MetaResolvedSymbols; passedThrough?: string[]; inferredSelectorMixin?: InferredSelector; } export interface NodeTypes { SELECTOR?: any; IMMUTABLE_SELECTOR?: any; RESOLVED?: any; } type SelectorWalkReturn = number | undefined | void; export interface FeatureHooks { metaInit: (context: FeatureContext) => void; analyzeInit: (context: FeatureContext) => void; analyzeAtRule: (options: { context: FeatureContext; atRule: postcss.AtRule; analyzeRule: ( rule: postcss.Rule, options: { isScoped: boolean; originalNode: postcss.AtRule | postcss.Rule } ) => boolean; }) => void; analyzeSelectorNode: (options: { context: FeatureContext; node: T['IMMUTABLE_SELECTOR']; topSelectorIndex: number; rule: postcss.Rule; originalNode: postcss.AtRule | postcss.Rule; // used by rules generated from at-rules walkContext: SelectorNodeContext; }) => SelectorWalkReturn; analyzeSelectorDone: (options: { context: FeatureContext; rule: postcss.Rule; originalNode: postcss.AtRule | postcss.Rule; // used by rules generated from at-rules }) => SelectorWalkReturn; analyzeDeclaration: (options: { context: FeatureContext; decl: postcss.Declaration }) => void; analyzeDone: (context: FeatureContext) => void; prepareAST: (options: { context: FeatureTransformContext; node: postcss.ChildNode; toRemove: Array void)>; }) => void; transformInit: (options: { context: FeatureTransformContext }) => void; transformResolve: (options: { context: FeatureTransformContext }) => T['RESOLVED']; transformAtRuleNode: (options: { context: FeatureTransformContext; atRule: postcss.AtRule; resolved: T['RESOLVED']; // ToDo: move to FeatureTransformContext transformer: StylableTransformer; }) => void; transformSelectorNode: (options: { context: FeatureTransformContext; node: T['SELECTOR']; selectorContext: Required; }) => boolean | void; transformDeclaration: (options: { context: FeatureTransformContext; decl: postcss.Declaration; resolved: T['RESOLVED']; }) => void; transformValue: (options: { context: FeatureTransformContext; node: ParsedValue; data: EvalValueData; }) => void; transformJSExports: (options: { exports: StylableExports; resolved: T['RESOLVED'] }) => void; transformLastPass: (options: { context: FeatureTransformContext; ast: postcss.Root; transformer: StylableTransformer; path: string[]; }) => void; } const defaultHooks: FeatureHooks = { metaInit() { /**/ }, analyzeInit() { /**/ }, analyzeAtRule() { /**/ }, analyzeSelectorNode() { /**/ }, analyzeSelectorDone() { /**/ }, analyzeDeclaration() { /**/ }, analyzeDone() { /**/ }, prepareAST() { /**/ }, transformInit() { /**/ }, transformResolve() { return {}; }, transformAtRuleNode() { /**/ }, transformSelectorNode() { /**/ }, transformDeclaration() { /**/ }, transformValue() { /**/ }, transformJSExports() { /**/ }, transformLastPass() { /**/ }, }; export function createFeature( hooks: Partial> ): FeatureHooks { return { ...defaultHooks, ...hooks, }; }