/** * Core package of PurgeCSS * * Contains the core methods to analyze the files, remove unused CSS. * * @packageDocumentation */ import * as postcss from 'postcss'; /* Excluded from this release type: AtRules */ /** * @public */ export declare type ComplexSafelist = { standard?: StringRegExpArray; /** * You can safelist selectors and their children based on a regular * expression with `safelist.deep` * * @example * * ```ts * const purgecss = await new PurgeCSS().purge({ * content: [], * css: [], * safelist: { * deep: [/red$/] * } * }) * ``` * * In this example, selectors such as `.bg-red .child-of-bg` will be left * in the final CSS, even if `child-of-bg` is not found. * */ deep?: StringRegExpArray; /** * You can safelist whole selectors if any part of that selector matches a * pattern with `safelist.greedy` * * @example * * ```ts * const purgecss = await new PurgeCSS().purge({ * content: [], * css: [], * safelist: { * greedy: [/red$/] * } * }) * ``` * * In this example, selectors such as `button.bg-red.nonexistent-class` * will be left in the final CSS, even if `button` and `nonexistent-class` * are not found. * */ greedy?: StringRegExpArray; variables?: StringRegExpArray; keyframes?: StringRegExpArray; }; /** * Cache of the selectors extracted from content files, shared across * PurgeCSS instances. * * Integrations that run PurgeCSS many times with the same content, e.g. a * PostCSS plugin called once per CSS file or a bundler plugin in watch mode, * can set the same cache on every PurgeCSS instance they create with * {@link PurgeCSS.contentCache}. A content file is then only read and * extracted again when its modification time, change time, size, inode or * the extractor used for it changed. Runs at the same time share the files * being read and extracted: each file is extracted once. * * A file modified or changed (e.g. its modification time set back) less than * 2 seconds before it was read is extracted again on the next run, as a * modification within the precision of the file system timestamps would keep * the same modification and change times. * * The paths given to the methods are resolved from the current working * directory. * * Globs are still resolved on every run, so new files are picked up and * deleted files no longer contribute selectors. The entries of the files that * are no longer used stay in the cache until {@link ContentCache.prune}, * {@link ContentCache.delete} or {@link ContentCache.clear} is called. * * The extractors are called concurrently and in no particular order: they * must not depend on the order of the files or on a state kept between files. * * @example * ```ts * const contentCache = new ContentCache() * for (const css of cssFiles) { * const purgeCSS = new PurgeCSS() * purgeCSS.contentCache = contentCache * await purgeCSS.purge({ content: ['src/pages/*.html'], css: [css] }) * } * ``` * * @public */ export declare class ContentCache { private entries; /** * Strings of the selectors of the entries, one per distinct selector: the * files of a project share most of their selectors, which would otherwise * be kept once per file, each one keeping the whole content of its file * in memory. It holds the selectors of the files removed from the cache * too, until {@link ContentCache.clear}. */ private selectorsPool; /** * Number of files in the cache */ get size(): number; /** * Get the selectors of a file if they are still valid. The selectors may * still be being extracted by another run. * * @param filePath - path of the content file * @param stats - current stats of the file * @param extractor - extractor function used for the file * @returns the selectors extracted from the file, or `undefined` when the * file is not in the cache or changed since it was extracted */ get(filePath: string, stats: ContentFileStats, extractor: ExtractorFunction): Promise | undefined; /** * Store the selectors of a file. The entry is removed when its selectors * reject, or once they resolve when the file was modified or changed less * than 2 seconds before {@link ContentCacheEntry.checkedAt}. * * @param filePath - path of the content file * @param entry - selectors of the file and what they were extracted from */ set(filePath: string, entry: ContentCacheEntry): void; /** * Check if a file is in the cache, whether its entry is still valid or not * * @param filePath - path of the content file */ has(filePath: string): boolean; /** * Absolute paths of the files in the cache */ keys(): IterableIterator; /** * Remove a file from the cache * * @param filePath - path of the content file * @returns true if the file was in the cache */ delete(filePath: string): boolean; /** * Remove the files that are not in the given list, e.g. the files of a * previous build that the content globs no longer match * * @param filePaths - paths of the files to keep * @returns the number of files removed */ prune(filePaths: Iterable): number; /** * Remove all the files from the cache */ clear(): void; } /** * Selectors extracted from a content file, along with what they were * extracted from * * @public */ export declare interface ContentCacheEntry extends ContentFileStats { /** extractor function used to extract the selectors */ extractor: ExtractorFunction; /** * selectors extracted from the file. The promise is stored as soon as the * file starts being read, so that runs at the same time share the work. */ selectors: Promise; /** * time, `Date.now()`, right before the file was stat. When the file was * modified or changed less than 2 seconds before, the entry is only shared * while the file is being read and extracted, and is removed once it is * done. */ checkedAt: number; } /** * Information of `fs.Stats` that tells if a content file changed * * @public */ export declare interface ContentFileStats { /** modification time of the file, `fs.Stats.mtimeMs` */ mtimeMs: number; /** * change time of the file, `fs.Stats.ctimeMs`. Unlike the modification * time, it cannot be set back, e.g. by `touch -r` or a backup restore. */ ctimeMs: number; /** size of the file in bytes, `fs.Stats.size` */ size: number; /** inode number of the file, `fs.Stats.ino` */ ino: number; } /** * @public */ export declare const defaultOptions: Options; /** * @public */ export declare type ExtractorFunction = (content: T) => ExtractorResult; /** * @public */ export declare type ExtractorResult = ExtractorResultDetailed | string[]; /** * @public */ export declare interface ExtractorResultDetailed { attributes: { names: string[]; values: string[]; }; classes: string[]; ids: string[]; tags: string[]; undetermined: string[]; } /** * @public */ export declare class ExtractorResultSets { private undetermined; private attrNames; private attrValues; private classes; private ids; private tags; constructor(er: ExtractorResult); merge(that: ExtractorResult | ExtractorResultSets): this; hasAttrName(name: string): boolean; private someAttrValue; hasAttrPrefix(prefix: string): boolean; hasAttrSuffix(suffix: string): boolean; hasAttrSubstr(substr: string): boolean; hasAttrValue(value: string): boolean; hasClass(name: string): boolean; hasId(id: string): boolean; hasTag(tag: string): boolean; /* Excluded from this release type: internSelectors */ } /** * @public */ export declare interface Extractors { extensions: string[]; extractor: ExtractorFunction; } /* Excluded from this release type: IgnoreType */ /** * Check if a value matches a pattern of the options: a regular expression, * or a string written between slashes like "/^btn-/", is tested against the * value, any other string matches the value exactly * * @param pattern - string or regular expression * @param value - value to match, e.g. a selector or a variable name * * @public */ export declare function matchesPattern(pattern: string | RegExp, value: string): boolean; /** * Merge two extractor selectors * * @param extractorSelectorsA - extractor selectors A * @param extractorSelectorsB - extractor selectors B * @returns the merged extractor result sets * * @public */ export declare function mergeExtractorSelectors(...extractors: (ExtractorResultDetailed | ExtractorResultSets)[]): ExtractorResultSets; /** * Options used by PurgeCSS to remove unused CSS * Those options are used internally * @see {@link UserDefinedOptions} for the options defined by the user * * @public */ export declare interface Options { /** * You can specify content that should be analyzed by PurgeCSS with an * array of filenames or globs. The files can be HTML, Pug, Blade, etc. * * @example * * ```ts * await new PurgeCSS().purge({ * content: ['index.html', '*.js', '*.html', '*.vue'], * css: ['css/app.css'] * }) * ``` * * @example * PurgeCSS also works with raw content. To do this, you need to pass an * object with the `raw` property instead of a filename. To work properly * with custom extractors you need to pass the `extension` property along * with the raw content. * * ```ts * await new PurgeCSS().purge({ * content: [ * { * raw: '
', * extension: 'html' * }, * '*.js', * '*.html', * '*.vue' * ], * css: [ * { * raw: 'body { margin: 0 }' * }, * 'css/app.css' * ] * }) * ``` */ content: Array; /** * Similar to content, you can specify css that should be processed by * PurgeCSS with an array of filenames or globs */ css: Array; defaultExtractor: ExtractorFunction; extractors: Array; /** * If there are any unused \@font-face rules in your css, you can remove * them by setting the `fontFace` option to `true`. * * @defaultValue `false` * * @example * ```ts * await new PurgeCSS().purge({ * content: ['index.html', '*.js', '*.html', '*.vue'], * css: ['css/app.css'], * fontFace: true * }) * ``` */ fontFace: boolean; keyframes: boolean; output?: string; rejected: boolean; rejectedCss: boolean; /** {@inheritDoc postcss#SourceMapOptions} */ sourceMap: boolean | (postcss.SourceMapOptions & { to?: string; }); stdin: boolean; stdout: boolean; variables: boolean; /** * You can indicate which selectors are safe to leave in the final CSS. * This can be accomplished with the option safelist. */ safelist: Required; /** * Blocklist will block the CSS selectors from appearing in the final * output CSS. The selectors will be removed even when they are seen * as used by PurgeCSS. */ blocklist: StringRegExpArray; /** * If you provide globs for the content parameter, you can use this option * to exclude certain files or folders that would otherwise be scanned. * Pass an array of globs matching items that should be excluded. * (Note: this option has no effect if content is not globs.) */ skippedContentGlobs: Array; /** * Attributes that are set or changed at runtime, e.g. by JavaScript, and * therefore may not appear in the content files. Attribute selectors on * these attributes are kept whatever their value. Strings match the * attribute name exactly, regular expressions are tested against it. * * @example * ```ts * await new PurgeCSS().purge({ * content: ['index.html'], * css: ['css/app.css'], * dynamicAttributes: ['aria-selected', /^data-/] * }) * ``` */ dynamicAttributes: StringRegExpArray; } /** * @public */ export declare type PostCSSRoot = postcss.Root; /** * Class used to instantiate PurgeCSS and can then be used * to purge CSS files. * * @example * ```ts * await new PurgeCSS().purge({ * content: ['index.html'], * css: ['css/app.css'] * }) * ``` * * @public */ export declare class PurgeCSS { private ignore; private atRules; private usedAnimations; private usedFontFaces; selectorsRemoved: Set; removedNodes: postcss.Node[]; variablesStructure: VariablesStructure; options: Options; /** removals of nodes made during the walk through the css */ private removals; /** * Cache of the selectors extracted from the content files. When set, a * content file is only read and extracted again if it changed since the * cache got its selectors, see {@link ContentCache}. The same cache can be * set on several PurgeCSS instances, running one after the other or at the * same time. * * @defaultValue `undefined`, the content files are read on every run */ contentCache?: ContentCache; private collectDeclarationsData; /** * Collect the data of the declarations directly inside a node * * @param node - rule or at-rule of postcss AST * @param isIgnored - whether the node is kept by an ignore annotation */ private collectDeclarationsDataOfNode; /** * Check if a node is kept by an ignore annotation: inside an ignore range, * or right after an ignore next line comment, which is then removed * * @param node - node of postcss AST * @param index - index of the node in the children of its parent */ private isIgnored; /** * Get the extractor corresponding to the extension file * @param filename - Name of the file * @param extractors - Array of extractors definition */ private getFileExtractor; /** * Extract the selectors present in the files using a PurgeCSS extractor * * @param files - Array of files path or glob pattern * @param extractors - Array of extractors */ extractSelectorsFromFiles(files: string[], extractors: Extractors[]): Promise; /** * Extract the selectors present in a file, reusing the selectors of the * content cache when the file did not change * * @param file - path of the file * @param extractors - Array of extractors */ private extractSelectorsFromFile; /** * Extract the selectors present in the passed string using a PurgeCSS extractor * * @param content - Array of content * @param extractors - Array of extractors */ extractSelectorsFromString(content: RawContent[], extractors: Extractors[]): Promise; /** * Evaluate at-rule and register it for future reference * @param node - node of postcss AST * @param index - index of the node in the children of its parent */ private evaluateAtRule; /** * Evaluate css selector and decide if it should be removed or not * * @param node - node of postcss AST * @param index - index of the node in the children of its parent * @param selectors - selectors used in content files */ private evaluateRule; /** * Get the purged version of the css based on the files * * @param cssOptions - css options, files or raw strings * @param selectors - set of extracted css selectors */ getPurgedCSS(cssOptions: Array, selectors: ExtractorResultSets): Promise; /** * Build the result of a purged css file * * @param purgedRoot - purged css file */ private getResultPurge; /** * Check if the keyframe is safelisted with the option safelist keyframes * * @param keyframesName - name of the keyframe animation */ private isKeyframesSafelisted; /** * Check if the selector is blocklisted with the option blocklist * * @param selector - css selector */ private isSelectorBlocklisted; /** * Check if the selector is safelisted with the option safelist standard * * @param selector - css selector */ private isSelectorSafelisted; /** * Check if the selector is safelisted with the option safelist deep * * @param selector - selector */ private isSelectorSafelistedDeep; /** * Check if the selector is safelisted with the option safelist greedy * * @param selector - selector */ private isSelectorSafelistedGreedy; /** * Check if the attribute is dynamic, i.e. it can be set or changed at runtime. * Attribute selectors on dynamic attributes are always kept, whatever their * value, as the attribute may not appear in the content files. * * `value` is highly used in input elements and can change based on the user, * idem for `checked`, `selected` and `open`, so they are always dynamic. * Other attributes can be added with the option dynamicAttributes. * * @param attributeName - name of the attribute, e.g. `aria-selected` */ private isAttributeDynamic; /** * Remove unused CSS * * @param userOptions - PurgeCSS options or path to the configuration file * @returns an array of object containing the filename and the associated CSS * * @example Using a configuration file named purgecss.config.js * ```ts * const purgeCSSResults = await new PurgeCSS().purge() * ``` * * @example Using a custom path to the configuration file * ```ts * const purgeCSSResults = await new PurgeCSS().purge('./purgecss.config.js') * ``` * * @example Using the PurgeCSS options * ```ts * const purgeCSSResults = await new PurgeCSS().purge({ * content: ['index.html', '**\/*.js', '**\/*.html', '**\/*.vue'], * css: ['css/app.css'] * }) * ``` */ purge(userOptions: UserDefinedOptions | string | undefined): Promise; /** * Remove unused CSS variables */ removeUnusedCSSVariables(): void; /** * Remove unused font-faces */ removeUnusedFontFaces(): void; /** * Remove unused keyframes */ removeUnusedKeyframes(): void; /** * Transform a selector node into a string */ private getSelectorValue; /** * Determine if the selector should be kept, based on the selectors found in the files * * @param selector - set of css selectors found in the content files or string * @param selectorsFromExtractor - selectors in the css rule * * @returns true if the selector should be kept in the processed CSS */ private shouldKeepSelector; /** * Walk through the CSS AST and remove unused CSS * * @param root - root node of the postcss AST * @param selectors - selectors used in content files */ walkThroughCSS(root: PostCSSRoot, selectors: ExtractorResultSets): void; } /** * @public */ export declare interface RawContent { extension: string; raw: T; } /** * @public */ export declare interface RawCSS { /** css to purge */ raw: string; /** * name of the css, returned as the `file` of its result. It is used as the * path of the css in source maps, like the path of a css file: the map * `sources` are relative to the directory of `sourceMap.to`, which * defaults to the name. */ name?: string; } /** * @public */ export declare interface ResultPurge { css: string; /** * sourceMap property will be empty if * {@link UserDefinedOptions.sourceMap} inline is not set to false, as the * source map will be contained within the text of ResultPurge.css */ sourceMap?: string; rejectedCss?: string; file?: string; rejected?: string[]; } /** * Load the configuration file from the path * * @param configFile - Path of the config file * @returns The options from the configuration file * * @throws Error * This exception is thrown if the configuration file was not imported * * @public */ export declare function setOptions(configFile?: string): Promise; /** * Format the user defined safelist into a standardized safelist object * * @param userDefinedSafelist - the user defined safelist * @returns the formatted safelist object that can be used in the PurgeCSS options * * @public */ export declare function standardizeSafelist(userDefinedSafelist?: UserDefinedSafelist): Required; /** * Strings and regular expressions an option is matched against. A string * matches a value exactly, except a string written between slashes, like * `"/^btn-/"` or `"/^btn-/i"`, which is parsed as a regular expression. This * form lets configuration files that cannot contain regular expressions, such * as `postcss.config.json`, use patterns. * * @public */ export declare type StringRegExpArray = Array; /** * Options used by PurgeCSS to remove unused CSS * * @public */ export declare interface UserDefinedOptions { /** {@inheritDoc purgecss#Options.content} */ content: Array; /** {@inheritDoc purgecss#Options.css} */ css: Array; /** {@inheritDoc purgecss#Options.defaultExtractor} */ defaultExtractor?: ExtractorFunction; /** {@inheritDoc purgecss#Options.extractors} */ extractors?: Array; /** {@inheritDoc purgecss#Options.fontFace} */ fontFace?: boolean; /** {@inheritDoc purgecss#Options.keyframes} */ keyframes?: boolean; /** {@inheritDoc purgecss#Options.output} */ output?: string; /** {@inheritDoc purgecss#Options.rejected} */ rejected?: boolean; /** {@inheritDoc purgecss#Options.rejectedCss} */ rejectedCss?: boolean; /** {@inheritDoc purgecss#Options.sourceMap } */ sourceMap?: boolean | (postcss.SourceMapOptions & { to?: string; }); /** {@inheritDoc purgecss#Options.stdin} */ stdin?: boolean; /** {@inheritDoc purgecss#Options.stdout} */ stdout?: boolean; /** {@inheritDoc purgecss#Options.variables} */ variables?: boolean; /** {@inheritDoc purgecss#Options.safelist} */ safelist?: UserDefinedSafelist; /** {@inheritDoc purgecss#Options.blocklist} */ blocklist?: StringRegExpArray; /** {@inheritDoc purgecss#Options.skippedContentGlobs} */ skippedContentGlobs?: Array; /** {@inheritDoc purgecss#Options.dynamicAttributes} */ dynamicAttributes?: StringRegExpArray; } /** * @public */ export declare type UserDefinedSafelist = StringRegExpArray | ComplexSafelist; /** * @public */ export declare class VariableNode { /** * @deprecated The dependencies between declarations are no longer * recorded, so this list is always empty. The variables used by a used * variable are found by name in `VariablesStructure.removeUnused`. It will * be removed in the next major version. */ nodes: VariableNode[]; value: postcss.Declaration; isUsed: boolean; constructor(declaration: postcss.Declaration); } /** * @public */ export declare class VariablesStructure { nodes: Map; properties: Map; usedVariables: Set; safelist: StringRegExpArray; addVariable(declaration: postcss.Declaration): void; /** * Register an `@property` at-rule so it can be removed along with the * declarations of the variable it defines * * @param atRule - `@property` at-rule */ addProperty(atRule: postcss.AtRule): void; /** * @deprecated The variables used by a custom property are found by name in * `removeUnused`, so the dependencies between declarations are no longer * recorded and this method does nothing. It will be removed in the next * major version. */ addVariableUsage(declaration: postcss.Declaration, matchedVariables: IterableIterator): void; addVariableUsageInProperties(matchedVariables: IterableIterator): void; /** * Mark every declaration of the variable as used. The variables it uses are * not marked, `removeUnused` adds them to the used variables first. * * @param variableName - name of the variable, e.g. `--color` */ setAsUsed(variableName: string): void; removeUnused(): void; isVariablesSafelisted(variable: string): boolean; } export { }