Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
* supported everywhere `theme-color` is. Also, values
* such as `currentcolor` don't make sense, but they
* will be catched by the above check.
*
* See also:
*
* * https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Browser_compatibility
* * https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/graphics/Color.cpp?rcl=6263bcf0ec9f112b5f0d84fc059c759302bd8c67
*/
// TODO: Use `isSupported` for all color syntax checks.
// `RGBA` support depends on the browser.
return (color.model === 'rgb' &&
hexWithAlphaRegex.test(normalizedColorValue) &&
!isSupported({ property: 'color', value: '#00000000' }, context.targetedBrowsers)) ||
// `HWB` is not supported anywhere (?).
color.model === 'hwb';
};
* supported everywhere `theme-color` is. Also, values
* such as `currentcolor` don't make sense, but they
* will be catched by the above check.
*
* See also:
*
* * https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Browser_compatibility
* * https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/graphics/Color.cpp?rcl=6263bcf0ec9f112b5f0d84fc059c759302bd8c67
*/
// TODO: Use `isSupported` for all color syntax checks.
// `RGBA` support depends on the browser.
return (color.model === 'rgb' &&
hexWithAlphaRegex.test(normalizedColorValue) &&
!isSupported({ property: 'color', value: '#00000000' }, context.targetedBrowsers)) ||
// `HWB` is not supported anywhere (?).
color.model === 'hwb';
};
!elementHrefHasRequiredProtocol(element) ||
!checkSameOrigin(resource, element)) {
return;
}
checkForRelValue(resource, element, 'noopener', Severity.error);
/*
* If no browsers were targeted, or `noopener`
* is not supported by all targeted browsers,
* also check for 'noreferrer'.
*/
// TODO: Fix `isSupported` so `element` can be `a`.
if (!context.targetedBrowsers.length || !isSupported({ attribute: 'rel', element: 'link', value: 'noopener' }, context.targetedBrowsers)) {
checkForRelValue(resource, element, 'noreferrer', Severity.warning);
}
};
const filterItem = (item: Declaration | DeclarationGroup, browsers: string[]): string[] => {
if ('prop' in item) {
const supportsProperty = getSupported({ property: item.prop }, browsers);
const supportsValue = supportsProperty && getSupported({ property: item.prop, value: item.value }, supportsProperty);
return supportsValue || [];
}
switch (item.type) {
case 'and':
return intersection(...item.nodes.map((child) => {
return filterItem(child, browsers);
}));
case 'or':
return union(...item.nodes.map((child) => {
return filterItem(child, browsers);
}));
case 'not':
return difference(browsers, filterItem(item.nodes[0], browsers));
const filterItem = (item: Declaration | DeclarationGroup, browsers: string[]): string[] => {
if ('prop' in item) {
const supportsProperty = getSupported({ property: item.prop }, browsers);
const supportsValue = supportsProperty && getSupported({ property: item.prop, value: item.value }, supportsProperty);
return supportsValue || [];
}
switch (item.type) {
case 'and':
return intersection(...item.nodes.map((child) => {
return filterItem(child, browsers);
}));
case 'or':
return union(...item.nodes.map((child) => {
return filterItem(child, browsers);
}));
case 'not':
return difference(browsers, filterItem(item.nodes[0], browsers));
default:
export const filterSupports = (params: string, browsers: string[]): string[] | null => {
const hasAtSupports = getSupported({ rule: 'supports'}, browsers);
if (!hasAtSupports) {
return null;
}
const root = parseSupports(params);
if (!root) {
return null;
}
try {
const supported = filterItem(root, hasAtSupports);
return supported.length ? supported : null;
} catch (e) {
const validateDeclValue = (node: Declaration, context: Context): ReportData | null => {
const unsupported = getUnsupportedDetails({ property: node.prop, value: node.value }, context.browsers);
if (unsupported) {
const formatFeature = (value: string) => {
return `${node.prop}: ${value}`;
};
return { feature: formatFeature(node.value), formatFeature, isValue: true, node, unsupported };
}
return null;
};
const validateElement = (node: HTMLElement, context: Context) => {
const element = node.nodeName.toLowerCase();
if (context.ignore.has(element)) {
return;
}
const unsupported = getUnsupportedDetails({ element }, context.browsers);
if (unsupported) {
context.report({ feature: element, unsupported });
} else {
for (let i = 0; i < node.attributes.length; i++) {
validateAttribute(element, node.attributes[i], context);
}
}
};
const validateAttributeValue = (element: string, attr: HTMLAttribute, context: Context) => {
if (context.ignore.has(`${element}[${attr.name}=${attr.value}]`)) {
return;
}
const unsupported = getUnsupportedDetails({ attribute: attr.name, element, value: attr.value }, context.browsers);
if (unsupported) {
context.report({ feature: `${element}[${attr.name}=${attr.value}]`, unsupported });
}
};
export const formatUnsupported = (browser: string, versionAdded?: string, versionRemoved?: string): string => {
const browserName = getFriendlyName(browser);
if (versionAdded && versionRemoved) {
return `${browserName} ${versionRemoved}-${versionAdded}`;
} else if (versionAdded) {
return `${browserName} < ${versionAdded}`;
} else if (versionRemoved) {
return `${browserName} ${versionRemoved}+`;
}
return browserName;
};