UNPKG

lightningcss

Version:

A CSS parser, transformer, and minifier written in Rust

825 lines (756 loc) 20.3 kB
// @flow type Exclude<A, B> = A; // see https://gist.github.com/thecotne/6e5969f4aaf8f253985ed36b30ac9fe0 type $FlowGen$If<X: boolean, Then, Else = empty> = $Call< ((true, Then, Else) => Then) & ((false, Then, Else) => Else), X, Then, Else >; type $FlowGen$Assignable<A, B> = $Call< ((...r: [B]) => true) & ((...r: [A]) => false), A >; import type { Angle, CssColor, Rule, CustomProperty, EnvironmentVariable, Function, Image, LengthValue, MediaQuery, Declaration, Ratio, Resolution, Selector, SupportsCondition, Time, Token, TokenOrValue, UnknownAtRule, Url, Variable, StyleRule, DeclarationBlock, ParsedComponent, Multiplier, StyleSheet, Location2, } from "./ast.js.flow"; import { Targets, Features } from "./targets.js.flow"; declare export * from "./ast.js.flow"; declare export { Targets, Features }; export type TransformOptions<C: CustomAtRules> = {| /** * The filename being transformed. Used for error messages and source maps. */ filename: string, /** * The source code to transform. */ code: Uint8Array, /** * Whether to enable minification. */ minify?: boolean, /** * Whether to output a source map. */ sourceMap?: boolean, /** * An input source map to extend. */ inputSourceMap?: string, /** * An optional project root path, used as the source root in the output source map. * Also used to generate relative paths for sources used in CSS module hashes. */ projectRoot?: string, /** * The browser targets for the generated code. */ targets?: Targets, /** * Features that should always be compiled, even when supported by targets. */ include?: number, /** * Features that should never be compiled, even when unsupported by targets. */ exclude?: number, /** * Whether to enable parsing various draft syntax. */ drafts?: Drafts, /** * Whether to enable various non-standard syntax. */ nonStandard?: NonStandard, /** * Whether to compile this file as a CSS module. */ cssModules?: boolean | CSSModulesConfig, /** * Whether to analyze dependencies (e.g. string). * When enabled, string dependencies * are replaced with hashed placeholders that can be replaced with the final * urls later (after bundling). Dependencies are returned as part of the result. */ analyzeDependencies?: boolean | DependencyOptions, /** * Replaces user action pseudo classes with class names that can be applied from JavaScript. * This is useful for polyfills, for example. */ pseudoClasses?: PseudoClasses, /** * A list of class names, ids, and custom identifiers (e.g. @keyframes) that are known * to be unused. These will be removed during minification. Note that these are not * selectors but individual names (without any . or # prefixes). */ unusedSymbols?: string[], /** * Whether to ignore invalid rules and declarations rather than erroring. * When enabled, warnings are returned, and the invalid rule or declaration is * omitted from the output code. */ errorRecovery?: boolean, /** * An AST visitor object. This allows custom transforms or analysis to be implemented in JavaScript. * Multiple visitors can be composed into one using the string function. * For optimal performance, visitors should be as specific as possible about what types of values * they care about so that JavaScript has to be called as little as possible. */ visitor?: Visitor<C>, /** * Defines how to parse custom CSS at-rules. Each at-rule can have a prelude, defined using a CSS * [syntax string](https://drafts.css-houdini.org/css-properties-values-api/#syntax-strings), and * a block body. The body can be a declaration list, rule list, or style block as defined in the * [css spec](https://drafts.csswg.org/css-syntax/#declaration-rule-list). */ customAtRules?: C, |}; declare type PropertyStart = | "-" | "_" | "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"; export type ReturnedDeclaration = | Declaration | {| /** * The property name. */ property: string, /** * The raw string value for the declaration. */ raw: string, |}; export type ReturnedMediaQuery = | MediaQuery | {| /** * The raw string value for the media query. */ raw: string, |}; declare type FindByType<Union, Name> = $FlowGen$If< $FlowGen$Assignable< Union, {| type: Name, |} >, Union, empty >; export type ReturnedRule = Rule<ReturnedDeclaration, ReturnedMediaQuery>; declare type RequiredValue<Rule> = $FlowGen$If< $FlowGen$Assignable< Rule, {| value: { [key: string]: any }, |} >, $FlowGen$If< $FlowGen$Assignable<$PropertyType<Rule, "value">, StyleRule>, {| ...Rule, ...{| value: {| ...Required<StyleRule>, ...{| declarations: Required<DeclarationBlock>, |}, |}, |}, |}, {| ...Rule, ...{| value: Required<$PropertyType<Rule, "value">>, |}, |} >, Rule >; declare type RuleVisitor<R = RequiredValue<Rule>> = ( rule: R ) => ReturnedRule | ReturnedRule[] | void; declare type MappedRuleVisitors = $ObjMapi< { [k: Exclude<$PropertyType<Rule, "type">, "unknown" | "custom">]: any }, <Name>(Name) => RuleVisitor<RequiredValue<FindByType<Rule, Name>>> >; declare type UnknownVisitors<T> = { [name: string]: RuleVisitor<T>, }; declare type CustomVisitors<T: CustomAtRules> = $ObjMapi< T, <Name>(Name) => RuleVisitor<CustomAtRule<Name, $ElementType<T, Name>>> >; declare type AnyCustomAtRule<C: CustomAtRules> = $ElementType< $ObjMapi<C, <Key>(Key) => CustomAtRule<Key, $ElementType<C, Key>>>, $Keys<C> >; declare type RuleVisitors<C: CustomAtRules> = {| ...MappedRuleVisitors, ...{| unknown?: | UnknownVisitors<UnknownAtRule> | $Diff< RuleVisitor<UnknownAtRule>, { [key: $Keys<CallableFunction>]: any } >, custom?: | CustomVisitors<C> | $Diff< RuleVisitor<AnyCustomAtRule<C>>, { [key: $Keys<CallableFunction>]: any } >, |}, |}; declare type PreludeTypes = Exclude< $PropertyType<ParsedComponent, "type">, "literal" | "repeated" | "token" >; declare type SyntaxString = string | string; declare type ComponentTypes = $ObjMapi< { [k: PreludeTypes]: any }, <Key>(Key) => FindByType<ParsedComponent, Key> >; declare type Repetitions = $ObjMapi< { [k: PreludeTypes]: any }, <Key>(Key) => {| type: "repeated", value: {| components: FindByType<ParsedComponent, Key>[], multiplier: Multiplier, |}, |} >; declare type MappedPrelude = {| ...ComponentTypes, ...Repetitions |}; declare type MappedBody<P: $PropertyType<CustomAtRuleDefinition, "body">> = $FlowGen$If<$FlowGen$Assignable<P, "style-block">, "rule-list", P>; declare type CustomAtRule<N, R: CustomAtRuleDefinition> = {| name: N, prelude: $FlowGen$If< $FlowGen$Assignable<$PropertyType<R, "prelude">, $Keys<MappedPrelude>>, $ElementType<MappedPrelude, $PropertyType<R, "prelude">>, ParsedComponent >, body: FindByType<CustomAtRuleBody, MappedBody<$PropertyType<R, "body">>>, loc: Location2, |}; declare type CustomAtRuleBody = | {| type: "declaration-list", value: Required<DeclarationBlock>, |} | {| type: "rule-list", value: RequiredValue<Rule>[], |}; declare type FindProperty<Union, Name> = $FlowGen$If< $FlowGen$Assignable< Union, {| property: Name, |} >, Union, empty >; declare type DeclarationVisitor<P = Declaration> = ( property: P ) => ReturnedDeclaration | ReturnedDeclaration[] | void; declare type MappedDeclarationVisitors = $ObjMapi< { [k: Exclude< $PropertyType<Declaration, "property">, "unparsed" | "custom" >]: any, }, <Name>( Name ) => DeclarationVisitor< FindProperty<Declaration, Name> | FindProperty<Declaration, "unparsed"> > >; declare type CustomPropertyVisitors = { [name: string]: DeclarationVisitor<CustomProperty>, }; declare type DeclarationVisitors = {| ...MappedDeclarationVisitors, ...{| custom?: CustomPropertyVisitors | DeclarationVisitor<CustomProperty>, |}, |}; declare type RawValue = {| /** * A raw string value which will be parsed like CSS. */ raw: string, |}; declare type TokenReturnValue = TokenOrValue | TokenOrValue[] | RawValue | void; declare type TokenVisitor = (token: Token) => TokenReturnValue; declare type VisitableTokenTypes = | "ident" | "at-keyword" | "hash" | "id-hash" | "string" | "number" | "percentage" | "dimension"; declare type TokenVisitors = $ObjMapi< { [k: VisitableTokenTypes]: any }, <Name>(Name) => (token: FindByType<Token, Name>) => TokenReturnValue >; declare type FunctionVisitor = (fn: Function) => TokenReturnValue; declare type EnvironmentVariableVisitor = ( env: EnvironmentVariable ) => TokenReturnValue; declare type EnvironmentVariableVisitors = { [name: string]: EnvironmentVariableVisitor, }; export type Visitor<C: CustomAtRules> = {| StyleSheet?: ( stylesheet: StyleSheet ) => StyleSheet<ReturnedDeclaration, ReturnedMediaQuery> | void, StyleSheetExit?: ( stylesheet: StyleSheet ) => StyleSheet<ReturnedDeclaration, ReturnedMediaQuery> | void, Rule?: RuleVisitor<> | RuleVisitors<C>, RuleExit?: RuleVisitor<> | RuleVisitors<C>, Declaration?: DeclarationVisitor<> | DeclarationVisitors, DeclarationExit?: DeclarationVisitor<> | DeclarationVisitors, Url?: (url: Url) => Url | void, Color?: (color: CssColor) => CssColor | void, Image?: (image: Image) => Image | void, ImageExit?: (image: Image) => Image | void, Length?: (length: LengthValue) => LengthValue | void, Angle?: (angle: Angle) => Angle | void, Ratio?: (ratio: Ratio) => Ratio | void, Resolution?: (resolution: Resolution) => Resolution | void, Time?: (time: Time) => Time | void, CustomIdent?: (ident: string) => string | void, DashedIdent?: (ident: string) => string | void, MediaQuery?: ( query: MediaQuery ) => ReturnedMediaQuery | ReturnedMediaQuery[] | void, MediaQueryExit?: ( query: MediaQuery ) => ReturnedMediaQuery | ReturnedMediaQuery[] | void, SupportsCondition?: (condition: SupportsCondition) => SupportsCondition, SupportsConditionExit?: (condition: SupportsCondition) => SupportsCondition, Selector?: (selector: Selector) => Selector | Selector[] | void, Token?: TokenVisitor | TokenVisitors, Function?: | FunctionVisitor | { [name: string]: FunctionVisitor, }, FunctionExit?: | FunctionVisitor | { [name: string]: FunctionVisitor, }, Variable?: (variable: Variable) => TokenReturnValue, VariableExit?: (variable: Variable) => TokenReturnValue, EnvironmentVariable?: | EnvironmentVariableVisitor | EnvironmentVariableVisitors, EnvironmentVariableExit?: | EnvironmentVariableVisitor | EnvironmentVariableVisitors, |}; export type CustomAtRules = {| [name: string]: CustomAtRuleDefinition, |}; export type CustomAtRuleDefinition = {| /** * Defines the syntax for a custom at-rule prelude. The value should be a * CSS [syntax string](https://drafts.css-houdini.org/css-properties-values-api/#syntax-strings) * representing the types of values that are accepted. This property may be omitted or * set to null to indicate that no prelude is accepted. */ prelude?: SyntaxString | null, /** * Defines the type of body contained within the at-rule block. * - declaration-list: A CSS declaration list, as in a style rule. * - rule-list: A list of CSS rules, as supported within a non-nested * at-rule such as string. * - style-block: Both a declaration list and rule list, as accepted within * a nested at-rule within a style rule (e.g. string inside a style rule * with directly nested declarations). */ body?: "declaration-list" | "rule-list" | "style-block" | null, |}; export type DependencyOptions = {| /** * Whether to preserve string rules rather than removing them. */ preserveImports?: boolean, |}; export type BundleOptions<C: CustomAtRules> = $Diff< TransformOptions<C>, {| code: any |} >; export type BundleAsyncOptions<C: CustomAtRules> = {| ...$Exact<BundleOptions<C>>, resolver?: Resolver, |}; /** * Custom resolver to use when loading CSS files. */ export type Resolver = {| /** * Read the given file and return its contents as a string. */ read?: (file: string) => string | Promise<string>, /** * Resolve the given CSS import specifier from the provided originating file to a * path which gets passed to string. */ resolve?: ( specifier: string, originatingFile: string ) => string | Promise<string>, |}; export type Drafts = {| /** * Whether to enable @custom-media rules. */ customMedia?: boolean, |}; export type NonStandard = {| /** * Whether to enable the non-standard >>> and /deep/ selector combinators used by Angular and Vue. */ deepSelectorCombinator?: boolean, |}; export type PseudoClasses = {| hover?: string, active?: string, focus?: string, focusVisible?: string, focusWithin?: string, |}; export type TransformResult = {| /** * The transformed code. */ code: Uint8Array, /** * The generated source map, if enabled. */ map: Uint8Array | void, /** * CSS module exports, if enabled. */ exports: CSSModuleExports | void, /** * CSS module references, if string is enabled. */ references: CSSModuleReferences, /** * string dependencies, if enabled. */ dependencies: Dependency[] | void, /** * Warnings that occurred during compilation. */ warnings: Warning[], |}; export type Warning = {| message: string, type: string, value?: any, loc: ErrorLocation, |}; export type CSSModulesConfig = {| /** * The pattern to use when renaming class names and other identifiers. Default is string. */ pattern?: string, /** * Whether to rename dashed identifiers, e.g. custom properties. */ dashedIdents?: boolean, /** * Whether to enable hashing for string. */ animation?: boolean, /** * Whether to enable hashing for CSS grid identifiers. */ grid?: boolean, /** * Whether to enable hashing for string names. */ container?: boolean, /** * Whether to enable hashing for custom identifiers. */ customIdents?: boolean, /** * Whether to require at least one class or id selector in each rule. */ pure?: boolean, |}; export type CSSModuleExports = { /** * Maps exported (i.e. original) names to local names. */ [name: string]: CSSModuleExport, }; export type CSSModuleExport = {| /** * The local (compiled) name for this export. */ name: string, /** * Whether the export is referenced in this file. */ isReferenced: boolean, /** * Other names that are composed by this export. */ composes: CSSModuleReference[], |}; export type CSSModuleReferences = { /** * Maps placeholder names to references. */ [name: string]: DependencyCSSModuleReference, }; export type CSSModuleReference = | LocalCSSModuleReference | GlobalCSSModuleReference | DependencyCSSModuleReference; export type LocalCSSModuleReference = {| type: "local", /** * The local (compiled) name for the reference. */ name: string, |}; export type GlobalCSSModuleReference = {| type: "global", /** * The referenced global name. */ name: string, |}; export type DependencyCSSModuleReference = {| type: "dependency", /** * The name to reference within the dependency. */ name: string, /** * The dependency specifier for the referenced file. */ specifier: string, |}; export type Dependency = ImportDependency | UrlDependency; export type ImportDependency = {| type: "import", /** * The url of the string dependency. */ url: string, /** * The media query for the string rule. */ media: string | null, /** * The string rule. */ supports: string | null, /** * The source location where the string rule was found. */ loc: SourceLocation, /** * The placeholder that the import was replaced with. */ placeholder: string, |}; export type UrlDependency = {| type: "url", /** * The url of the dependency. */ url: string, /** * The source location where the string was found. */ loc: SourceLocation, /** * The placeholder that the url was replaced with. */ placeholder: string, |}; export type SourceLocation = {| /** * The file path in which the dependency exists. */ filePath: string, /** * The start location of the dependency. */ start: Location, /** * The end location (inclusive) of the dependency. */ end: Location, |}; export type Location = {| /** * The line number (1-based). */ line: number, /** * The column number (0-based). */ column: number, |}; export type ErrorLocation = {| ...$Exact<Location>, filename: string, |}; /** * Compiles a CSS file, including optionally minifying and lowering syntax to the given * targets. A source map may also be generated, but this is not enabled by default. */ declare export function transform<C: CustomAtRules>( options: TransformOptions<C> ): TransformResult; export type TransformAttributeOptions = {| /** * The filename in which the style attribute appeared. Used for error messages and dependencies. */ filename?: string, /** * The source code to transform. */ code: Uint8Array, /** * Whether to enable minification. */ minify?: boolean, /** * The browser targets for the generated code. */ targets?: Targets, /** * Whether to analyze string dependencies. * When enabled, string dependencies are replaced with hashed placeholders * that can be replaced with the final urls later (after bundling). * Dependencies are returned as part of the result. */ analyzeDependencies?: boolean, /** * Whether to ignore invalid rules and declarations rather than erroring. * When enabled, warnings are returned, and the invalid rule or declaration is * omitted from the output code. */ errorRecovery?: boolean, /** * An AST visitor object. This allows custom transforms or analysis to be implemented in JavaScript. * Multiple visitors can be composed into one using the string function. * For optimal performance, visitors should be as specific as possible about what types of values * they care about so that JavaScript has to be called as little as possible. */ visitor?: Visitor<empty>, |}; export type TransformAttributeResult = {| /** * The transformed code. */ code: Uint8Array, /** * string dependencies, if enabled. */ dependencies: Dependency[] | void, /** * Warnings that occurred during compilation. */ warnings: Warning[], |}; /** * Compiles a single CSS declaration list, such as an inline style attribute in HTML. */ declare export function transformStyleAttribute( options: TransformAttributeOptions ): TransformAttributeResult; /** * Converts a browserslist result into targets that can be passed to lightningcss. * @param browserslist the result of calling string */ declare export function browserslistToTargets(browserslist: string[]): Targets; /** * Bundles a CSS file and its dependencies, inlining @import rules. */ declare export function bundle<C: CustomAtRules>( options: BundleOptions<C> ): TransformResult; /** * Bundles a CSS file and its dependencies asynchronously, inlining @import rules. */ declare export function bundleAsync<C: CustomAtRules>( options: BundleAsyncOptions<C> ): Promise<TransformResult>; /** * Composes multiple visitor objects into a single one. */ declare export function composeVisitors<C: CustomAtRules>( visitors: Visitor<C>[] ): Visitor<C>;