|
| 1 | +import { ObjectDictionary } from "@opticss/util"; |
| 2 | +// Every CSS Block style is assigned a unique number that is globally unique |
| 3 | +export type GlobalStyleIndex = number; |
| 4 | +// This represents an index that is local to a specific block |
| 5 | +export type LocalStyleIndex = number; |
| 6 | +// For clarity as to what type of information the strings are |
| 7 | +export type Classname = string; |
| 8 | +export type OptimizedClassname = string; |
| 9 | +// this is a really fancy way to alias to `number` |
| 10 | +export type OutputClassnameIndex = Exclude<keyof AggregateRewriteData["outputClassnames"], string>; |
| 11 | +// this is a really fancy way to alias to `number` |
| 12 | +export type GlobalBlockIndex = Exclude<keyof AggregateRewriteData["blocks"], string>; |
| 13 | +// this is a really fancy way to alias to `number` |
| 14 | +export type OptimizationIndex = Exclude<keyof AggregateRewriteData["optimizations"], string>; |
| 15 | + |
| 16 | +// These 5 lines are a compact AST for boolean expressions. |
| 17 | +// Normally an AST would use objects with more expressive keys, but we want a |
| 18 | +// more compact data structure in this AST for fewer bytes in our output. |
| 19 | +// An array represents a sub-expression and the first element in that array indicates the |
| 20 | +// sub-expression type. |
| 21 | +// |
| 22 | +// When a GlobalStyleIndex is encountered, that part of the boolean expression |
| 23 | +// is considered true iff the current input state has that GlobalStyleIndex applied. |
| 24 | +export enum Operator { AND = 1, OR = 2, NOT = 3 } |
| 25 | +export type ConditionalStyleExpression = AndStyleExpression | OrStyleExpression | NotStyleExpression; |
| 26 | +export type StyleExpression = number | ConditionalStyleExpression; |
| 27 | +export type AndStyleExpression = [Operator.AND, ...StyleExpression[]]; |
| 28 | +export type OrStyleExpression = [Operator.OR, ...StyleExpression[]]; |
| 29 | +export type NotStyleExpression = [Operator.NOT, StyleExpression]; |
| 30 | + |
| 31 | +export interface ConditionalStyle { |
| 32 | + style: GlobalBlockIndex; |
| 33 | + conditions: ConditionalStyleExpression; |
| 34 | +} |
| 35 | + |
| 36 | +export interface StyleRequirements { |
| 37 | + // The key is a GlobalStyleIndex. |
| 38 | + // |
| 39 | + // Value is condition that must be met for this style to be applied |
| 40 | + // even if the style itself is not dynamic. |
| 41 | + [styleIndex: number]: ConditionalStyleExpression; |
| 42 | +} |
| 43 | + |
| 44 | +export interface ImpliedStyles { |
| 45 | + // The key is a GlobalStyleIndex |
| 46 | + // |
| 47 | + // Value is an unordered set. |
| 48 | + // - GlobalStyleIndex: a style that is also applied in conjunction with the given style. |
| 49 | + // - string: public class name (block alias) that is also applied in conjunction with the given style. |
| 50 | + // |
| 51 | + // Note: This list is only the directly implied styles. The full implication |
| 52 | + // graph is resolved at runtime. |
| 53 | + [styleIndex: number]: Array<GlobalStyleIndex | string | ConditionalStyle>; |
| 54 | +} |
| 55 | + |
| 56 | +export type OptimizationEntry = [OutputClassnameIndex, StyleExpression]; |
| 57 | + |
| 58 | +export interface AggregateRewriteData { |
| 59 | + // Maps a block's unique ID to an index of AggregateRewriteData["blocks"]. |
| 60 | + blockIds: ObjectDictionary<GlobalBlockIndex>; |
| 61 | + blocks: Array<BlockInfo>; |
| 62 | + |
| 63 | + // This is a list of all the class names that might be returned by the rewrite helper |
| 64 | + // with the exception of public class names (block aliases) that are found in the styleImplications. |
| 65 | + // Note: classnames from the original source that are not optimized are also returned here. |
| 66 | + // Note: classnames from the original source that the optimizer has flagged as obsolete are not listed here. |
| 67 | + outputClassnames: Array<OptimizedClassname>; |
| 68 | + styleRequirements: StyleRequirements; |
| 69 | + impliedStyles: ImpliedStyles; |
| 70 | + // Adds the class name to the output if the style expression matches the current input state. |
| 71 | + optimizations: Array<OptimizationEntry>; |
| 72 | + // possibleOptimizations: { |
| 73 | + // // Key is a GlobalStyleIndex. |
| 74 | + // // Value is a list of all outputs that might apply for the given GlobalStyleIndex. |
| 75 | + // [styleIndex: number]: Array<OptimizationIndex>; |
| 76 | + // }; |
| 77 | +} |
| 78 | + |
| 79 | +export interface BlockInfo { |
| 80 | + // The styles of this block |
| 81 | + // Note: this includes all the styles that are inherited but not overridden |
| 82 | + // but does not include the styles that are inherited but then overridden. |
| 83 | + blockInterfaceStyles: ObjectDictionary<LocalStyleIndex>; |
| 84 | + // Given a block that implements this block's interface or inherits from this interface |
| 85 | + // Get an array of GlobalStyleIndex values that directly correspond to the same index as BlockInfo["styles"]. |
| 86 | + // Note: If an implementation inherits from this block, this array will contain |
| 87 | + // GlobalStyleIndex values from this BlockInfo's styles wherever those styles |
| 88 | + // are not overridden. Thus it is guaranteed that each value in `implementationStyles` |
| 89 | + // has the same length as the `styles` array. |
| 90 | + implementations: { |
| 91 | + // The key is a GlobalStyleIndex |
| 92 | + [blockIndex: number]: Array<GlobalStyleIndex | null>; |
| 93 | + }; |
| 94 | +} |
0 commit comments