forked from dequelabs/axe-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparse-sameorigin-stylesheet.js
More file actions
100 lines (87 loc) · 2.56 KB
/
parse-sameorigin-stylesheet.js
File metadata and controls
100 lines (87 loc) · 2.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import parseCrossOriginStylesheet from './parse-crossorigin-stylesheet';
/**
* 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}
*/
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 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);
}
export default parseSameOriginStylesheet;