Socket
Socket
Sign inDemoInstall

purgecss

Package Overview
Dependencies
Maintainers
2
Versions
62
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

purgecss - npm Package Compare versions

Comparing version 4.1.2 to 4.1.3

2

bin/purgecss.js
#!/usr/bin/env node
"use strict";var e=require("commander"),t=require("fs"),s=require("glob"),r=require("path"),o=require("postcss"),i=require("postcss-selector-parser"),n=require("util");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function c(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(s){if("default"!==s){var r=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,r.get?r:{enumerable:!0,get:function(){return e[s]}})}})),t.default=e,Object.freeze(t)}var l=c(t),u=a(t),d=a(s),f=a(r),h=c(o),p=a(i),m="4.1.1",g="Remove unused css selectors";function v(e,t){t&&t.forEach(e.add,e)}class y{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)?v(this.undetermined,e):e instanceof y?(v(this.undetermined,e.undetermined),v(this.attrNames,e.attrNames),v(this.attrValues,e.attrValues),v(this.classes,e.classes),v(this.ids,e.ids),v(this.tags,e.tags)):(v(this.undetermined,e.undetermined),e.attributes&&(v(this.attrNames,e.attributes.names),v(this.attrValues,e.attributes.values)),v(this.classes,e.classes),v(this.ids,e.ids),v(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 e.trim().split(" ").every((e=>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 b=["*",":root",":after",":before"],S={css:[],content:[],defaultExtractor:e=>e.match(/[A-Za-z0-9_-]+/g)||[],extractors:[],fontFace:!1,keyframes:!1,rejected:!1,rejectedCss:!1,stdin:!1,stdout:!1,variables:!1,safelist:{standard:[],deep:[],greedy:[],variables:[],keyframes:[]},blocklist:[],skippedContentGlobs:[],dynamicAttributes:[]};function w(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}class k{constructor(e){this.nodes=[],this.isUsed=!1,this.value=e}}class F{constructor(){this.nodes=new Map,this.usedVariables=new Set,this.safelist=[]}addVariable(e){const{prop:t}=e;if(this.nodes.has(t)){const s=new k(e),r=this.nodes.get(t)||[];this.nodes.set(t,[...r,s])}else{const s=new k(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.forEach((t=>{null==e||e.forEach((e=>t.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);if(t){const e=[...t];for(;0!==e.length;){const t=e.pop();t&&!t.isUsed&&(t.isUsed=!0,e.push(...t.nodes))}}}removeUnused(){for(const e of this.usedVariables){const t=this.nodes.get(e);if(t)for(const e of t){w(e.value.value,/var\((.+?)[,)]/g).forEach((e=>{this.usedVariables.has(e[1])||this.usedVariables.add(e[1])}))}}for(const e of this.usedVariables)this.setAsUsed(e);for(const[e,t]of this.nodes)for(const s of t)s.isUsed||this.isVariablesSafelisted(e)||s.value.remove()}isVariablesSafelisted(e){return this.safelist.some((t=>"string"==typeof t?t===e:t.test(e)))}}const A={access:n.promisify(l.access),readFile:n.promisify(l.readFile)};function V(e=[]){return Array.isArray(e)?{...S.safelist,standard:e}:{...S.safelist,...e}}async function j(e="purgecss.config.js"){let t;try{const s=f.default.resolve(process.cwd(),e);t=await function(e){return Promise.resolve().then((function(){return c(require(e))}))}(s)}catch(e){throw new Error(`Error loading the config file ${e.message}`)}return{...S,...t,safelist:V(t.safelist)}}async function x(e,t){return new y(await t(e))}function C(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 U(e){return e.replace(/(^["'])|(["']$)/g,"")}function R(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 E(e,t){return t.hasId(e.value)}function N(e,t){return t.hasTag(e.value)}function P(e){return"atrule"===(null==e?void 0:e.type)}function q(e){return"rule"===(null==e?void 0:e.type)}class G{constructor(){this.ignore=!1,this.atRules={fontFace:[],keyframes:[]},this.usedAnimations=new Set,this.usedFontFaces=new Set,this.selectorsRemoved=new Set,this.removedNodes=[],this.variablesStructure=new F,this.options=S}collectDeclarationsData(e){const{prop:t,value:s}=e;if(this.options.variables){const r=w(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=U(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 y([]);for(const r of e){let e=[];try{await A.access(r,l.constants.F_OK),e.push(r)}catch(t){e=d.default.sync(r,{nodir:!0,ignore:this.options.skippedContentGlobs})}for(const r of e){const e=await A.readFile(r,"utf-8"),o=this.getFileExtractor(r,t),i=await x(e,o);s.merge(i)}}return s}async extractSelectorsFromString(e,t){const s=new y([]);for(const{raw:r,extension:o}of e){const e=this.getFileExtractor(`.${o}`,t),i=await x(r,e);s.merge(i)}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:U(t.value),node:e})}evaluateRule(e,t){if(this.ignore)return;const s=e.prev();if(function(e){return"comment"===(null==e?void 0:e.type)}(s)&&C(s,"next"))return void s.remove();if(e.parent&&P(e.parent)&&e.parent.name.endsWith("keyframes"))return;if(!q(e))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 r=!0;const o=[];if(e.selector=p.default((e=>{e.walk((e=>{"selector"===e.type&&(r=this.shouldKeepSelector(e,t),r||(this.options.rejected&&this.selectorsRemoved.add(e.toString()),this.options.rejectedCss&&o.push(e.toString()),e.remove()))}))})).processSync(e.selector),r&&void 0!==e.nodes)for(const t of e.nodes)"decl"===t.type&&this.collectDeclarationsData(t);const i=e.parent;if(e.selector||e.remove(),function(e){return!!(q(e)&&!e.selector||(null==e?void 0:e.nodes)&&!e.nodes.length||P(e)&&(!e.nodes&&!e.params||!e.params&&e.nodes&&!e.nodes.length))}(i)&&(null==i||i.remove()),this.options.rejectedCss&&o.length>0){const t=e.clone(),s=null==i?void 0:i.clone().removeAll().append(t);t.selectors=o;const r=s||t;this.removedNodes.push(r)}}async getPurgedCSS(e,t){const s=[],r=[];for(const t of e)"string"==typeof t?r.push(...d.default.sync(t,{nodir:!0,ignore:this.options.skippedContentGlobs})):r.push(t);for(const e of r){const r="string"==typeof e?this.options.stdin?e:await A.readFile(e,"utf-8"):e.raw,o=h.parse(r);this.walkThroughCSS(o,t),this.options.fontFace&&this.removeUnusedFontFaces(),this.options.keyframes&&this.removeUnusedKeyframes(),this.options.variables&&this.removeUnusedCSSVariables();const i={css:o.toString(),file:"string"==typeof e?e:e.name};this.options.rejected&&(i.rejected=Array.from(this.selectorsRemoved),this.selectorsRemoved.clear()),this.options.rejectedCss&&(i.rejectedCss=h.root({nodes:this.removedNodes}).toString()),s.push(i)}return s}isKeyframesSafelisted(e){return this.options.safelist.keyframes.some((t=>"string"==typeof t?t===e:t.test(e)))}isSelectorBlocklisted(e){return this.options.blocklist.some((t=>"string"==typeof t?t===e:t.test(e)))}isSelectorSafelisted(e){const t=this.options.safelist.standard.some((t=>"string"==typeof t?t===e:t.test(e))),s=/^::.*/.test(e);return b.includes(e)||s||t}isSelectorSafelistedDeep(e){return this.options.safelist.deep.some((t=>t.test(e)))}isSelectorSafelistedGreedy(e){return this.options.safelist.greedy.some((t=>t.test(e)))}async purge(e){this.options="object"!=typeof e?await j(e):{...S,...e,safelist:V(e.safelist)};const{content:t,css:s,extractors:r,safelist:o}=this.options;this.options.variables&&(this.variablesStructure.safelist=o.variables||[]);const 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,function(...e){const t=new y([]);return e.forEach(t.merge,t),t}(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)||this.isKeyframesSafelisted(e.params)||e.remove()}getSelectorValue(e){return"attribute"===e.type&&e.attribute||e.value}shouldKeepSelector(e,t){if(function(e){return e.parent&&"pseudo"===e.parent.type&&e.parent.value.startsWith(":")||!1}(e))return!0;if(this.options.safelist.greedy.length>0){if(e.nodes.map(this.getSelectorValue).some((e=>e&&this.isSelectorSafelistedGreedy(e))))return!0}let s=!1;for(const o of e.nodes){const e=this.getSelectorValue(o);if(e&&this.isSelectorSafelistedDeep(e))return!0;if(e&&(b.includes(e)||this.isSelectorSafelisted(e)))s=!0;else{if(e&&this.isSelectorBlocklisted(e))return!1;switch(o.type){case"attribute":s=!![...this.options.dynamicAttributes,"value","checked","selected","open"].includes(o.attribute)||R(o,t);break;case"class":r=o,s=t.hasClass(r.value);break;case"id":s=E(o,t);break;case"tag":s=N(o,t);break;default:continue}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&&(C(e,"start")?(this.ignore=!0,e.remove()):C(e,"end")&&(this.ignore=!1,e.remove())))))}}async function O(e,t){try{await u.default.promises.writeFile(e,t)}catch(e){console.error(e.message)}}try{!async function(){var t;e.program.description(g).version(m).usage("--css <css...> --content <content...> [options]"),e.program.option("-con, --content <files...>","glob of content files").option("-css, --css <files...>","glob of css files").option("-c, --config <path>","path to the configuration file").option("-o, --output <path>","file path directory to write purged css files to").option("-font, --font-face","option to remove unused font-faces").option("-keyframes, --keyframes","option to remove unused keyframes").option("-v, --variables","option to remove unused variables").option("-rejected, --rejected","option to output rejected selectors").option("-rejected-css, --rejected-css","option to output rejected css").option("-s, --safelist <list...>","list of classes that should not be removed").option("-b, --blocklist <list...>","list of selectors that should be removed").option("-k, --skippedContentGlobs <list...>","list of glob patterns for folders/files that should not be scanned"),e.program.parse(process.argv);const{config:s,css:r,content:o,output:i,fontFace:n,keyframes:a,variables:c,rejected:l,rejectedCss:u,safelist:d,blocklist:f,skippedContentGlobs:h}=e.program.opts();s||o&&r||e.program.help();let p=S;s&&(p=await j(s)),o&&(p.content=o),r&&(p.css=r),n&&(p.fontFace=n),a&&(p.keyframes=a),l&&(p.rejected=l),u&&(p.rejectedCss=u),c&&(p.variables=c),d&&(p.safelist=V(d)),f&&(p.blocklist=f),h&&(p.skippedContentGlobs=h);const v=await(new G).purge(p),y=p.output||i;if(y){if(1===v.length&&y.endsWith(".css"))return void await O(y,v[0].css);for(const e of v){const s=null===(t=null==e?void 0:e.file)||void 0===t?void 0:t.split("/").pop();await O(`${i}/${s}`,e.css)}}else console.log(JSON.stringify(v))}()}catch(e){console.error(e.message),process.exit(1)}
"use strict";var e=require("commander"),t=require("fs"),s=require("glob"),r=require("path"),o=require("postcss"),i=require("postcss-selector-parser"),n=require("util");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function c(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(s){if("default"!==s){var r=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,r.get?r:{enumerable:!0,get:function(){return e[s]}})}})),t.default=e,Object.freeze(t)}var l=c(t),u=a(t),d=a(s),f=a(r),h=c(o),p=a(i),m="4.1.2",g="Remove unused css selectors";function v(e,t){t&&t.forEach(e.add,e)}class y{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)?v(this.undetermined,e):e instanceof y?(v(this.undetermined,e.undetermined),v(this.attrNames,e.attrNames),v(this.attrValues,e.attrValues),v(this.classes,e.classes),v(this.ids,e.ids),v(this.tags,e.tags)):(v(this.undetermined,e.undetermined),e.attributes&&(v(this.attrNames,e.attributes.names),v(this.attrValues,e.attributes.values)),v(this.classes,e.classes),v(this.ids,e.ids),v(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 e.trim().split(" ").every((e=>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 b=["*",":root",":after",":before"],S={css:[],content:[],defaultExtractor:e=>e.match(/[A-Za-z0-9_-]+/g)||[],extractors:[],fontFace:!1,keyframes:!1,rejected:!1,rejectedCss:!1,stdin:!1,stdout:!1,variables:!1,safelist:{standard:[],deep:[],greedy:[],variables:[],keyframes:[]},blocklist:[],skippedContentGlobs:[],dynamicAttributes:[]};function w(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}class k{constructor(e){this.nodes=[],this.isUsed=!1,this.value=e}}class F{constructor(){this.nodes=new Map,this.usedVariables=new Set,this.safelist=[]}addVariable(e){const{prop:t}=e;if(this.nodes.has(t)){const s=new k(e),r=this.nodes.get(t)||[];this.nodes.set(t,[...r,s])}else{const s=new k(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.forEach((t=>{null==e||e.forEach((e=>t.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);if(t){const e=[...t];for(;0!==e.length;){const t=e.pop();t&&!t.isUsed&&(t.isUsed=!0,e.push(...t.nodes))}}}removeUnused(){for(const e of this.usedVariables){const t=this.nodes.get(e);if(t)for(const e of t){w(e.value.value,/var\((.+?)[,)]/g).forEach((e=>{this.usedVariables.has(e[1])||this.usedVariables.add(e[1])}))}}for(const e of this.usedVariables)this.setAsUsed(e);for(const[e,t]of this.nodes)for(const s of t)s.isUsed||this.isVariablesSafelisted(e)||s.value.remove()}isVariablesSafelisted(e){return this.safelist.some((t=>"string"==typeof t?t===e:t.test(e)))}}const A={access:n.promisify(l.access),readFile:n.promisify(l.readFile)};function V(e=[]){return Array.isArray(e)?{...S.safelist,standard:e}:{...S.safelist,...e}}async function j(e="purgecss.config.js"){let t;try{const s=f.default.resolve(process.cwd(),e);t=await function(e){return Promise.resolve().then((function(){return c(require(e))}))}(s)}catch(e){throw new Error(`Error loading the config file ${e.message}`)}return{...S,...t,safelist:V(t.safelist)}}async function x(e,t){return new y(await t(e))}function C(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 U(e){return e.replace(/(^["'])|(["']$)/g,"")}function R(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 E(e,t){return t.hasId(e.value)}function N(e,t){return t.hasTag(e.value)}function P(e){return"atrule"===(null==e?void 0:e.type)}function q(e){return"rule"===(null==e?void 0:e.type)}class G{constructor(){this.ignore=!1,this.atRules={fontFace:[],keyframes:[]},this.usedAnimations=new Set,this.usedFontFaces=new Set,this.selectorsRemoved=new Set,this.removedNodes=[],this.variablesStructure=new F,this.options=S}collectDeclarationsData(e){const{prop:t,value:s}=e;if(this.options.variables){const r=w(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=U(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 y([]);for(const r of e){let e=[];try{await A.access(r,l.constants.F_OK),e.push(r)}catch(t){e=d.default.sync(r,{nodir:!0,ignore:this.options.skippedContentGlobs})}for(const r of e){const e=await A.readFile(r,"utf-8"),o=this.getFileExtractor(r,t),i=await x(e,o);s.merge(i)}}return s}async extractSelectorsFromString(e,t){const s=new y([]);for(const{raw:r,extension:o}of e){const e=this.getFileExtractor(`.${o}`,t),i=await x(r,e);s.merge(i)}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:U(t.value),node:e})}evaluateRule(e,t){if(this.ignore)return;const s=e.prev();if(function(e){return"comment"===(null==e?void 0:e.type)}(s)&&C(s,"next"))return void s.remove();if(e.parent&&P(e.parent)&&e.parent.name.endsWith("keyframes"))return;if(!q(e))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 r=!0;const o=[];if(e.selector=p.default((e=>{e.walk((e=>{"selector"===e.type&&(r=this.shouldKeepSelector(e,t),r||(this.options.rejected&&this.selectorsRemoved.add(e.toString()),this.options.rejectedCss&&o.push(e.toString()),e.remove()))}))})).processSync(e.selector),r&&void 0!==e.nodes)for(const t of e.nodes)"decl"===t.type&&this.collectDeclarationsData(t);const i=e.parent;if(e.selector||e.remove(),function(e){return!!(q(e)&&!e.selector||(null==e?void 0:e.nodes)&&!e.nodes.length||P(e)&&(!e.nodes&&!e.params||!e.params&&e.nodes&&!e.nodes.length))}(i)&&(null==i||i.remove()),this.options.rejectedCss&&o.length>0){const t=e.clone(),s=null==i?void 0:i.clone().removeAll().append(t);t.selectors=o;const r=s||t;this.removedNodes.push(r)}}async getPurgedCSS(e,t){const s=[],r=[];for(const t of e)"string"==typeof t?r.push(...d.default.sync(t,{nodir:!0,ignore:this.options.skippedContentGlobs})):r.push(t);for(const e of r){const r="string"==typeof e?this.options.stdin?e:await A.readFile(e,"utf-8"):e.raw,o=h.parse(r);this.walkThroughCSS(o,t),this.options.fontFace&&this.removeUnusedFontFaces(),this.options.keyframes&&this.removeUnusedKeyframes(),this.options.variables&&this.removeUnusedCSSVariables();const i={css:o.toString(),file:"string"==typeof e?e:e.name};this.options.rejected&&(i.rejected=Array.from(this.selectorsRemoved),this.selectorsRemoved.clear()),this.options.rejectedCss&&(i.rejectedCss=h.root({nodes:this.removedNodes}).toString()),s.push(i)}return s}isKeyframesSafelisted(e){return this.options.safelist.keyframes.some((t=>"string"==typeof t?t===e:t.test(e)))}isSelectorBlocklisted(e){return this.options.blocklist.some((t=>"string"==typeof t?t===e:t.test(e)))}isSelectorSafelisted(e){const t=this.options.safelist.standard.some((t=>"string"==typeof t?t===e:t.test(e))),s=/^::.*/.test(e);return b.includes(e)||s||t}isSelectorSafelistedDeep(e){return this.options.safelist.deep.some((t=>t.test(e)))}isSelectorSafelistedGreedy(e){return this.options.safelist.greedy.some((t=>t.test(e)))}async purge(e){this.options="object"!=typeof e?await j(e):{...S,...e,safelist:V(e.safelist)};const{content:t,css:s,extractors:r,safelist:o}=this.options;this.options.variables&&(this.variablesStructure.safelist=o.variables||[]);const 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,function(...e){const t=new y([]);return e.forEach(t.merge,t),t}(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)||this.isKeyframesSafelisted(e.params)||e.remove()}getSelectorValue(e){return"attribute"===e.type&&e.attribute||e.value}shouldKeepSelector(e,t){if(function(e){return e.parent&&"pseudo"===e.parent.type&&e.parent.value.startsWith(":")||!1}(e))return!0;if(this.options.safelist.greedy.length>0){if(e.nodes.map(this.getSelectorValue).some((e=>e&&this.isSelectorSafelistedGreedy(e))))return!0}let s=!1;for(const o of e.nodes){const e=this.getSelectorValue(o);if(e&&this.isSelectorSafelistedDeep(e))return!0;if(e&&(b.includes(e)||this.isSelectorSafelisted(e)))s=!0;else{if(e&&this.isSelectorBlocklisted(e))return!1;switch(o.type){case"attribute":s=!![...this.options.dynamicAttributes,"value","checked","selected","open"].includes(o.attribute)||R(o,t);break;case"class":r=o,s=t.hasClass(r.value);break;case"id":s=E(o,t);break;case"tag":s=N(o,t);break;default:continue}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&&(C(e,"start")?(this.ignore=!0,e.remove()):C(e,"end")&&(this.ignore=!1,e.remove())))))}}async function O(e,t){try{await u.default.promises.writeFile(e,t)}catch(e){console.error(e.message)}}try{!async function(){var t;e.program.description(g).version(m).usage("--css <css...> --content <content...> [options]"),e.program.option("-con, --content <files...>","glob of content files").option("-css, --css <files...>","glob of css files").option("-c, --config <path>","path to the configuration file").option("-o, --output <path>","file path directory to write purged css files to").option("-font, --font-face","option to remove unused font-faces").option("-keyframes, --keyframes","option to remove unused keyframes").option("-v, --variables","option to remove unused variables").option("-rejected, --rejected","option to output rejected selectors").option("-rejected-css, --rejected-css","option to output rejected css").option("-s, --safelist <list...>","list of classes that should not be removed").option("-b, --blocklist <list...>","list of selectors that should be removed").option("-k, --skippedContentGlobs <list...>","list of glob patterns for folders/files that should not be scanned"),e.program.parse(process.argv);const{config:s,css:r,content:o,output:i,fontFace:n,keyframes:a,variables:c,rejected:l,rejectedCss:u,safelist:d,blocklist:f,skippedContentGlobs:h}=e.program.opts();s||o&&r||e.program.help();let p=S;s&&(p=await j(s)),o&&(p.content=o),r&&(p.css=r),n&&(p.fontFace=n),a&&(p.keyframes=a),l&&(p.rejected=l),u&&(p.rejectedCss=u),c&&(p.variables=c),d&&(p.safelist=V(d)),f&&(p.blocklist=f),h&&(p.skippedContentGlobs=h);const v=await(new G).purge(p),y=p.output||i;if(y){if(1===v.length&&y.endsWith(".css"))return void await O(y,v[0].css);for(const e of v){const s=null===(t=null==e?void 0:e.file)||void 0===t?void 0:t.split("/").pop();await O(`${y}/${s}`,e.css)}}else console.log(JSON.stringify(v))}()}catch(e){console.error(e.message),process.exit(1)}
import * as postcss from "postcss";
type PostCSSRoot = postcss.Root;
interface AtRules {
fontFace: Array<{
name: string;
node: postcss.AtRule;
}>;
keyframes: postcss.AtRule[];
fontFace: Array<{
name: string;
node: postcss.AtRule;
}>;
keyframes: postcss.AtRule[];
}
interface RawContent<T = string> {
extension: string;
raw: T;
extension: string;
raw: T;
}
interface RawCSS {
raw: string;
name?: string;
raw: string;
name?: string;
}
interface ExtractorResultDetailed {
attributes: {
names: string[];
values: string[];
};
classes: string[];
ids: string[];
tags: string[];
undetermined: string[];
attributes: {
names: string[];
values: string[];
};
classes: string[];
ids: string[];
tags: string[];
undetermined: string[];
}

@@ -31,4 +31,4 @@ type ExtractorResult = ExtractorResultDetailed | string[];

interface Extractors {
extensions: string[];
extractor: ExtractorFunction;
extensions: string[];
extractor: ExtractorFunction;
}

@@ -38,72 +38,74 @@ type IgnoreType = "end" | "start" | "next";

type ComplexSafelist = {
standard?: StringRegExpArray;
deep?: RegExp[];
greedy?: RegExp[];
variables?: StringRegExpArray;
keyframes?: StringRegExpArray;
standard?: StringRegExpArray;
deep?: RegExp[];
greedy?: RegExp[];
variables?: StringRegExpArray;
keyframes?: StringRegExpArray;
};
type UserDefinedSafelist = StringRegExpArray | ComplexSafelist;
interface UserDefinedOptions {
content: Array<string | RawContent>;
css: Array<string | RawCSS>;
defaultExtractor?: ExtractorFunction;
extractors?: Array<Extractors>;
fontFace?: boolean;
keyframes?: boolean;
output?: string;
rejected?: boolean;
rejectedCss?: boolean;
stdin?: boolean;
stdout?: boolean;
variables?: boolean;
safelist?: UserDefinedSafelist;
blocklist?: StringRegExpArray;
skippedContentGlobs?: Array<string>;
dynamicAttributes?: string[];
content: Array<string | RawContent>;
css: Array<string | RawCSS>;
defaultExtractor?: ExtractorFunction;
extractors?: Array<Extractors>;
fontFace?: boolean;
keyframes?: boolean;
output?: string;
rejected?: boolean;
rejectedCss?: boolean;
stdin?: boolean;
stdout?: boolean;
variables?: boolean;
safelist?: UserDefinedSafelist;
blocklist?: StringRegExpArray;
skippedContentGlobs?: Array<string>;
dynamicAttributes?: string[];
}
interface Options {
content: Array<string | RawContent>;
css: Array<string | RawCSS>;
defaultExtractor: ExtractorFunction;
extractors: Array<Extractors>;
fontFace: boolean;
keyframes: boolean;
output?: string;
rejected: boolean;
rejectedCss: boolean;
stdin: boolean;
stdout: boolean;
variables: boolean;
safelist: Required<ComplexSafelist>;
blocklist: StringRegExpArray;
skippedContentGlobs: Array<string>;
dynamicAttributes: string[];
content: Array<string | RawContent>;
css: Array<string | RawCSS>;
defaultExtractor: ExtractorFunction;
extractors: Array<Extractors>;
fontFace: boolean;
keyframes: boolean;
output?: string;
rejected: boolean;
rejectedCss: boolean;
stdin: boolean;
stdout: boolean;
variables: boolean;
safelist: Required<ComplexSafelist>;
blocklist: StringRegExpArray;
skippedContentGlobs: Array<string>;
dynamicAttributes: string[];
}
interface ResultPurge {
css: string;
rejectedCss?: string;
file?: string;
rejected?: string[];
css: string;
rejectedCss?: string;
file?: string;
rejected?: string[];
}
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;
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;
}
declare const defaultOptions: Options;
declare function standardizeSafelist(userDefinedSafelist?: UserDefinedSafelist): Required<ComplexSafelist>;
declare function standardizeSafelist(
userDefinedSafelist?: UserDefinedSafelist
): Required<ComplexSafelist>;
/**

@@ -119,182 +121,217 @@ * Load the configuration file from the path

*/
declare function mergeExtractorSelectors(...extractors: (ExtractorResultDetailed | ExtractorResultSets)[]): ExtractorResultSets;
declare function mergeExtractorSelectors(
...extractors: (ExtractorResultDetailed | ExtractorResultSets)[]
): ExtractorResultSets;
declare class PurgeCSS {
private ignore;
private atRules;
private usedAnimations;
private usedFontFaces;
selectorsRemoved: Set<string>;
removedNodes: postcss.Node[];
private variablesStructure;
options: Options;
private collectDeclarationsData;
/**
* Get the extractor corresponding to the extension file
* @param filename Name of the file
* @param extractors Array of extractors definition
*/
/**
* 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
*/
/**
* 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<ExtractorResultSets>;
/**
* Extract the selectors present in the passed string using a PurgeCSS extractor
* @param content Array of content
* @param extractors Array of extractors
*/
/**
* 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<ExtractorResultSets>;
/**
* Evaluate at-rule and register it for future reference
* @param node node of postcss AST
*/
/**
* Evaluate at-rule and register it for future reference
* @param node node of postcss AST
*/
private evaluateAtRule;
/**
* Evaluate css selector and decide if it should be removed or not
* @param node node of postcss AST
* @param selectors selectors used in content files
*/
/**
* Evaluate css selector and decide if it should be removed or not
* @param node node of postcss AST
* @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
*/
/**
* 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<string | RawCSS>, selectors: ExtractorResultSets): Promise<ResultPurge[]>;
/**
* Check if the keyframe is safelisted with the option safelist keyframes
* @param keyframesName name of the keyframe animation
*/
/**
* 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
*/
/**
* 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
*/
/**
* 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
*/
/**
* 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
*/
/**
* Check if the selector is safelisted with the option safelist greedy
* @param selector selector
*/
private isSelectorSafelistedGreedy;
/**
* Remove unused css
* @param userOptions PurgeCSS options
*/
/**
* Remove unused css
* @param userOptions PurgeCSS options
*/
purge(userOptions: UserDefinedOptions | string | undefined): Promise<ResultPurge[]>;
/**
* Remove unused CSS variables
*/
/**
* Remove unused CSS variables
*/
removeUnusedCSSVariables(): void;
/**
* Remove unused font-faces
*/
/**
* Remove unused font-faces
*/
removeUnusedFontFaces(): void;
/**
* Remove unused keyframes
*/
/**
* Remove unused keyframes
*/
removeUnusedKeyframes(): void;
/**
* Transform a selector node into a string
*/
/**
* 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
*/
/**
* 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
*/
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
*/
/**
* 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;
private ignore;
private atRules;
private usedAnimations;
private usedFontFaces;
selectorsRemoved: Set<string>;
removedNodes: postcss.Node[];
private variablesStructure;
options: Options;
private collectDeclarationsData;
/**
* Get the extractor corresponding to the extension file
* @param filename Name of the file
* @param extractors Array of extractors definition
*/
/**
* 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
*/
/**
* 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<ExtractorResultSets>;
/**
* Extract the selectors present in the passed string using a PurgeCSS extractor
* @param content Array of content
* @param extractors Array of extractors
*/
/**
* 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<ExtractorResultSets>;
/**
* Evaluate at-rule and register it for future reference
* @param node node of postcss AST
*/
/**
* Evaluate at-rule and register it for future reference
* @param node node of postcss AST
*/
private evaluateAtRule;
/**
* Evaluate css selector and decide if it should be removed or not
* @param node node of postcss AST
* @param selectors selectors used in content files
*/
/**
* Evaluate css selector and decide if it should be removed or not
* @param node node of postcss AST
* @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
*/
/**
* 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<string | RawCSS>,
selectors: ExtractorResultSets
): Promise<ResultPurge[]>;
/**
* Check if the keyframe is safelisted with the option safelist keyframes
* @param keyframesName name of the keyframe animation
*/
/**
* 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
*/
/**
* 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
*/
/**
* 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
*/
/**
* 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
*/
/**
* Check if the selector is safelisted with the option safelist greedy
* @param selector selector
*/
private isSelectorSafelistedGreedy;
/**
* Remove unused css
* @param userOptions PurgeCSS options
*/
/**
* Remove unused css
* @param userOptions PurgeCSS options
*/
purge(
userOptions: UserDefinedOptions | string | undefined
): Promise<ResultPurge[]>;
/**
* Remove unused CSS variables
*/
/**
* Remove unused CSS variables
*/
removeUnusedCSSVariables(): void;
/**
* Remove unused font-faces
*/
/**
* Remove unused font-faces
*/
removeUnusedFontFaces(): void;
/**
* Remove unused keyframes
*/
/**
* Remove unused keyframes
*/
removeUnusedKeyframes(): void;
/**
* Transform a selector node into a string
*/
/**
* 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
*/
/**
* 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
*/
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
*/
/**
* 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;
}
export { PurgeCSS as default, PurgeCSS, defaultOptions, PostCSSRoot, AtRules, RawContent, RawCSS, ExtractorResultDetailed, ExtractorResult, ExtractorFunction, Extractors, IgnoreType, StringRegExpArray, ComplexSafelist, UserDefinedSafelist, UserDefinedOptions, Options, ResultPurge, standardizeSafelist, setOptions, mergeExtractorSelectors };
export {
PurgeCSS as default,
PurgeCSS,
defaultOptions,
PostCSSRoot,
AtRules,
RawContent,
RawCSS,
ExtractorResultDetailed,
ExtractorResult,
ExtractorFunction,
Extractors,
IgnoreType,
StringRegExpArray,
ComplexSafelist,
UserDefinedSafelist,
UserDefinedOptions,
Options,
ResultPurge,
standardizeSafelist,
setOptions,
mergeExtractorSelectors,
};
import * as postcss from "postcss";
type PostCSSRoot = postcss.Root;
interface AtRules {
fontFace: Array<{
name: string;
node: postcss.AtRule;
}>;
keyframes: postcss.AtRule[];
fontFace: Array<{
name: string;
node: postcss.AtRule;
}>;
keyframes: postcss.AtRule[];
}
interface RawContent<T = string> {
extension: string;
raw: T;
extension: string;
raw: T;
}
interface RawCSS {
raw: string;
name?: string;
raw: string;
name?: string;
}
interface ExtractorResultDetailed {
attributes: {
names: string[];
values: string[];
};
classes: string[];
ids: string[];
tags: string[];
undetermined: string[];
attributes: {
names: string[];
values: string[];
};
classes: string[];
ids: string[];
tags: string[];
undetermined: string[];
}

@@ -31,4 +31,4 @@ type ExtractorResult = ExtractorResultDetailed | string[];

interface Extractors {
extensions: string[];
extractor: ExtractorFunction;
extensions: string[];
extractor: ExtractorFunction;
}

@@ -38,72 +38,74 @@ type IgnoreType = "end" | "start" | "next";

type ComplexSafelist = {
standard?: StringRegExpArray;
deep?: RegExp[];
greedy?: RegExp[];
variables?: StringRegExpArray;
keyframes?: StringRegExpArray;
standard?: StringRegExpArray;
deep?: RegExp[];
greedy?: RegExp[];
variables?: StringRegExpArray;
keyframes?: StringRegExpArray;
};
type UserDefinedSafelist = StringRegExpArray | ComplexSafelist;
interface UserDefinedOptions {
content: Array<string | RawContent>;
css: Array<string | RawCSS>;
defaultExtractor?: ExtractorFunction;
extractors?: Array<Extractors>;
fontFace?: boolean;
keyframes?: boolean;
output?: string;
rejected?: boolean;
rejectedCss?: boolean;
stdin?: boolean;
stdout?: boolean;
variables?: boolean;
safelist?: UserDefinedSafelist;
blocklist?: StringRegExpArray;
skippedContentGlobs?: Array<string>;
dynamicAttributes?: string[];
content: Array<string | RawContent>;
css: Array<string | RawCSS>;
defaultExtractor?: ExtractorFunction;
extractors?: Array<Extractors>;
fontFace?: boolean;
keyframes?: boolean;
output?: string;
rejected?: boolean;
rejectedCss?: boolean;
stdin?: boolean;
stdout?: boolean;
variables?: boolean;
safelist?: UserDefinedSafelist;
blocklist?: StringRegExpArray;
skippedContentGlobs?: Array<string>;
dynamicAttributes?: string[];
}
interface Options {
content: Array<string | RawContent>;
css: Array<string | RawCSS>;
defaultExtractor: ExtractorFunction;
extractors: Array<Extractors>;
fontFace: boolean;
keyframes: boolean;
output?: string;
rejected: boolean;
rejectedCss: boolean;
stdin: boolean;
stdout: boolean;
variables: boolean;
safelist: Required<ComplexSafelist>;
blocklist: StringRegExpArray;
skippedContentGlobs: Array<string>;
dynamicAttributes: string[];
content: Array<string | RawContent>;
css: Array<string | RawCSS>;
defaultExtractor: ExtractorFunction;
extractors: Array<Extractors>;
fontFace: boolean;
keyframes: boolean;
output?: string;
rejected: boolean;
rejectedCss: boolean;
stdin: boolean;
stdout: boolean;
variables: boolean;
safelist: Required<ComplexSafelist>;
blocklist: StringRegExpArray;
skippedContentGlobs: Array<string>;
dynamicAttributes: string[];
}
interface ResultPurge {
css: string;
rejectedCss?: string;
file?: string;
rejected?: string[];
css: string;
rejectedCss?: string;
file?: string;
rejected?: string[];
}
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;
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;
}
declare const defaultOptions: Options;
declare function standardizeSafelist(userDefinedSafelist?: UserDefinedSafelist): Required<ComplexSafelist>;
declare function standardizeSafelist(
userDefinedSafelist?: UserDefinedSafelist
): Required<ComplexSafelist>;
/**

@@ -119,182 +121,217 @@ * Load the configuration file from the path

*/
declare function mergeExtractorSelectors(...extractors: (ExtractorResultDetailed | ExtractorResultSets)[]): ExtractorResultSets;
declare function mergeExtractorSelectors(
...extractors: (ExtractorResultDetailed | ExtractorResultSets)[]
): ExtractorResultSets;
declare class PurgeCSS {
private ignore;
private atRules;
private usedAnimations;
private usedFontFaces;
selectorsRemoved: Set<string>;
removedNodes: postcss.Node[];
private variablesStructure;
options: Options;
private collectDeclarationsData;
/**
* Get the extractor corresponding to the extension file
* @param filename Name of the file
* @param extractors Array of extractors definition
*/
/**
* 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
*/
/**
* 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<ExtractorResultSets>;
/**
* Extract the selectors present in the passed string using a PurgeCSS extractor
* @param content Array of content
* @param extractors Array of extractors
*/
/**
* 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<ExtractorResultSets>;
/**
* Evaluate at-rule and register it for future reference
* @param node node of postcss AST
*/
/**
* Evaluate at-rule and register it for future reference
* @param node node of postcss AST
*/
private evaluateAtRule;
/**
* Evaluate css selector and decide if it should be removed or not
* @param node node of postcss AST
* @param selectors selectors used in content files
*/
/**
* Evaluate css selector and decide if it should be removed or not
* @param node node of postcss AST
* @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
*/
/**
* 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<string | RawCSS>, selectors: ExtractorResultSets): Promise<ResultPurge[]>;
/**
* Check if the keyframe is safelisted with the option safelist keyframes
* @param keyframesName name of the keyframe animation
*/
/**
* 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
*/
/**
* 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
*/
/**
* 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
*/
/**
* 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
*/
/**
* Check if the selector is safelisted with the option safelist greedy
* @param selector selector
*/
private isSelectorSafelistedGreedy;
/**
* Remove unused css
* @param userOptions PurgeCSS options
*/
/**
* Remove unused css
* @param userOptions PurgeCSS options
*/
purge(userOptions: UserDefinedOptions | string | undefined): Promise<ResultPurge[]>;
/**
* Remove unused CSS variables
*/
/**
* Remove unused CSS variables
*/
removeUnusedCSSVariables(): void;
/**
* Remove unused font-faces
*/
/**
* Remove unused font-faces
*/
removeUnusedFontFaces(): void;
/**
* Remove unused keyframes
*/
/**
* Remove unused keyframes
*/
removeUnusedKeyframes(): void;
/**
* Transform a selector node into a string
*/
/**
* 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
*/
/**
* 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
*/
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
*/
/**
* 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;
private ignore;
private atRules;
private usedAnimations;
private usedFontFaces;
selectorsRemoved: Set<string>;
removedNodes: postcss.Node[];
private variablesStructure;
options: Options;
private collectDeclarationsData;
/**
* Get the extractor corresponding to the extension file
* @param filename Name of the file
* @param extractors Array of extractors definition
*/
/**
* 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
*/
/**
* 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<ExtractorResultSets>;
/**
* Extract the selectors present in the passed string using a PurgeCSS extractor
* @param content Array of content
* @param extractors Array of extractors
*/
/**
* 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<ExtractorResultSets>;
/**
* Evaluate at-rule and register it for future reference
* @param node node of postcss AST
*/
/**
* Evaluate at-rule and register it for future reference
* @param node node of postcss AST
*/
private evaluateAtRule;
/**
* Evaluate css selector and decide if it should be removed or not
* @param node node of postcss AST
* @param selectors selectors used in content files
*/
/**
* Evaluate css selector and decide if it should be removed or not
* @param node node of postcss AST
* @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
*/
/**
* 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<string | RawCSS>,
selectors: ExtractorResultSets
): Promise<ResultPurge[]>;
/**
* Check if the keyframe is safelisted with the option safelist keyframes
* @param keyframesName name of the keyframe animation
*/
/**
* 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
*/
/**
* 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
*/
/**
* 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
*/
/**
* 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
*/
/**
* Check if the selector is safelisted with the option safelist greedy
* @param selector selector
*/
private isSelectorSafelistedGreedy;
/**
* Remove unused css
* @param userOptions PurgeCSS options
*/
/**
* Remove unused css
* @param userOptions PurgeCSS options
*/
purge(
userOptions: UserDefinedOptions | string | undefined
): Promise<ResultPurge[]>;
/**
* Remove unused CSS variables
*/
/**
* Remove unused CSS variables
*/
removeUnusedCSSVariables(): void;
/**
* Remove unused font-faces
*/
/**
* Remove unused font-faces
*/
removeUnusedFontFaces(): void;
/**
* Remove unused keyframes
*/
/**
* Remove unused keyframes
*/
removeUnusedKeyframes(): void;
/**
* Transform a selector node into a string
*/
/**
* 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
*/
/**
* 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
*/
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
*/
/**
* 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;
}
export { PurgeCSS as default, PurgeCSS, defaultOptions, PostCSSRoot, AtRules, RawContent, RawCSS, ExtractorResultDetailed, ExtractorResult, ExtractorFunction, Extractors, IgnoreType, StringRegExpArray, ComplexSafelist, UserDefinedSafelist, UserDefinedOptions, Options, ResultPurge, standardizeSafelist, setOptions, mergeExtractorSelectors };
export {
PurgeCSS as default,
PurgeCSS,
defaultOptions,
PostCSSRoot,
AtRules,
RawContent,
RawCSS,
ExtractorResultDetailed,
ExtractorResult,
ExtractorFunction,
Extractors,
IgnoreType,
StringRegExpArray,
ComplexSafelist,
UserDefinedSafelist,
UserDefinedOptions,
Options,
ResultPurge,
standardizeSafelist,
setOptions,
mergeExtractorSelectors,
};
{
"name": "purgecss",
"version": "4.1.2",
"version": "4.1.3",
"description": "Remove unused css selectors",

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

},
"gitHead": "1329d96b0ad17e9b2b4d604d1a689856da176a59"
"gitHead": "37e5053a446880d12fd2f55abfc362c3dac9c49c"
}
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc