Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
allHrefs.forEach(href => {
while (redirectResponses[href]) {
href = redirectResponses[href];
}
if (skippedUrls.has(href)) {
// skippedUrls are URLs that for some reason was deliberately not
// downloaded. You can supply a `options.skippable` function which
// might, for some reason, skip certain URLs. But if we don't
// remember which URLs we skipped, when we later find all the
// tags to start analyze, we'd get an error here because
// we deliberately chose to now parse its CSS.
return;
}
const ast = stylesheetAsts[href];
csstree.walk(ast, {
visit: 'Rule',
enter: function(node, item, list) {
if (
this.atrule &&
csstree.keyword(this.atrule.name).basename === 'keyframes'
) {
// Don't bother inspecting rules that are inside a keyframe.
return;
}
if (!node.prelude.children) {
const cssErrorMessage = `Invalid CSS found while evaluating ${href}: "${node.prelude.value}"`;
if (options.ignoreCSSErrors) {
console.warn(cssErrorMessage);
list.remove(item);
} else {
export default function finalRuleRemover (ast, propertiesToRemove) {
// remove empty rules
csstree.walk(ast, {
visit: 'Rule',
leave: (rule, item, list) => {
if (rule.block.children.isEmpty()) {
list.remove(item)
}
}
})
// remove unwanted and empty at-rules
csstree.walk(ast, {
visit: 'Atrule',
leave: (atrule, item, list) => {
const name = csstree.keyword(atrule.name).basename
/* ==@-rule handling== */
/* - Case 0 : Non nested @-rule [REMAIN]
(@charset, @import, @namespace)
*/
if (name === 'charset' || name === 'import' || name === 'namespace') {
return
}
/* Case 1: @-rule with CSS properties inside [REMAIN]
@font-face, @keyframes - keep here, but remove later in code, unless it is used.
*/
if (name === 'font-face' || name === 'keyframes' || name === 'viewport') {
function validate(css, filename) {
var errors = [];
var ast = csstree.parse(css, {
filename: filename,
positions: true,
onParseError: function(error) {
errors.push(error);
}
});
csstree.walk(ast, {
visit: 'Declaration',
enter: function(node) {
var match = syntax.matchDeclaration(node);
var error = match.error;
if (error) {
var message = error.rawMessage || error.message || error;
// ignore errors except those which make sense
if (error.name !== 'SyntaxMatchError' &&
error.name !== 'SyntaxReferenceError') {
return;
}
if (message === 'Mismatch') {
message = 'Invalid value for `' + node.property + '`';
const walkTree = ast => {
csstree.walk(ast, {
visit: 'Rule',
enter: function(node) {
// Namespace all discovery styles
node.prelude.children.forEach(child => {
child.children.prependData({
type: 'WhiteSpace',
value: ' '
});
child.children.prependData({
type: 'ClassSelector',
name: WRAPPER_NODE
});
});
}
});
function countDeclarations (ast) {
let count = 0
csstree.walk(ast, {
visit: 'Declaration',
enter: () => count++
})
return count
}
enter: (declaration, item, list) => {
let tooLong = false
csstree.walk(declaration, {
visit: 'Url',
enter: function (url) {
const value = url.value.value
if (
BASE64_ENCODE_PATTERN.test(value) &&
value.length > maxEmbeddedBase64Length
) {
tooLong = true
}
}
})
if (tooLong) {
const value = csstree.generate(declaration.value)
debuglog(
'DROP: ' +
module.exports = function rejoinAtrule(ast, options) {
relocateAtrules(ast, options);
walk(ast, {
visit: 'Atrule',
reverse: true,
enter: processAtrule
});
};
enter(node) {
if (cssName(node.property) === 'animation' || cssName(node.property) === 'animation-name') {
walk(node.value, value => {
if (value.type === 'Identifier' && value.name in animations) {
value.name = animations[value.name];
}
});
}
}
});
export async function optimizeCSS(
{ text, url: baseURL }: Sheet,
document?: Document | ShadowRoot,
noStoring = false
) {
const ast = csstree.parse(text)
await replaceImports(ast, baseURL)
csstree.walk(ast, (node, item, list) => {
if (document && node.type === 'Rule' && node.prelude.type === 'SelectorList') {
const includesURL = (node.block.children.some(node => {
if (node.type !== 'Declaration' || node.value.type === 'Raw') {
return false
}
return (node.value.children.some(node => node.type === 'Url') as any) as boolean
}) as any) as boolean
if (!includesURL) {
return
}
try {
const prelude = csstree.clone(node.prelude) as csstree.SelectorList
processSelectorList(prelude)
module.exports = function restructRule(ast) {
walk(ast, {
visit: 'Rule',
reverse: true,
enter: processRule
});
};