postcss-discard-unused
Advanced tools
Comparing version 4.0.1 to 5.0.0-rc.0
@@ -1,50 +0,31 @@ | ||
# 4.0.0-rc.0 | ||
# Change Log | ||
* Breaking: Drops support for Node 0.12, we now require at least Node 4. | ||
* Breaking: Update PostCSS to 6.0.0. | ||
* Resolves an issue with the module not properly detecting namespaces | ||
within attribute selectors. | ||
All notable changes to this project will be documented in this file. | ||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. | ||
# 2.2.3 | ||
# 5.0.0-rc.0 (2021-02-19) | ||
* Font lookup is now case-insensitive, preventing unwanted removal of fonts | ||
that are used (thanks to @thomas-mcdonald). | ||
# 2.2.2 | ||
### chore | ||
* Removed a dependency on `flatten`. | ||
* Performance tweaks; now performs a single AST pass instead of four. | ||
* minimum require version of node is 10.13 ([#871](https://github.com/cssnano/cssnano/issues/871)) ([28bda24](https://github.com/cssnano/cssnano/commit/28bda243e32ce3ba89b3c358a5f78727b3732f11)) | ||
# 2.2.1 | ||
* Now compiled with Babel 6. | ||
### Features | ||
# 2.2.0 | ||
* migarete to PostCSS 8 ([#975](https://github.com/cssnano/cssnano/issues/975)) ([40b82dc](https://github.com/cssnano/cssnano/commit/40b82dca7f53ac02cd4fe62846dec79b898ccb49)) | ||
* Added a new option to remove `@namespace` rules (thanks to @plesiecki). | ||
# 2.1.0 | ||
### BREAKING CHANGES | ||
* Added options to customise what the module discards (thanks to @TrySound). | ||
* minimum supported `postcss` version is `8.2.1` | ||
* minimum require version of node is 10.13 | ||
# 2.0.0 | ||
* Upgraded to PostCSS 5. | ||
# 1.0.3 | ||
## 4.1.1 (2018-09-24) | ||
* Improved performance by reducing the amount of AST iterations. | ||
* Converted the codebase to ES6. | ||
# 1.0.2 | ||
### Bug Fixes | ||
* Fixes an integration issue where the module would crash on `undefined` | ||
`rule.nodes`. | ||
# 1.0.1 | ||
* Fixes an issue where multiple animations were not being recognized. | ||
# 1.0.0 | ||
* Initial release. | ||
* **postcss-merge-longhand:** not mangle border output ([#555](https://github.com/cssnano/cssnano/issues/555)) ([9a70605](https://github.com/cssnano/cssnano/commit/9a706050b621e7795a9bf74eb7110b5c81804ffe)), closes [#553](https://github.com/cssnano/cssnano/issues/553) [#554](https://github.com/cssnano/cssnano/issues/554) |
@@ -1,21 +0,12 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.default = void 0; | ||
var _uniqs = require('uniqs'); | ||
var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser")); | ||
var _uniqs2 = _interopRequireDefault(_uniqs); | ||
var _postcss = require('postcss'); | ||
var _postcssSelectorParser = require('postcss-selector-parser'); | ||
var _postcssSelectorParser2 = _interopRequireDefault(_postcssSelectorParser); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
const { comma, space } = _postcss.list; | ||
const atrule = 'atrule'; | ||
@@ -25,113 +16,195 @@ const decl = 'decl'; | ||
function addValues(cache, { value }) { | ||
return comma(value).reduce((memo, val) => [...memo, ...space(val)], cache); | ||
function uniqs(items) { | ||
return items.filter(function (item, i) { | ||
return i === items.indexOf(item); | ||
}); | ||
} | ||
function filterAtRule({ atRules, values }) { | ||
values = (0, _uniqs2.default)(values); | ||
atRules.forEach(node => { | ||
const hasAtRule = values.some(value => value === node.params); | ||
if (!hasAtRule) { | ||
node.remove(); | ||
} | ||
}); | ||
function addValues(cache, { | ||
value | ||
}, comma, space) { | ||
return comma(value).reduce((memo, val) => [...memo, ...space(val)], cache); | ||
} | ||
function filterNamespace({ atRules, rules }) { | ||
rules = (0, _uniqs2.default)(rules); | ||
atRules.forEach(atRule => { | ||
const { 0: param, length: len } = atRule.params.split(' ').filter(Boolean); | ||
if (len === 1) { | ||
return; | ||
} | ||
const hasRule = rules.some(r => r === param || r === '*'); | ||
if (!hasRule) { | ||
atRule.remove(); | ||
} | ||
}); | ||
function filterAtRule({ | ||
atRules, | ||
values | ||
}) { | ||
values = uniqs(values); | ||
atRules.forEach(node => { | ||
const hasAtRule = values.some(value => value === node.params); | ||
if (!hasAtRule) { | ||
node.remove(); | ||
} | ||
}); | ||
} | ||
function hasFont(fontFamily, cache) { | ||
return comma(fontFamily).some(font => cache.some(c => ~c.indexOf(font))); | ||
function filterNamespace({ | ||
atRules, | ||
rules | ||
}) { | ||
rules = uniqs(rules); | ||
atRules.forEach(atRule => { | ||
const { | ||
0: param, | ||
length: len | ||
} = atRule.params.split(' ').filter(Boolean); | ||
if (len === 1) { | ||
return; | ||
} | ||
const hasRule = rules.some(r => r === param || r === '*'); | ||
if (!hasRule) { | ||
atRule.remove(); | ||
} | ||
}); | ||
} | ||
// fonts have slightly different logic | ||
function filterFont({ atRules, values }) { | ||
values = (0, _uniqs2.default)(values); | ||
atRules.forEach(r => { | ||
const families = r.nodes.filter(({ prop }) => prop === 'font-family'); | ||
// Discard the @font-face if it has no font-family | ||
if (!families.length) { | ||
return r.remove(); | ||
} | ||
families.forEach(family => { | ||
if (!hasFont(family.value.toLowerCase(), values)) { | ||
r.remove(); | ||
} | ||
}); | ||
function hasFont(fontFamily, cache, comma) { | ||
return comma(fontFamily).some(font => cache.some(c => ~c.indexOf(font))); | ||
} // fonts have slightly different logic | ||
function filterFont({ | ||
atRules, | ||
values | ||
}, comma) { | ||
values = uniqs(values); | ||
atRules.forEach(r => { | ||
const families = r.nodes.filter(({ | ||
prop | ||
}) => prop === 'font-family'); // Discard the @font-face if it has no font-family | ||
if (!families.length) { | ||
return r.remove(); | ||
} | ||
families.forEach(family => { | ||
if (!hasFont(family.value.toLowerCase(), values, comma)) { | ||
r.remove(); | ||
} | ||
}); | ||
}); | ||
} | ||
exports.default = (0, _postcss.plugin)('postcss-discard-unused', opts => { | ||
const { fontFace, counterStyle, keyframes, namespace } = Object.assign({}, { | ||
fontFace: true, | ||
counterStyle: true, | ||
keyframes: true, | ||
namespace: true | ||
}, opts); | ||
return css => { | ||
const counterStyleCache = { atRules: [], values: [] }; | ||
const keyframesCache = { atRules: [], values: [] }; | ||
const namespaceCache = { atRules: [], rules: [] }; | ||
const fontCache = { atRules: [], values: [] }; | ||
css.walk(node => { | ||
const { type, prop, selector, name } = node; | ||
function pluginCreator(opts) { | ||
const { | ||
fontFace, | ||
counterStyle, | ||
keyframes, | ||
namespace | ||
} = Object.assign({}, { | ||
fontFace: true, | ||
counterStyle: true, | ||
keyframes: true, | ||
namespace: true | ||
}, opts); | ||
return { | ||
postcssPlugin: 'postcss-discard-unused', | ||
prepare() { | ||
const counterStyleCache = { | ||
atRules: [], | ||
values: [] | ||
}; | ||
const keyframesCache = { | ||
atRules: [], | ||
values: [] | ||
}; | ||
const namespaceCache = { | ||
atRules: [], | ||
rules: [] | ||
}; | ||
const fontCache = { | ||
atRules: [], | ||
values: [] | ||
}; | ||
return { | ||
OnceExit(css, { | ||
list | ||
}) { | ||
const { | ||
comma, | ||
space | ||
} = list; | ||
css.walk(node => { | ||
const { | ||
type, | ||
prop, | ||
selector, | ||
name | ||
} = node; | ||
if (type === rule && namespace && ~selector.indexOf('|')) { | ||
if (~selector.indexOf('[')) { | ||
// Attribute selector, so we should parse further. | ||
(0, _postcssSelectorParser2.default)(ast => { | ||
ast.walkAttributes(({ namespace: ns }) => { | ||
namespaceCache.rules = namespaceCache.rules.concat(ns); | ||
}); | ||
}).process(selector); | ||
} else { | ||
// Use a simple split function for the namespace | ||
namespaceCache.rules = namespaceCache.rules.concat(selector.split('|')[0]); | ||
} | ||
return; | ||
if (~selector.indexOf('[')) { | ||
// Attribute selector, so we should parse further. | ||
(0, _postcssSelectorParser.default)(ast => { | ||
ast.walkAttributes(({ | ||
namespace: ns | ||
}) => { | ||
namespaceCache.rules = namespaceCache.rules.concat(ns); | ||
}); | ||
}).process(selector); | ||
} else { | ||
// Use a simple split function for the namespace | ||
namespaceCache.rules = namespaceCache.rules.concat(selector.split('|')[0]); | ||
} | ||
return; | ||
} | ||
if (type === decl) { | ||
if (counterStyle && /list-style|system/.test(prop)) { | ||
counterStyleCache.values = addValues(counterStyleCache.values, node); | ||
} | ||
if (fontFace && node.parent.type === rule && /font(|-family)/.test(prop)) { | ||
fontCache.values = fontCache.values.concat(comma(node.value.toLowerCase())); | ||
} | ||
if (keyframes && /animation/.test(prop)) { | ||
keyframesCache.values = addValues(keyframesCache.values, node); | ||
} | ||
return; | ||
if (counterStyle && /list-style|system/.test(prop)) { | ||
counterStyleCache.values = addValues(counterStyleCache.values, node, comma, space); | ||
} | ||
if (fontFace && node.parent.type === rule && /font(|-family)/.test(prop)) { | ||
fontCache.values = fontCache.values.concat(comma(node.value.toLowerCase())); | ||
} | ||
if (keyframes && /animation/.test(prop)) { | ||
keyframesCache.values = addValues(keyframesCache.values, node, comma, space); | ||
} | ||
return; | ||
} | ||
if (type === atrule) { | ||
if (counterStyle && /counter-style/.test(name)) { | ||
counterStyleCache.atRules.push(node); | ||
} | ||
if (fontFace && name === 'font-face' && node.nodes) { | ||
fontCache.atRules.push(node); | ||
} | ||
if (keyframes && /keyframes/.test(name)) { | ||
keyframesCache.atRules.push(node); | ||
} | ||
if (namespace && name === 'namespace') { | ||
namespaceCache.atRules.push(node); | ||
} | ||
return; | ||
if (counterStyle && /counter-style/.test(name)) { | ||
counterStyleCache.atRules.push(node); | ||
} | ||
if (fontFace && name === 'font-face' && node.nodes) { | ||
fontCache.atRules.push(node); | ||
} | ||
if (keyframes && /keyframes/.test(name)) { | ||
keyframesCache.atRules.push(node); | ||
} | ||
if (namespace && name === 'namespace') { | ||
namespaceCache.atRules.push(node); | ||
} | ||
return; | ||
} | ||
}); | ||
counterStyle && filterAtRule(counterStyleCache); | ||
fontFace && filterFont(fontCache); | ||
keyframes && filterAtRule(keyframesCache); | ||
namespace && filterNamespace(namespaceCache); | ||
}; | ||
}); | ||
module.exports = exports['default']; | ||
}); | ||
counterStyle && filterAtRule(counterStyleCache); | ||
fontFace && filterFont(fontCache, comma); | ||
keyframes && filterAtRule(keyframesCache); | ||
namespace && filterNamespace(namespaceCache); | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
pluginCreator.postcss = true; | ||
var _default = pluginCreator; | ||
exports.default = _default; | ||
module.exports = exports.default; |
{ | ||
"name": "postcss-discard-unused", | ||
"version": "4.0.1", | ||
"version": "5.0.0-rc.0", | ||
"description": "Discard unused counter styles, keyframes and fonts.", | ||
@@ -12,3 +12,5 @@ "main": "dist/index.js", | ||
"scripts": { | ||
"prepublish": "cross-env BABEL_ENV=publish babel src --out-dir dist --ignore /__tests__/" | ||
"prebuild": "del-cli dist", | ||
"build": "cross-env BABEL_ENV=publish babel src --config-file ../../babel.config.js --out-dir dist --ignore \"**/__tests__/\"", | ||
"prepublish": "yarn build" | ||
}, | ||
@@ -24,6 +26,2 @@ "keywords": [ | ||
"license": "MIT", | ||
"devDependencies": { | ||
"babel-cli": "^6.0.0", | ||
"cross-env": "^5.0.0" | ||
}, | ||
"homepage": "https://github.com/cssnano/cssnano", | ||
@@ -37,5 +35,3 @@ "author": { | ||
"dependencies": { | ||
"postcss": "^7.0.0", | ||
"postcss-selector-parser": "^3.0.0", | ||
"uniqs": "^2.0.0" | ||
"postcss-selector-parser": "^6.0.4" | ||
}, | ||
@@ -46,4 +42,11 @@ "bugs": { | ||
"engines": { | ||
"node": ">=6.9.0" | ||
} | ||
"node": "^10 || ^12 || >=14.0" | ||
}, | ||
"devDependencies": { | ||
"postcss": "^8.2.1" | ||
}, | ||
"peerDependencies": { | ||
"postcss": "^8.2.1" | ||
}, | ||
"gitHead": "8c16e67a4d24a13ac7e09a36d4faf504196efd0f" | ||
} |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
10611
2
1
175
1
+ Addedcssesc@3.0.0(transitive)
+ Addednanoid@3.3.8(transitive)
+ Addedpicocolors@1.1.1(transitive)
+ Addedpostcss@8.5.1(transitive)
+ Addedpostcss-selector-parser@6.1.2(transitive)
+ Addedsource-map-js@1.2.1(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
- Removedpostcss@^7.0.0
- Removeduniqs@^2.0.0
- Removeddot-prop@5.3.0(transitive)
- Removedindexes-of@1.0.1(transitive)
- Removedis-obj@2.0.0(transitive)
- Removedpicocolors@0.2.1(transitive)
- Removedpostcss@7.0.39(transitive)
- Removedpostcss-selector-parser@3.1.2(transitive)
- Removedsource-map@0.6.1(transitive)
- Removeduniq@1.0.1(transitive)
- Removeduniqs@2.0.0(transitive)