Socket
Socket
Sign inDemoInstall

purgecss

Package Overview
Dependencies
24
Maintainers
2
Versions
62
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.2.1 to 2.3.0

LICENSE

6

lib/purgecss.d.ts
import * as postcss from "postcss";
interface RawContent {
interface RawContent<T = string> {
extension: string;
raw: string;
raw: T;
}

@@ -20,3 +20,3 @@ interface RawCSS {

type ExtractorResult = ExtractorResultDetailed | string[];
type ExtractorFunction = (content: string) => ExtractorResult;
type ExtractorFunction<T = string> = (content: T) => ExtractorResult;
interface Extractors {

@@ -23,0 +23,0 @@ extensions: string[];

import * as postcss from "postcss";
interface RawContent {
interface RawContent<T = string> {
extension: string;
raw: string;
raw: T;
}

@@ -20,3 +20,3 @@ interface RawCSS {

type ExtractorResult = ExtractorResultDetailed | string[];
type ExtractorFunction = (content: string) => ExtractorResult;
type ExtractorFunction<T = string> = (content: T) => ExtractorResult;
interface Extractors {

@@ -23,0 +23,0 @@ extensions: string[];

@@ -1,1 +0,1 @@

import{parse as t}from"postcss";import e from"postcss-selector-parser";import{access as s,readFile as r,constants as i}from"fs";import{promisify as n}from"util";import a from"glob";import o from"path";const c={css:[],content:[],defaultExtractor:t=>t.match(/[A-Za-z0-9_-]+/g)||[],extractors:[],fontFace:!1,keyframes:!1,rejected:!1,stdin:!1,stdout:!1,variables:!1,whitelist:[],whitelistPatterns:[],whitelistPatternsChildren:[]},u=["*","::-webkit-scrollbar","::selection",":root","::before","::after"];class h{constructor(t){this.nodes=[],this.isUsed=!1,this.value=t}}class l{constructor(){this.nodes=new Map,this.usedVariables=new Set}addVariable(t){const{prop:e}=t;if(!this.nodes.has(e)){const s=new h(t);this.nodes.set(e,s)}}addVariableUsage(t,e){const{prop:s}=t,r=this.nodes.get(s);for(const t of e){const e=t[1];if(this.nodes.has(e)){const t=this.nodes.get(e);null==r||r.nodes.push(t)}}}addVariableUsageInProperties(t){for(const e of t){const t=e[1];this.usedVariables.add(t)}}setAsUsed(t){const e=[this.nodes.get(t)];for(;0!==e.length;){const t=e.pop();t&&!t.isUsed&&(t.isUsed=!0,e.push(...t.nodes))}}removeUnused(){for(const t of this.usedVariables)this.setAsUsed(t);for(const[,t]of this.nodes)t.isUsed||t.value.remove()}}function d(t,e){e&&e.forEach(t.add,t)}class f{constructor(t){this.undetermined=new Set,this.attrNames=new Set,this.attrValues=new Set,this.classes=new Set,this.ids=new Set,this.tags=new Set,this.merge(t)}merge(t){return Array.isArray(t)?d(this.undetermined,t):t instanceof f?(d(this.undetermined,t.undetermined),d(this.attrNames,t.attrNames),d(this.attrValues,t.attrValues),d(this.classes,t.classes),d(this.ids,t.ids),d(this.tags,t.tags)):(d(this.undetermined,t.undetermined),t.attributes&&(d(this.attrNames,t.attributes.names),d(this.attrValues,t.attributes.values)),d(this.classes,t.classes),d(this.ids,t.ids),d(this.tags,t.tags)),this}hasAttrName(t){return this.attrNames.has(t)||this.undetermined.has(t)}someAttrValue(t){for(const e of this.attrValues)if(t(e))return!0;for(const e of this.undetermined)if(t(e))return!0;return!1}hasAttrPrefix(t){return this.someAttrValue(e=>e.startsWith(t))}hasAttrSuffix(t){return this.someAttrValue(e=>e.endsWith(t))}hasAttrSubstr(t){return this.someAttrValue(e=>e.includes(t))}hasAttrValue(t){return this.attrValues.has(t)||this.undetermined.has(t)}hasClass(t){return this.classes.has(t)||this.undetermined.has(t)}hasId(t){return this.ids.has(t)||this.undetermined.has(t)}hasTag(t){return this.tags.has(t)||this.undetermined.has(t)}}const m={access:n(s),readFile:n(r)};async function p(t="purgecss.config.js"){let e;try{const s=o.join(process.cwd(),t);e=await import(s)}catch(t){throw new Error(`Error loading the config file ${t.message}`)}return{...c,...e}}async function g(t,e){return new f(await e(t))}function v(t,e){switch(e){case"next":return t.text.includes("purgecss ignore");case"start":return t.text.includes("purgecss start ignore");case"end":return t.text.includes("purgecss end ignore")}}function y(...t){const e=new f([]);return t.forEach(e.merge,e),e}function w(t){return t.replace(/(^["'])|(["']$)/g,"")}function S(t,e){if(!e.hasAttrName(t.attribute))return!1;if(void 0===t.value)return!0;switch(t.operator){case"$=":return e.hasAttrSuffix(t.value);case"~=":case"*=":return e.hasAttrSubstr(t.value);case"=":return e.hasAttrValue(t.value);case"|=":case"^=":return e.hasAttrPrefix(t.value);default:return!0}}function b(t,e){return e.hasId(t.value)}function F(t,e){return e.hasTag(t.value)}class x{constructor(){this.ignore=!1,this.atRules={fontFace:[],keyframes:[]},this.usedAnimations=new Set,this.usedFontFaces=new Set,this.selectorsRemoved=new Set,this.variablesStructure=new l,this.options=c}collectDeclarationsData(t){const{prop:e,value:s}=t;if(this.options.variables){const r=function(t,e){const s=[];return t.replace(e,(function(){const e=arguments,r=Array.prototype.slice.call(e,0,-2);return r.input=e[e.length-1],r.index=e[e.length-2],s.push(r),t})),s}(s,/var\((.+?)[,)]/g);e.startsWith("--")?(this.variablesStructure.addVariable(t),r.length>0&&this.variablesStructure.addVariableUsage(t,r)):r.length>0&&this.variablesStructure.addVariableUsageInProperties(r)}if(!this.options.keyframes||"animation"!==e&&"animation-name"!==e)if(this.options.fontFace){if("font-family"===e)for(const t of s.split(",")){const e=w(t.trim());this.usedFontFaces.add(e)}}else;else for(const t of s.split(/[\s,]+/))this.usedAnimations.add(t)}getFileExtractor(t,e){const s=e.find(e=>e.extensions.find(e=>t.endsWith(e)));return void 0===s?this.options.defaultExtractor:s.extractor}async extractSelectorsFromFiles(t,e){const s=new f([]);for(const r of t){let t=[];try{await m.access(r,i.F_OK),t.push(r)}catch(e){t=a.sync(r)}for(const r of t){const t=await m.readFile(r,"utf-8"),i=this.getFileExtractor(r,e),n=await g(t,i);s.merge(n)}}return s}async extractSelectorsFromString(t,e){const s=new f([]);for(const{raw:r,extension:i}of t){const t=this.getFileExtractor(`.${i}`,e),n=await g(r,t);s.merge(n)}return s}evaluateAtRule(t){if(this.options.keyframes&&t.name.endsWith("keyframes"))this.atRules.keyframes.push(t);else if(this.options.fontFace&&"font-face"===t.name&&t.nodes)for(const e of t.nodes)"decl"===e.type&&"font-family"===e.prop&&this.atRules.fontFace.push({name:w(e.value),node:t})}async evaluateRule(t,s){if(this.ignore)return;const r=t.prev();if(r&&"comment"===r.type&&v(r,"next"))return void r.remove();if(t.parent&&"atrule"===t.parent.type&&"keyframes"===t.parent.name)return;if("rule"!==t.type)return;if(function(t){let e=!1;return t.walkComments(t=>{t&&"comment"===t.type&&t.text.includes("purgecss ignore current")&&(e=!0,t.remove())}),e}(t))return;let i=!0;if(t.selector=e(t=>{t.walk(t=>{"selector"===t.type&&(i=this.shouldKeepSelector(t,s),i||(this.options.rejected&&this.selectorsRemoved.add(t.toString()),t.remove()))})}).processSync(t.selector),i&&void 0!==t.nodes)for(const e of t.nodes)"decl"===e.type&&this.collectDeclarationsData(e);const n=t.parent;t.selector||t.remove(),function(t){return!!("rule"===t.type&&!t.selector||t.nodes&&!t.nodes.length||"atrule"===t.type&&(!t.nodes&&!t.params||!t.params&&t.nodes&&!t.nodes.length))}(n)&&n.remove()}async getPurgedCSS(e,s){const r=[],i=[];for(const t of e)"string"==typeof t?i.push(...a.sync(t)):i.push(t);for(const e of i){const i="string"==typeof e?this.options.stdin?e:await m.readFile(e,"utf-8"):e.raw,n=t(i);this.walkThroughCSS(n,s),this.options.fontFace&&this.removeUnusedFontFaces(),this.options.keyframes&&this.removeUnusedKeyframes(),this.options.variables&&this.removeUnusedCSSVariables();const a={css:n.toString(),file:"string"==typeof e?e:void 0};"string"==typeof e&&(a.file=e),this.options.rejected&&(a.rejected=Array.from(this.selectorsRemoved),this.selectorsRemoved.clear()),r.push(a)}return r}isSelectorWhitelisted(t){return u.includes(t)||this.options.whitelist&&this.options.whitelist.some(e=>e===t)||this.options.whitelistPatterns&&this.options.whitelistPatterns.some(e=>e.test(t))}isSelectorWhitelistedChildren(t){return this.options.whitelistPatternsChildren&&this.options.whitelistPatternsChildren.some(e=>e.test(t))}async purge(t){this.options="object"!=typeof t?await p(t):{...c,...t};const{content:e,css:s,extractors:r}=this.options,i=e.filter(t=>"string"==typeof t),n=e.filter(t=>"object"==typeof t),a=await this.extractSelectorsFromFiles(i,r),o=await this.extractSelectorsFromString(n,r);return this.getPurgedCSS(s,y(a,o))}removeUnusedCSSVariables(){this.variablesStructure.removeUnused()}removeUnusedFontFaces(){for(const{name:t,node:e}of this.atRules.fontFace)this.usedFontFaces.has(t)||e.remove()}removeUnusedKeyframes(){for(const t of this.atRules.keyframes)this.usedAnimations.has(t.params)||t.remove()}shouldKeepSelector(t,e){if(function(t){return t.parent&&"pseudo"===t.parent.type&&t.parent.value.startsWith(":")||!1}(t))return!0;let s=!1;for(const i of t.nodes){const t="attribute"===i.type&&i.attribute||i.value;if(t&&this.isSelectorWhitelistedChildren(t))return!0;if(t&&(u.includes(t)||this.isSelectorWhitelisted(t)))s=!0;else{switch(i.type){case"attribute":s=!!["value","checked","selected","open"].includes(i.attribute)||S(i,e);break;case"class":r=i,s=e.hasClass(r.value);break;case"id":s=b(i,e);break;case"tag":s=F(i,e)}if(!s)return!1}}var r;return s}walkThroughCSS(t,e){t.walk(t=>"rule"===t.type?this.evaluateRule(t,e):"atrule"===t.type?this.evaluateAtRule(t):void("comment"===t.type&&(v(t,"start")?(this.ignore=!0,t.remove()):v(t,"end")&&(this.ignore=!1,t.remove()))))}}export default x;export{x as PurgeCSS,c as defaultOptions,y as mergeExtractorSelectors,p as setOptions};
import{parse as t}from"postcss";import e from"postcss-selector-parser";import{access as s,readFile as r,constants as i}from"fs";import{promisify as n}from"util";import o from"glob";import a from"path";const c={css:[],content:[],defaultExtractor:t=>t.match(/[A-Za-z0-9_-]+/g)||[],extractors:[],fontFace:!1,keyframes:!1,rejected:!1,stdin:!1,stdout:!1,variables:!1,whitelist:[],whitelistPatterns:[],whitelistPatternsChildren:[]},u=["*","::-webkit-scrollbar","::selection",":root","::before","::after"];class h{constructor(t){this.nodes=[],this.isUsed=!1,this.value=t}}class l{constructor(){this.nodes=new Map,this.usedVariables=new Set}addVariable(t){const{prop:e}=t;if(!this.nodes.has(e)){const s=new h(t);this.nodes.set(e,s)}}addVariableUsage(t,e){const{prop:s}=t,r=this.nodes.get(s);for(const t of e){const e=t[1];if(this.nodes.has(e)){const t=this.nodes.get(e);null==r||r.nodes.push(t)}}}addVariableUsageInProperties(t){for(const e of t){const t=e[1];this.usedVariables.add(t)}}setAsUsed(t){const e=[this.nodes.get(t)];for(;0!==e.length;){const t=e.pop();t&&!t.isUsed&&(t.isUsed=!0,e.push(...t.nodes))}}removeUnused(){for(const t of this.usedVariables)this.setAsUsed(t);for(const[,t]of this.nodes)t.isUsed||t.value.remove()}}function d(t,e){e&&e.forEach(t.add,t)}class f{constructor(t){this.undetermined=new Set,this.attrNames=new Set,this.attrValues=new Set,this.classes=new Set,this.ids=new Set,this.tags=new Set,this.merge(t)}merge(t){return Array.isArray(t)?d(this.undetermined,t):t instanceof f?(d(this.undetermined,t.undetermined),d(this.attrNames,t.attrNames),d(this.attrValues,t.attrValues),d(this.classes,t.classes),d(this.ids,t.ids),d(this.tags,t.tags)):(d(this.undetermined,t.undetermined),t.attributes&&(d(this.attrNames,t.attributes.names),d(this.attrValues,t.attributes.values)),d(this.classes,t.classes),d(this.ids,t.ids),d(this.tags,t.tags)),this}hasAttrName(t){return this.attrNames.has(t)||this.undetermined.has(t)}someAttrValue(t){for(const e of this.attrValues)if(t(e))return!0;for(const e of this.undetermined)if(t(e))return!0;return!1}hasAttrPrefix(t){return this.someAttrValue(e=>e.startsWith(t))}hasAttrSuffix(t){return this.someAttrValue(e=>e.endsWith(t))}hasAttrSubstr(t){return this.someAttrValue(e=>e.includes(t))}hasAttrValue(t){return this.attrValues.has(t)||this.undetermined.has(t)}hasClass(t){return this.classes.has(t)||this.undetermined.has(t)}hasId(t){return this.ids.has(t)||this.undetermined.has(t)}hasTag(t){return this.tags.has(t)||this.undetermined.has(t)}}const m={access:n(s),readFile:n(r)};async function p(t="purgecss.config.js"){let e;try{const s=a.join(process.cwd(),t);e=await import(s)}catch(t){throw new Error(`Error loading the config file ${t.message}`)}return{...c,...e}}async function g(t,e){return new f(await e(t))}function v(t,e){switch(e){case"next":return t.text.includes("purgecss ignore");case"start":return t.text.includes("purgecss start ignore");case"end":return t.text.includes("purgecss end ignore")}}function y(...t){const e=new f([]);return t.forEach(e.merge,e),e}function w(t){return t.replace(/(^["'])|(["']$)/g,"")}function S(t,e){if(!e.hasAttrName(t.attribute))return!1;if(void 0===t.value)return!0;switch(t.operator){case"$=":return e.hasAttrSuffix(t.value);case"~=":case"*=":return e.hasAttrSubstr(t.value);case"=":return e.hasAttrValue(t.value);case"|=":case"^=":return e.hasAttrPrefix(t.value);default:return!0}}function b(t,e){return e.hasId(t.value)}function F(t,e){return e.hasTag(t.value)}class x{constructor(){this.ignore=!1,this.atRules={fontFace:[],keyframes:[]},this.usedAnimations=new Set,this.usedFontFaces=new Set,this.selectorsRemoved=new Set,this.variablesStructure=new l,this.options=c}collectDeclarationsData(t){const{prop:e,value:s}=t;if(this.options.variables){const r=function(t,e){const s=[];return t.replace(e,(function(){const e=arguments,r=Array.prototype.slice.call(e,0,-2);return r.input=e[e.length-1],r.index=e[e.length-2],s.push(r),t})),s}(s,/var\((.+?)[,)]/g);e.startsWith("--")?(this.variablesStructure.addVariable(t),r.length>0&&this.variablesStructure.addVariableUsage(t,r)):r.length>0&&this.variablesStructure.addVariableUsageInProperties(r)}if(!this.options.keyframes||"animation"!==e&&"animation-name"!==e)if(this.options.fontFace){if("font-family"===e)for(const t of s.split(",")){const e=w(t.trim());this.usedFontFaces.add(e)}}else;else for(const t of s.split(/[\s,]+/))this.usedAnimations.add(t)}getFileExtractor(t,e){const s=e.find(e=>e.extensions.find(e=>t.endsWith(e)));return void 0===s?this.options.defaultExtractor:s.extractor}async extractSelectorsFromFiles(t,e){const s=new f([]);for(const r of t){let t=[];try{await m.access(r,i.F_OK),t.push(r)}catch(e){t=o.sync(r,{nodir:!0})}for(const r of t){const t=await m.readFile(r,"utf-8"),i=this.getFileExtractor(r,e),n=await g(t,i);s.merge(n)}}return s}async extractSelectorsFromString(t,e){const s=new f([]);for(const{raw:r,extension:i}of t){const t=this.getFileExtractor(`.${i}`,e),n=await g(r,t);s.merge(n)}return s}evaluateAtRule(t){if(this.options.keyframes&&t.name.endsWith("keyframes"))this.atRules.keyframes.push(t);else if(this.options.fontFace&&"font-face"===t.name&&t.nodes)for(const e of t.nodes)"decl"===e.type&&"font-family"===e.prop&&this.atRules.fontFace.push({name:w(e.value),node:t})}async evaluateRule(t,s){if(this.ignore)return;const r=t.prev();if(r&&"comment"===r.type&&v(r,"next"))return void r.remove();if(t.parent&&"atrule"===t.parent.type&&"keyframes"===t.parent.name)return;if("rule"!==t.type)return;if(function(t){let e=!1;return t.walkComments(t=>{t&&"comment"===t.type&&t.text.includes("purgecss ignore current")&&(e=!0,t.remove())}),e}(t))return;let i=!0;if(t.selector=e(t=>{t.walk(t=>{"selector"===t.type&&(i=this.shouldKeepSelector(t,s),i||(this.options.rejected&&this.selectorsRemoved.add(t.toString()),t.remove()))})}).processSync(t.selector),i&&void 0!==t.nodes)for(const e of t.nodes)"decl"===e.type&&this.collectDeclarationsData(e);const n=t.parent;t.selector||t.remove(),function(t){return!!("rule"===t.type&&!t.selector||t.nodes&&!t.nodes.length||"atrule"===t.type&&(!t.nodes&&!t.params||!t.params&&t.nodes&&!t.nodes.length))}(n)&&n.remove()}async getPurgedCSS(e,s){const r=[],i=[];for(const t of e)"string"==typeof t?i.push(...o.sync(t,{nodir:!0})):i.push(t);for(const e of i){const i="string"==typeof e?this.options.stdin?e:await m.readFile(e,"utf-8"):e.raw,n=t(i);this.walkThroughCSS(n,s),this.options.fontFace&&this.removeUnusedFontFaces(),this.options.keyframes&&this.removeUnusedKeyframes(),this.options.variables&&this.removeUnusedCSSVariables();const o={css:n.toString(),file:"string"==typeof e?e:void 0};"string"==typeof e&&(o.file=e),this.options.rejected&&(o.rejected=Array.from(this.selectorsRemoved),this.selectorsRemoved.clear()),r.push(o)}return r}isSelectorWhitelisted(t){return u.includes(t)||this.options.whitelist&&this.options.whitelist.some(e=>e===t)||this.options.whitelistPatterns&&this.options.whitelistPatterns.some(e=>e.test(t))}isSelectorWhitelistedChildren(t){return this.options.whitelistPatternsChildren&&this.options.whitelistPatternsChildren.some(e=>e.test(t))}async purge(t){this.options="object"!=typeof t?await p(t):{...c,...t};const{content:e,css:s,extractors:r}=this.options,i=e.filter(t=>"string"==typeof t),n=e.filter(t=>"object"==typeof t),o=await this.extractSelectorsFromFiles(i,r),a=await this.extractSelectorsFromString(n,r);return this.getPurgedCSS(s,y(o,a))}removeUnusedCSSVariables(){this.variablesStructure.removeUnused()}removeUnusedFontFaces(){for(const{name:t,node:e}of this.atRules.fontFace)this.usedFontFaces.has(t)||e.remove()}removeUnusedKeyframes(){for(const t of this.atRules.keyframes)this.usedAnimations.has(t.params)||t.remove()}shouldKeepSelector(t,e){if(function(t){return t.parent&&"pseudo"===t.parent.type&&t.parent.value.startsWith(":")||!1}(t))return!0;let s=!1;for(const i of t.nodes){const t="attribute"===i.type&&i.attribute||i.value;if(t&&this.isSelectorWhitelistedChildren(t))return!0;if(t&&(u.includes(t)||this.isSelectorWhitelisted(t)))s=!0;else{switch(i.type){case"attribute":s=!!["value","checked","selected","open"].includes(i.attribute)||S(i,e);break;case"class":r=i,s=e.hasClass(r.value);break;case"id":s=b(i,e);break;case"tag":s=F(i,e)}if(!s)return!1}}var r;return s}walkThroughCSS(t,e){t.walk(t=>"rule"===t.type?this.evaluateRule(t,e):"atrule"===t.type?this.evaluateAtRule(t):void("comment"===t.type&&(v(t,"start")?(this.ignore=!0,t.remove()):v(t,"end")&&(this.ignore=!1,t.remove()))))}}export default x;export{x as PurgeCSS,c as defaultOptions,y as mergeExtractorSelectors,p as setOptions};

@@ -1,1 +0,1 @@

"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("postcss"),s=e(require("postcss-selector-parser")),r=require("fs"),i=require("util"),n=e(require("glob")),a=e(require("path"));const o={css:[],content:[],defaultExtractor:e=>e.match(/[A-Za-z0-9_-]+/g)||[],extractors:[],fontFace:!1,keyframes:!1,rejected:!1,stdin:!1,stdout:!1,variables:!1,whitelist:[],whitelistPatterns:[],whitelistPatternsChildren:[]},c=["*","::-webkit-scrollbar","::selection",":root","::before","::after"];class u{constructor(e){this.nodes=[],this.isUsed=!1,this.value=e}}class l{constructor(){this.nodes=new Map,this.usedVariables=new Set}addVariable(e){const{prop:t}=e;if(!this.nodes.has(t)){const s=new u(e);this.nodes.set(t,s)}}addVariableUsage(e,t){const{prop:s}=e,r=this.nodes.get(s);for(const e of t){const t=e[1];if(this.nodes.has(t)){const e=this.nodes.get(t);null==r||r.nodes.push(e)}}}addVariableUsageInProperties(e){for(const t of e){const e=t[1];this.usedVariables.add(e)}}setAsUsed(e){const t=[this.nodes.get(e)];for(;0!==t.length;){const e=t.pop();e&&!e.isUsed&&(e.isUsed=!0,t.push(...e.nodes))}}removeUnused(){for(const e of this.usedVariables)this.setAsUsed(e);for(const[,e]of this.nodes)e.isUsed||e.value.remove()}}function h(e,t){t&&t.forEach(e.add,e)}class d{constructor(e){this.undetermined=new Set,this.attrNames=new Set,this.attrValues=new Set,this.classes=new Set,this.ids=new Set,this.tags=new Set,this.merge(e)}merge(e){return Array.isArray(e)?h(this.undetermined,e):e instanceof d?(h(this.undetermined,e.undetermined),h(this.attrNames,e.attrNames),h(this.attrValues,e.attrValues),h(this.classes,e.classes),h(this.ids,e.ids),h(this.tags,e.tags)):(h(this.undetermined,e.undetermined),e.attributes&&(h(this.attrNames,e.attributes.names),h(this.attrValues,e.attributes.values)),h(this.classes,e.classes),h(this.ids,e.ids),h(this.tags,e.tags)),this}hasAttrName(e){return this.attrNames.has(e)||this.undetermined.has(e)}someAttrValue(e){for(const t of this.attrValues)if(e(t))return!0;for(const t of this.undetermined)if(e(t))return!0;return!1}hasAttrPrefix(e){return this.someAttrValue(t=>t.startsWith(e))}hasAttrSuffix(e){return this.someAttrValue(t=>t.endsWith(e))}hasAttrSubstr(e){return this.someAttrValue(t=>t.includes(e))}hasAttrValue(e){return this.attrValues.has(e)||this.undetermined.has(e)}hasClass(e){return this.classes.has(e)||this.undetermined.has(e)}hasId(e){return this.ids.has(e)||this.undetermined.has(e)}hasTag(e){return this.tags.has(e)||this.undetermined.has(e)}}const f={access:i.promisify(r.access),readFile:i.promisify(r.readFile)};async function p(e="purgecss.config.js"){let t;try{const s=a.join(process.cwd(),e);t=await new Promise((function(e){e(function(e){if(e&&e.__esModule)return e;var t={};return e&&Object.keys(e).forEach((function(s){var r=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,r.get?r:{enumerable:!0,get:function(){return e[s]}})})),t.default=e,t}(require(s)))}))}catch(e){throw new Error(`Error loading the config file ${e.message}`)}return{...o,...t}}async function m(e,t){return new d(await t(e))}function g(e,t){switch(t){case"next":return e.text.includes("purgecss ignore");case"start":return e.text.includes("purgecss start ignore");case"end":return e.text.includes("purgecss end ignore")}}function v(...e){const t=new d([]);return e.forEach(t.merge,t),t}function y(e){return e.replace(/(^["'])|(["']$)/g,"")}function w(e,t){if(!t.hasAttrName(e.attribute))return!1;if(void 0===e.value)return!0;switch(e.operator){case"$=":return t.hasAttrSuffix(e.value);case"~=":case"*=":return t.hasAttrSubstr(e.value);case"=":return t.hasAttrValue(e.value);case"|=":case"^=":return t.hasAttrPrefix(e.value);default:return!0}}function S(e,t){return t.hasId(e.value)}function b(e,t){return t.hasTag(e.value)}class x{constructor(){this.ignore=!1,this.atRules={fontFace:[],keyframes:[]},this.usedAnimations=new Set,this.usedFontFaces=new Set,this.selectorsRemoved=new Set,this.variablesStructure=new l,this.options=o}collectDeclarationsData(e){const{prop:t,value:s}=e;if(this.options.variables){const r=function(e,t){const s=[];return e.replace(t,(function(){const t=arguments,r=Array.prototype.slice.call(t,0,-2);return r.input=t[t.length-1],r.index=t[t.length-2],s.push(r),e})),s}(s,/var\((.+?)[,)]/g);t.startsWith("--")?(this.variablesStructure.addVariable(e),r.length>0&&this.variablesStructure.addVariableUsage(e,r)):r.length>0&&this.variablesStructure.addVariableUsageInProperties(r)}if(!this.options.keyframes||"animation"!==t&&"animation-name"!==t)if(this.options.fontFace){if("font-family"===t)for(const e of s.split(",")){const t=y(e.trim());this.usedFontFaces.add(t)}}else;else for(const e of s.split(/[\s,]+/))this.usedAnimations.add(e)}getFileExtractor(e,t){const s=t.find(t=>t.extensions.find(t=>e.endsWith(t)));return void 0===s?this.options.defaultExtractor:s.extractor}async extractSelectorsFromFiles(e,t){const s=new d([]);for(const i of e){let e=[];try{await f.access(i,r.constants.F_OK),e.push(i)}catch(t){e=n.sync(i)}for(const r of e){const e=await f.readFile(r,"utf-8"),i=this.getFileExtractor(r,t),n=await m(e,i);s.merge(n)}}return s}async extractSelectorsFromString(e,t){const s=new d([]);for(const{raw:r,extension:i}of e){const e=this.getFileExtractor(`.${i}`,t),n=await m(r,e);s.merge(n)}return s}evaluateAtRule(e){if(this.options.keyframes&&e.name.endsWith("keyframes"))this.atRules.keyframes.push(e);else if(this.options.fontFace&&"font-face"===e.name&&e.nodes)for(const t of e.nodes)"decl"===t.type&&"font-family"===t.prop&&this.atRules.fontFace.push({name:y(t.value),node:e})}async evaluateRule(e,t){if(this.ignore)return;const r=e.prev();if(r&&"comment"===r.type&&g(r,"next"))return void r.remove();if(e.parent&&"atrule"===e.parent.type&&"keyframes"===e.parent.name)return;if("rule"!==e.type)return;if(function(e){let t=!1;return e.walkComments(e=>{e&&"comment"===e.type&&e.text.includes("purgecss ignore current")&&(t=!0,e.remove())}),t}(e))return;let i=!0;if(e.selector=s(e=>{e.walk(e=>{"selector"===e.type&&(i=this.shouldKeepSelector(e,t),i||(this.options.rejected&&this.selectorsRemoved.add(e.toString()),e.remove()))})}).processSync(e.selector),i&&void 0!==e.nodes)for(const t of e.nodes)"decl"===t.type&&this.collectDeclarationsData(t);const n=e.parent;e.selector||e.remove(),function(e){return!!("rule"===e.type&&!e.selector||e.nodes&&!e.nodes.length||"atrule"===e.type&&(!e.nodes&&!e.params||!e.params&&e.nodes&&!e.nodes.length))}(n)&&n.remove()}async getPurgedCSS(e,s){const r=[],i=[];for(const t of e)"string"==typeof t?i.push(...n.sync(t)):i.push(t);for(const e of i){const i="string"==typeof e?this.options.stdin?e:await f.readFile(e,"utf-8"):e.raw,n=t.parse(i);this.walkThroughCSS(n,s),this.options.fontFace&&this.removeUnusedFontFaces(),this.options.keyframes&&this.removeUnusedKeyframes(),this.options.variables&&this.removeUnusedCSSVariables();const a={css:n.toString(),file:"string"==typeof e?e:void 0};"string"==typeof e&&(a.file=e),this.options.rejected&&(a.rejected=Array.from(this.selectorsRemoved),this.selectorsRemoved.clear()),r.push(a)}return r}isSelectorWhitelisted(e){return c.includes(e)||this.options.whitelist&&this.options.whitelist.some(t=>t===e)||this.options.whitelistPatterns&&this.options.whitelistPatterns.some(t=>t.test(e))}isSelectorWhitelistedChildren(e){return this.options.whitelistPatternsChildren&&this.options.whitelistPatternsChildren.some(t=>t.test(e))}async purge(e){this.options="object"!=typeof e?await p(e):{...o,...e};const{content:t,css:s,extractors:r}=this.options,i=t.filter(e=>"string"==typeof e),n=t.filter(e=>"object"==typeof e),a=await this.extractSelectorsFromFiles(i,r),c=await this.extractSelectorsFromString(n,r);return this.getPurgedCSS(s,v(a,c))}removeUnusedCSSVariables(){this.variablesStructure.removeUnused()}removeUnusedFontFaces(){for(const{name:e,node:t}of this.atRules.fontFace)this.usedFontFaces.has(e)||t.remove()}removeUnusedKeyframes(){for(const e of this.atRules.keyframes)this.usedAnimations.has(e.params)||e.remove()}shouldKeepSelector(e,t){if(function(e){return e.parent&&"pseudo"===e.parent.type&&e.parent.value.startsWith(":")||!1}(e))return!0;let s=!1;for(const i of e.nodes){const e="attribute"===i.type&&i.attribute||i.value;if(e&&this.isSelectorWhitelistedChildren(e))return!0;if(e&&(c.includes(e)||this.isSelectorWhitelisted(e)))s=!0;else{switch(i.type){case"attribute":s=!!["value","checked","selected","open"].includes(i.attribute)||w(i,t);break;case"class":r=i,s=t.hasClass(r.value);break;case"id":s=S(i,t);break;case"tag":s=b(i,t)}if(!s)return!1}}var r;return s}walkThroughCSS(e,t){e.walk(e=>"rule"===e.type?this.evaluateRule(e,t):"atrule"===e.type?this.evaluateAtRule(e):void("comment"===e.type&&(g(e,"start")?(this.ignore=!0,e.remove()):g(e,"end")&&(this.ignore=!1,e.remove()))))}}exports.PurgeCSS=x,exports.default=x,exports.defaultOptions=o,exports.mergeExtractorSelectors=v,exports.setOptions=p;
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("postcss"),s=e(require("postcss-selector-parser")),r=require("fs"),i=require("util"),n=e(require("glob")),a=e(require("path"));const o={css:[],content:[],defaultExtractor:e=>e.match(/[A-Za-z0-9_-]+/g)||[],extractors:[],fontFace:!1,keyframes:!1,rejected:!1,stdin:!1,stdout:!1,variables:!1,whitelist:[],whitelistPatterns:[],whitelistPatternsChildren:[]},c=["*","::-webkit-scrollbar","::selection",":root","::before","::after"];class u{constructor(e){this.nodes=[],this.isUsed=!1,this.value=e}}class l{constructor(){this.nodes=new Map,this.usedVariables=new Set}addVariable(e){const{prop:t}=e;if(!this.nodes.has(t)){const s=new u(e);this.nodes.set(t,s)}}addVariableUsage(e,t){const{prop:s}=e,r=this.nodes.get(s);for(const e of t){const t=e[1];if(this.nodes.has(t)){const e=this.nodes.get(t);null==r||r.nodes.push(e)}}}addVariableUsageInProperties(e){for(const t of e){const e=t[1];this.usedVariables.add(e)}}setAsUsed(e){const t=[this.nodes.get(e)];for(;0!==t.length;){const e=t.pop();e&&!e.isUsed&&(e.isUsed=!0,t.push(...e.nodes))}}removeUnused(){for(const e of this.usedVariables)this.setAsUsed(e);for(const[,e]of this.nodes)e.isUsed||e.value.remove()}}function h(e,t){t&&t.forEach(e.add,e)}class d{constructor(e){this.undetermined=new Set,this.attrNames=new Set,this.attrValues=new Set,this.classes=new Set,this.ids=new Set,this.tags=new Set,this.merge(e)}merge(e){return Array.isArray(e)?h(this.undetermined,e):e instanceof d?(h(this.undetermined,e.undetermined),h(this.attrNames,e.attrNames),h(this.attrValues,e.attrValues),h(this.classes,e.classes),h(this.ids,e.ids),h(this.tags,e.tags)):(h(this.undetermined,e.undetermined),e.attributes&&(h(this.attrNames,e.attributes.names),h(this.attrValues,e.attributes.values)),h(this.classes,e.classes),h(this.ids,e.ids),h(this.tags,e.tags)),this}hasAttrName(e){return this.attrNames.has(e)||this.undetermined.has(e)}someAttrValue(e){for(const t of this.attrValues)if(e(t))return!0;for(const t of this.undetermined)if(e(t))return!0;return!1}hasAttrPrefix(e){return this.someAttrValue(t=>t.startsWith(e))}hasAttrSuffix(e){return this.someAttrValue(t=>t.endsWith(e))}hasAttrSubstr(e){return this.someAttrValue(t=>t.includes(e))}hasAttrValue(e){return this.attrValues.has(e)||this.undetermined.has(e)}hasClass(e){return this.classes.has(e)||this.undetermined.has(e)}hasId(e){return this.ids.has(e)||this.undetermined.has(e)}hasTag(e){return this.tags.has(e)||this.undetermined.has(e)}}const f={access:i.promisify(r.access),readFile:i.promisify(r.readFile)};async function p(e="purgecss.config.js"){let t;try{const s=a.join(process.cwd(),e);t=await new Promise((function(e){e(function(e){if(e&&e.__esModule)return e;var t={};return e&&Object.keys(e).forEach((function(s){var r=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,r.get?r:{enumerable:!0,get:function(){return e[s]}})})),t.default=e,t}(require(s)))}))}catch(e){throw new Error(`Error loading the config file ${e.message}`)}return{...o,...t}}async function m(e,t){return new d(await t(e))}function g(e,t){switch(t){case"next":return e.text.includes("purgecss ignore");case"start":return e.text.includes("purgecss start ignore");case"end":return e.text.includes("purgecss end ignore")}}function v(...e){const t=new d([]);return e.forEach(t.merge,t),t}function y(e){return e.replace(/(^["'])|(["']$)/g,"")}function w(e,t){if(!t.hasAttrName(e.attribute))return!1;if(void 0===e.value)return!0;switch(e.operator){case"$=":return t.hasAttrSuffix(e.value);case"~=":case"*=":return t.hasAttrSubstr(e.value);case"=":return t.hasAttrValue(e.value);case"|=":case"^=":return t.hasAttrPrefix(e.value);default:return!0}}function S(e,t){return t.hasId(e.value)}function b(e,t){return t.hasTag(e.value)}class x{constructor(){this.ignore=!1,this.atRules={fontFace:[],keyframes:[]},this.usedAnimations=new Set,this.usedFontFaces=new Set,this.selectorsRemoved=new Set,this.variablesStructure=new l,this.options=o}collectDeclarationsData(e){const{prop:t,value:s}=e;if(this.options.variables){const r=function(e,t){const s=[];return e.replace(t,(function(){const t=arguments,r=Array.prototype.slice.call(t,0,-2);return r.input=t[t.length-1],r.index=t[t.length-2],s.push(r),e})),s}(s,/var\((.+?)[,)]/g);t.startsWith("--")?(this.variablesStructure.addVariable(e),r.length>0&&this.variablesStructure.addVariableUsage(e,r)):r.length>0&&this.variablesStructure.addVariableUsageInProperties(r)}if(!this.options.keyframes||"animation"!==t&&"animation-name"!==t)if(this.options.fontFace){if("font-family"===t)for(const e of s.split(",")){const t=y(e.trim());this.usedFontFaces.add(t)}}else;else for(const e of s.split(/[\s,]+/))this.usedAnimations.add(e)}getFileExtractor(e,t){const s=t.find(t=>t.extensions.find(t=>e.endsWith(t)));return void 0===s?this.options.defaultExtractor:s.extractor}async extractSelectorsFromFiles(e,t){const s=new d([]);for(const i of e){let e=[];try{await f.access(i,r.constants.F_OK),e.push(i)}catch(t){e=n.sync(i,{nodir:!0})}for(const r of e){const e=await f.readFile(r,"utf-8"),i=this.getFileExtractor(r,t),n=await m(e,i);s.merge(n)}}return s}async extractSelectorsFromString(e,t){const s=new d([]);for(const{raw:r,extension:i}of e){const e=this.getFileExtractor(`.${i}`,t),n=await m(r,e);s.merge(n)}return s}evaluateAtRule(e){if(this.options.keyframes&&e.name.endsWith("keyframes"))this.atRules.keyframes.push(e);else if(this.options.fontFace&&"font-face"===e.name&&e.nodes)for(const t of e.nodes)"decl"===t.type&&"font-family"===t.prop&&this.atRules.fontFace.push({name:y(t.value),node:e})}async evaluateRule(e,t){if(this.ignore)return;const r=e.prev();if(r&&"comment"===r.type&&g(r,"next"))return void r.remove();if(e.parent&&"atrule"===e.parent.type&&"keyframes"===e.parent.name)return;if("rule"!==e.type)return;if(function(e){let t=!1;return e.walkComments(e=>{e&&"comment"===e.type&&e.text.includes("purgecss ignore current")&&(t=!0,e.remove())}),t}(e))return;let i=!0;if(e.selector=s(e=>{e.walk(e=>{"selector"===e.type&&(i=this.shouldKeepSelector(e,t),i||(this.options.rejected&&this.selectorsRemoved.add(e.toString()),e.remove()))})}).processSync(e.selector),i&&void 0!==e.nodes)for(const t of e.nodes)"decl"===t.type&&this.collectDeclarationsData(t);const n=e.parent;e.selector||e.remove(),function(e){return!!("rule"===e.type&&!e.selector||e.nodes&&!e.nodes.length||"atrule"===e.type&&(!e.nodes&&!e.params||!e.params&&e.nodes&&!e.nodes.length))}(n)&&n.remove()}async getPurgedCSS(e,s){const r=[],i=[];for(const t of e)"string"==typeof t?i.push(...n.sync(t,{nodir:!0})):i.push(t);for(const e of i){const i="string"==typeof e?this.options.stdin?e:await f.readFile(e,"utf-8"):e.raw,n=t.parse(i);this.walkThroughCSS(n,s),this.options.fontFace&&this.removeUnusedFontFaces(),this.options.keyframes&&this.removeUnusedKeyframes(),this.options.variables&&this.removeUnusedCSSVariables();const a={css:n.toString(),file:"string"==typeof e?e:void 0};"string"==typeof e&&(a.file=e),this.options.rejected&&(a.rejected=Array.from(this.selectorsRemoved),this.selectorsRemoved.clear()),r.push(a)}return r}isSelectorWhitelisted(e){return c.includes(e)||this.options.whitelist&&this.options.whitelist.some(t=>t===e)||this.options.whitelistPatterns&&this.options.whitelistPatterns.some(t=>t.test(e))}isSelectorWhitelistedChildren(e){return this.options.whitelistPatternsChildren&&this.options.whitelistPatternsChildren.some(t=>t.test(e))}async purge(e){this.options="object"!=typeof e?await p(e):{...o,...e};const{content:t,css:s,extractors:r}=this.options,i=t.filter(e=>"string"==typeof e),n=t.filter(e=>"object"==typeof e),a=await this.extractSelectorsFromFiles(i,r),c=await this.extractSelectorsFromString(n,r);return this.getPurgedCSS(s,v(a,c))}removeUnusedCSSVariables(){this.variablesStructure.removeUnused()}removeUnusedFontFaces(){for(const{name:e,node:t}of this.atRules.fontFace)this.usedFontFaces.has(e)||t.remove()}removeUnusedKeyframes(){for(const e of this.atRules.keyframes)this.usedAnimations.has(e.params)||e.remove()}shouldKeepSelector(e,t){if(function(e){return e.parent&&"pseudo"===e.parent.type&&e.parent.value.startsWith(":")||!1}(e))return!0;let s=!1;for(const i of e.nodes){const e="attribute"===i.type&&i.attribute||i.value;if(e&&this.isSelectorWhitelistedChildren(e))return!0;if(e&&(c.includes(e)||this.isSelectorWhitelisted(e)))s=!0;else{switch(i.type){case"attribute":s=!!["value","checked","selected","open"].includes(i.attribute)||w(i,t);break;case"class":r=i,s=t.hasClass(r.value);break;case"id":s=S(i,t);break;case"tag":s=b(i,t)}if(!s)return!1}}var r;return s}walkThroughCSS(e,t){e.walk(e=>"rule"===e.type?this.evaluateRule(e,t):"atrule"===e.type?this.evaluateAtRule(e):void("comment"===e.type&&(g(e,"start")?(this.ignore=!0,e.remove()):g(e,"end")&&(this.ignore=!1,e.remove()))))}}exports.PurgeCSS=x,exports.default=x,exports.defaultOptions=o,exports.mergeExtractorSelectors=v,exports.setOptions=p;
{
"name": "purgecss",
"version": "2.2.1",
"version": "2.3.0",
"description": "Remove unused css selectors",

@@ -44,3 +44,3 @@ "author": "Ffloriel",

"glob": "^7.0.0",
"postcss": "7.0.28",
"postcss": "7.0.32",
"postcss-selector-parser": "^6.0.2"

@@ -54,3 +54,4 @@ },

"url": "https://github.com/FullHuman/purgecss/issues"
}
},
"gitHead": "5314e41edf328e2ad2639549e1587b82a964a42e"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc