axe-core
Version:
Accessibility engine for automated Web UI testing
97 lines (85 loc) • 2.42 kB
JavaScript
/**
* Parse non cross-origin stylesheets
*
* @method parseSameOriginStylesheet
* @memberof axe.utils
* @param {Object} sheet CSSStylesheet object
* @param {Object} options options object from `axe.utils.parseStylesheet`
* @param {Array<Number>} priority sheet priority
* @param {Array<String>} importedUrls urls of already imported stylesheets
* @param {Boolean} isCrossOrigin boolean denoting if a stylesheet is `cross-origin`
* @returns {Promise}
*/
axe.utils.parseSameOriginStylesheet = function parseSameOriginStylesheet(
sheet,
options,
priority,
importedUrls,
isCrossOrigin = false
) {
const rules = Array.from(sheet.cssRules);
if (!rules) {
return Promise.resolve();
}
/**
* reference -> https://developer.mozilla.org/en-US/docs/Web/API/CSSRule#Type_constants
*/
const cssImportRules = rules.filter(r => r.type === 3); // type === 3 -> CSSRule.IMPORT_RULE
/**
* when no `@import` rules in given sheet -> resolve the current `sheet` & exit
*/
if (!cssImportRules.length) {
// exit
return Promise.resolve({
isCrossOrigin,
priority,
root: options.rootNode,
shadowId: options.shadowId,
sheet
});
}
/**
* filter rules that are not already fetched
*/
const cssImportUrlsNotAlreadyImported = cssImportRules
// ensure rule has a href
.filter(rule => rule.href)
// extract href from object
.map(rule => rule.href)
// only href that are not already imported
.filter(url => !importedUrls.includes(url));
/**
* iterate `@import` rules and fetch styles
*/
const promises = cssImportUrlsNotAlreadyImported.map(
(importUrl, cssRuleIndex) => {
const newPriority = [...priority, cssRuleIndex];
const isCrossOriginRequest = /^https?:\/\/|^\/\//i.test(importUrl);
return axe.utils.parseCrossOriginStylesheet(
importUrl,
options,
newPriority,
importedUrls,
isCrossOriginRequest
);
}
);
const nonImportCSSRules = rules.filter(r => r.type !== 3);
// no further rules to process in this sheet
if (!nonImportCSSRules.length) {
return Promise.all(promises);
}
// convert all `nonImportCSSRules` style rules into `text` and chain
promises.push(
Promise.resolve(
options.convertDataToStylesheet({
data: nonImportCSSRules.map(rule => rule.cssText).join(),
isCrossOrigin,
priority,
root: options.rootNode,
shadowId: options.shadowId
})
)
);
return Promise.all(promises);
};