css-has-pseudo 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +1 -1
- package/browser.js +1 -1
- package/index.js +31 -27
- package/index.js.map +1 -1
- package/index.mjs +31 -27
- package/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ Next, use your transformed CSS with this script:
|
|
|
41
41
|
<script>cssHasPseudo(document)</script>
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
That’s it. The script is
|
|
44
|
+
That’s it. The script is 765 bytes and works in all browsers, including
|
|
45
45
|
Internet Explorer 11. With a [Mutation Observer polyfill], the script will work
|
|
46
46
|
down to Internet Explorer 9.
|
|
47
47
|
|
package/browser.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function cssHasPseudo(n){var t=[],
|
|
1
|
+
function cssHasPseudo(n){var t=[],e=n.createElement("x");function o(){requestAnimationFrame(function(){t.forEach(function(t){var o=[];[].forEach.call(n.querySelectorAll(t.n),function(u){var i=[].indexOf.call(u.parentNode.children,u)+1,c=t.t.map(function(n){return t.n+":nth-child("+i+") "+n}).join(),r=u.parentNode.querySelector(c);(t.e?!r:r)&&(o.push(u),e.innerHTML="<x "+t.o+">",u.setAttributeNode(e.children[0].attributes[0].cloneNode()),n.documentElement.style.zoom=1,n.documentElement.style.zoom=null)}),t.u.forEach(function(e){-1===o.indexOf(e)&&(e.removeAttribute(t.o),n.documentElement.style.zoom=1,n.documentElement.style.zoom=null)}),t.u=o})})}function u(n){try{[].forEach.call(n.cssRules||[],function(n){if(n.selectorText){var e=decodeURIComponent(n.selectorText.replace(/\\(.)/g,"$1")).match(/^(.*?)\[:(not-)?has\((.+?)\)\](.*?)$/);if(e){var o=":"+(e[2]?"not-":"")+"has("+encodeURIComponent(e[3]).replace(/%3A/g,":").replace(/%5B/g,"[").replace(/%5D/g,"]").replace(/%2C/g,",")+")";t.push({i:n,n:e[1],e:e[2],t:e[3].split(/\s*,\s*/),o:o,u:[]})}}else u(n)})}catch(n){}}[].forEach.call(n.styleSheets,u),o(),new MutationObserver(function(e){e.forEach(function(e){[].forEach.call(e.addedNodes||[],function(n){1===n.nodeType&&n.sheet&&u(n.sheet)}),[].push.apply(t,t.splice(0).filter(function(t){return t.i.parentStyleSheet&&t.i.parentStyleSheet.ownerNode&&n.documentElement.contains(t.i.parentStyleSheet.ownerNode)})),o()})}).observe(n,{childList:!0,subtree:!0}),n.addEventListener("focus",o,!0),n.addEventListener("blur",o,!0),n.addEventListener("input",o)}
|
package/index.js
CHANGED
|
@@ -5,12 +5,12 @@ function cssHasPseudo(document) {
|
|
|
5
5
|
|
|
6
6
|
const attributeElement = document.createElement('x'); // walk all stylesheets to collect observed css rules
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
[].forEach.call(document.styleSheets, walkStyleSheet);
|
|
9
9
|
transformObservedItems(); // observe DOM modifications that affect selectors
|
|
10
10
|
|
|
11
11
|
const mutationObserver = new MutationObserver(mutationsList => {
|
|
12
12
|
mutationsList.forEach(mutation => {
|
|
13
|
-
|
|
13
|
+
[].forEach.call(mutation.addedNodes || [], node => {
|
|
14
14
|
// walk stylesheets to collect observed css rules
|
|
15
15
|
if (node.nodeType === 1 && node.sheet) {
|
|
16
16
|
walkStyleSheet(node.sheet);
|
|
@@ -34,8 +34,8 @@ function cssHasPseudo(document) {
|
|
|
34
34
|
requestAnimationFrame(() => {
|
|
35
35
|
observedItems.forEach(item => {
|
|
36
36
|
const nodes = [];
|
|
37
|
-
|
|
38
|
-
const nthChild =
|
|
37
|
+
[].forEach.call(document.querySelectorAll(item.scopeSelector), element => {
|
|
38
|
+
const nthChild = [].indexOf.call(element.parentNode.children, element) + 1;
|
|
39
39
|
const relativeSelectors = item.relativeSelectors.map(relativeSelector => item.scopeSelector + ':nth-child(' + nthChild + ') ' + relativeSelector).join(); // find any relative :has element from the :scope element
|
|
40
40
|
|
|
41
41
|
const relativeElement = element.parentNode.querySelector(relativeSelectors);
|
|
@@ -70,34 +70,38 @@ function cssHasPseudo(document) {
|
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
function cleanupObservedCssRules() {
|
|
73
|
-
|
|
73
|
+
[].push.apply(observedItems, observedItems.splice(0).filter(item => item.rule.parentStyleSheet && item.rule.parentStyleSheet.ownerNode && document.documentElement.contains(item.rule.parentStyleSheet.ownerNode)));
|
|
74
74
|
} // walk a stylesheet to collect observed css rules
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
function walkStyleSheet(styleSheet) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
78
|
+
try {
|
|
79
|
+
// walk a css rule to collect observed css rules
|
|
80
|
+
[].forEach.call(styleSheet.cssRules || [], rule => {
|
|
81
|
+
if (rule.selectorText) {
|
|
82
|
+
// decode the selector text in all browsers to:
|
|
83
|
+
// [1] = :scope, [2] = :not(:has), [3] = :has relative, [4] = :scope relative
|
|
84
|
+
const selectors = decodeURIComponent(rule.selectorText.replace(/\\(.)/g, '$1')).match(/^(.*?)\[:(not-)?has\((.+?)\)\](.*?)$/);
|
|
85
|
+
|
|
86
|
+
if (selectors) {
|
|
87
|
+
const attributeName = ':' + (selectors[2] ? 'not-' : '') + 'has(' + // encode a :has() pseudo selector as an attribute name
|
|
88
|
+
encodeURIComponent(selectors[3]).replace(/%3A/g, ':').replace(/%5B/g, '[').replace(/%5D/g, ']').replace(/%2C/g, ',') + ')';
|
|
89
|
+
observedItems.push({
|
|
90
|
+
rule,
|
|
91
|
+
scopeSelector: selectors[1],
|
|
92
|
+
isNot: selectors[2],
|
|
93
|
+
relativeSelectors: selectors[3].split(/\s*,\s*/),
|
|
94
|
+
attributeName,
|
|
95
|
+
nodes: []
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
walkStyleSheet(rule);
|
|
96
100
|
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
+
});
|
|
102
|
+
} catch (error) {
|
|
103
|
+
/* do nothing and continue */
|
|
104
|
+
}
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
107
|
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["src/browser.js"],"sourcesContent":["export default function cssHasPseudo(document) {\n\tconst observedItems = [];\n\n\t// document.createAttribute() doesn't support `:` in the name. innerHTML does\n\tconst attributeElement = document.createElement('x');\n\n\t// walk all stylesheets to collect observed css rules\n\
|
|
1
|
+
{"version":3,"file":"index.js","sources":["src/browser.js"],"sourcesContent":["export default function cssHasPseudo(document) {\n\tconst observedItems = [];\n\n\t// document.createAttribute() doesn't support `:` in the name. innerHTML does\n\tconst attributeElement = document.createElement('x');\n\n\t// walk all stylesheets to collect observed css rules\n\t[].forEach.call(document.styleSheets, walkStyleSheet);\n\ttransformObservedItems();\n\n\t// observe DOM modifications that affect selectors\n\tconst mutationObserver = new MutationObserver(mutationsList => {\n\t\tmutationsList.forEach(mutation => {\n\t\t\t[].forEach.call(mutation.addedNodes || [], node => {\n\t\t\t\t// walk stylesheets to collect observed css rules\n\t\t\t\tif (node.nodeType === 1 && node.sheet) {\n\t\t\t\t\twalkStyleSheet(node.sheet);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// transform observed css rules\n\t\t\tcleanupObservedCssRules();\n\t\t\ttransformObservedItems();\n\t\t});\n\t});\n\n\tmutationObserver.observe(document, { childList: true, subtree: true });\n\n\t// observe DOM events that affect pseudo-selectors\n\tdocument.addEventListener('focus', transformObservedItems, true);\n\tdocument.addEventListener('blur', transformObservedItems, true);\n\tdocument.addEventListener('input', transformObservedItems);\n\n\t// transform observed css rules\n\tfunction transformObservedItems() {\n\t\trequestAnimationFrame(() => {\n\t\t\tobservedItems.forEach(\n\t\t\t\titem => {\n\t\t\t\t\tconst nodes = [];\n\n\t\t\t\t\t[].forEach.call(\n\t\t\t\t\t\tdocument.querySelectorAll(item.scopeSelector),\n\t\t\t\t\t\telement => {\n\t\t\t\t\t\t\tconst nthChild = [].indexOf.call(element.parentNode.children, element) + 1;\n\t\t\t\t\t\t\tconst relativeSelectors = item.relativeSelectors.map(\n\t\t\t\t\t\t\t\trelativeSelector => item.scopeSelector + ':nth-child(' + nthChild + ') ' + relativeSelector\n\t\t\t\t\t\t\t).join();\n\n\t\t\t\t\t\t\t// find any relative :has element from the :scope element\n\t\t\t\t\t\t\tconst relativeElement = element.parentNode.querySelector(relativeSelectors);\n\n\t\t\t\t\t\t\tconst shouldElementMatch = item.isNot ? !relativeElement : relativeElement;\n\n\t\t\t\t\t\t\tif (shouldElementMatch) {\n\t\t\t\t\t\t\t\t// memorize the node\n\t\t\t\t\t\t\t\tnodes.push(element);\n\n\t\t\t\t\t\t\t\t// set an attribute with an irregular attribute name\n\t\t\t\t\t\t\t\t// document.createAttribute() doesn't support special characters\n\t\t\t\t\t\t\t\tattributeElement.innerHTML = '<x ' + item.attributeName + '>';\n\n\t\t\t\t\t\t\t\telement.setAttributeNode(attributeElement.children[0].attributes[0].cloneNode());\n\n\t\t\t\t\t\t\t\t// trigger a style refresh in IE and Edge\n\t\t\t\t\t\t\t\tdocument.documentElement.style.zoom = 1; document.documentElement.style.zoom = null;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\t\t// remove the encoded attribute from all nodes that no longer match them\n\t\t\t\t\titem.nodes.forEach(node => {\n\t\t\t\t\t\tif (nodes.indexOf(node) === -1) {\n\t\t\t\t\t\t\tnode.removeAttribute(item.attributeName);\n\n\t\t\t\t\t\t\t// trigger a style refresh in IE and Edge\n\t\t\t\t\t\t\tdocument.documentElement.style.zoom = 1; document.documentElement.style.zoom = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t// update the\n\t\t\t\t\titem.nodes = nodes;\n\t\t\t\t}\n\t\t\t);\n\t\t});\n\t}\n\n\t// remove any observed cssrules that no longer apply\n\tfunction cleanupObservedCssRules() {\n\t\t[].push.apply(\n\t\t\tobservedItems,\n\t\t\tobservedItems.splice(0).filter(\n\t\t\t\titem => item.rule.parentStyleSheet &&\n\t\t\t\t\titem.rule.parentStyleSheet.ownerNode &&\n\t\t\t\t\tdocument.documentElement.contains(item.rule.parentStyleSheet.ownerNode)\n\t\t\t)\n\t\t);\n\t}\n\n\t// walk a stylesheet to collect observed css rules\n\tfunction walkStyleSheet(styleSheet) {\n\t\ttry {\n\t\t\t// walk a css rule to collect observed css rules\n\t\t\t[].forEach.call(styleSheet.cssRules || [], rule => {\n\t\t\t\tif (rule.selectorText) {\n\t\t\t\t\t// decode the selector text in all browsers to:\n\t\t\t\t\t// [1] = :scope, [2] = :not(:has), [3] = :has relative, [4] = :scope relative\n\t\t\t\t\tconst selectors = decodeURIComponent(rule.selectorText.replace(/\\\\(.)/g, '$1')).match(/^(.*?)\\[:(not-)?has\\((.+?)\\)\\](.*?)$/);\n\n\t\t\t\t\tif (selectors) {\n\t\t\t\t\t\tconst attributeName = ':' + (selectors[2] ? 'not-' : '') + 'has(' +\n\t\t\t\t\t\t\t// encode a :has() pseudo selector as an attribute name\n\t\t\t\t\t\t\tencodeURIComponent(selectors[3]).replace(/%3A/g, ':').replace(/%5B/g, '[').replace(/%5D/g, ']').replace(/%2C/g, ',') +\n\t\t\t\t\t\t')';\n\n\t\t\t\t\t\tobservedItems.push({\n\t\t\t\t\t\t\trule,\n\t\t\t\t\t\t\tscopeSelector: selectors[1],\n\t\t\t\t\t\t\tisNot: selectors[2],\n\t\t\t\t\t\t\trelativeSelectors: selectors[3].split(/\\s*,\\s*/),\n\t\t\t\t\t\t\tattributeName,\n\t\t\t\t\t\t\tnodes: []\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\twalkStyleSheet(rule);\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\t/* do nothing and continue */\n\t\t}\n\t}\n}\n"],"names":["cssHasPseudo","document","observedItems","attributeElement","createElement","forEach","call","styleSheets","walkStyleSheet","transformObservedItems","mutationObserver","MutationObserver","mutationsList","mutation","addedNodes","node","nodeType","sheet","cleanupObservedCssRules","observe","childList","subtree","addEventListener","requestAnimationFrame","item","nodes","querySelectorAll","scopeSelector","element","nthChild","indexOf","parentNode","children","relativeSelectors","map","relativeSelector","join","relativeElement","querySelector","shouldElementMatch","isNot","push","innerHTML","attributeName","setAttributeNode","attributes","cloneNode","documentElement","style","zoom","removeAttribute","apply","splice","filter","rule","parentStyleSheet","ownerNode","contains","styleSheet","cssRules","selectorText","selectors","decodeURIComponent","replace","match","encodeURIComponent","split","error"],"mappings":"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"}
|
package/index.mjs
CHANGED
|
@@ -3,12 +3,12 @@ function cssHasPseudo(document) {
|
|
|
3
3
|
|
|
4
4
|
const attributeElement = document.createElement('x'); // walk all stylesheets to collect observed css rules
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
[].forEach.call(document.styleSheets, walkStyleSheet);
|
|
7
7
|
transformObservedItems(); // observe DOM modifications that affect selectors
|
|
8
8
|
|
|
9
9
|
const mutationObserver = new MutationObserver(mutationsList => {
|
|
10
10
|
mutationsList.forEach(mutation => {
|
|
11
|
-
|
|
11
|
+
[].forEach.call(mutation.addedNodes || [], node => {
|
|
12
12
|
// walk stylesheets to collect observed css rules
|
|
13
13
|
if (node.nodeType === 1 && node.sheet) {
|
|
14
14
|
walkStyleSheet(node.sheet);
|
|
@@ -32,8 +32,8 @@ function cssHasPseudo(document) {
|
|
|
32
32
|
requestAnimationFrame(() => {
|
|
33
33
|
observedItems.forEach(item => {
|
|
34
34
|
const nodes = [];
|
|
35
|
-
|
|
36
|
-
const nthChild =
|
|
35
|
+
[].forEach.call(document.querySelectorAll(item.scopeSelector), element => {
|
|
36
|
+
const nthChild = [].indexOf.call(element.parentNode.children, element) + 1;
|
|
37
37
|
const relativeSelectors = item.relativeSelectors.map(relativeSelector => item.scopeSelector + ':nth-child(' + nthChild + ') ' + relativeSelector).join(); // find any relative :has element from the :scope element
|
|
38
38
|
|
|
39
39
|
const relativeElement = element.parentNode.querySelector(relativeSelectors);
|
|
@@ -68,34 +68,38 @@ function cssHasPseudo(document) {
|
|
|
68
68
|
|
|
69
69
|
|
|
70
70
|
function cleanupObservedCssRules() {
|
|
71
|
-
|
|
71
|
+
[].push.apply(observedItems, observedItems.splice(0).filter(item => item.rule.parentStyleSheet && item.rule.parentStyleSheet.ownerNode && document.documentElement.contains(item.rule.parentStyleSheet.ownerNode)));
|
|
72
72
|
} // walk a stylesheet to collect observed css rules
|
|
73
73
|
|
|
74
74
|
|
|
75
75
|
function walkStyleSheet(styleSheet) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
76
|
+
try {
|
|
77
|
+
// walk a css rule to collect observed css rules
|
|
78
|
+
[].forEach.call(styleSheet.cssRules || [], rule => {
|
|
79
|
+
if (rule.selectorText) {
|
|
80
|
+
// decode the selector text in all browsers to:
|
|
81
|
+
// [1] = :scope, [2] = :not(:has), [3] = :has relative, [4] = :scope relative
|
|
82
|
+
const selectors = decodeURIComponent(rule.selectorText.replace(/\\(.)/g, '$1')).match(/^(.*?)\[:(not-)?has\((.+?)\)\](.*?)$/);
|
|
83
|
+
|
|
84
|
+
if (selectors) {
|
|
85
|
+
const attributeName = ':' + (selectors[2] ? 'not-' : '') + 'has(' + // encode a :has() pseudo selector as an attribute name
|
|
86
|
+
encodeURIComponent(selectors[3]).replace(/%3A/g, ':').replace(/%5B/g, '[').replace(/%5D/g, ']').replace(/%2C/g, ',') + ')';
|
|
87
|
+
observedItems.push({
|
|
88
|
+
rule,
|
|
89
|
+
scopeSelector: selectors[1],
|
|
90
|
+
isNot: selectors[2],
|
|
91
|
+
relativeSelectors: selectors[3].split(/\s*,\s*/),
|
|
92
|
+
attributeName,
|
|
93
|
+
nodes: []
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
walkStyleSheet(rule);
|
|
94
98
|
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
+
});
|
|
100
|
+
} catch (error) {
|
|
101
|
+
/* do nothing and continue */
|
|
102
|
+
}
|
|
99
103
|
}
|
|
100
104
|
}
|
|
101
105
|
|
package/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["src/browser.js"],"sourcesContent":["export default function cssHasPseudo(document) {\n\tconst observedItems = [];\n\n\t// document.createAttribute() doesn't support `:` in the name. innerHTML does\n\tconst attributeElement = document.createElement('x');\n\n\t// walk all stylesheets to collect observed css rules\n\
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["src/browser.js"],"sourcesContent":["export default function cssHasPseudo(document) {\n\tconst observedItems = [];\n\n\t// document.createAttribute() doesn't support `:` in the name. innerHTML does\n\tconst attributeElement = document.createElement('x');\n\n\t// walk all stylesheets to collect observed css rules\n\t[].forEach.call(document.styleSheets, walkStyleSheet);\n\ttransformObservedItems();\n\n\t// observe DOM modifications that affect selectors\n\tconst mutationObserver = new MutationObserver(mutationsList => {\n\t\tmutationsList.forEach(mutation => {\n\t\t\t[].forEach.call(mutation.addedNodes || [], node => {\n\t\t\t\t// walk stylesheets to collect observed css rules\n\t\t\t\tif (node.nodeType === 1 && node.sheet) {\n\t\t\t\t\twalkStyleSheet(node.sheet);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// transform observed css rules\n\t\t\tcleanupObservedCssRules();\n\t\t\ttransformObservedItems();\n\t\t});\n\t});\n\n\tmutationObserver.observe(document, { childList: true, subtree: true });\n\n\t// observe DOM events that affect pseudo-selectors\n\tdocument.addEventListener('focus', transformObservedItems, true);\n\tdocument.addEventListener('blur', transformObservedItems, true);\n\tdocument.addEventListener('input', transformObservedItems);\n\n\t// transform observed css rules\n\tfunction transformObservedItems() {\n\t\trequestAnimationFrame(() => {\n\t\t\tobservedItems.forEach(\n\t\t\t\titem => {\n\t\t\t\t\tconst nodes = [];\n\n\t\t\t\t\t[].forEach.call(\n\t\t\t\t\t\tdocument.querySelectorAll(item.scopeSelector),\n\t\t\t\t\t\telement => {\n\t\t\t\t\t\t\tconst nthChild = [].indexOf.call(element.parentNode.children, element) + 1;\n\t\t\t\t\t\t\tconst relativeSelectors = item.relativeSelectors.map(\n\t\t\t\t\t\t\t\trelativeSelector => item.scopeSelector + ':nth-child(' + nthChild + ') ' + relativeSelector\n\t\t\t\t\t\t\t).join();\n\n\t\t\t\t\t\t\t// find any relative :has element from the :scope element\n\t\t\t\t\t\t\tconst relativeElement = element.parentNode.querySelector(relativeSelectors);\n\n\t\t\t\t\t\t\tconst shouldElementMatch = item.isNot ? !relativeElement : relativeElement;\n\n\t\t\t\t\t\t\tif (shouldElementMatch) {\n\t\t\t\t\t\t\t\t// memorize the node\n\t\t\t\t\t\t\t\tnodes.push(element);\n\n\t\t\t\t\t\t\t\t// set an attribute with an irregular attribute name\n\t\t\t\t\t\t\t\t// document.createAttribute() doesn't support special characters\n\t\t\t\t\t\t\t\tattributeElement.innerHTML = '<x ' + item.attributeName + '>';\n\n\t\t\t\t\t\t\t\telement.setAttributeNode(attributeElement.children[0].attributes[0].cloneNode());\n\n\t\t\t\t\t\t\t\t// trigger a style refresh in IE and Edge\n\t\t\t\t\t\t\t\tdocument.documentElement.style.zoom = 1; document.documentElement.style.zoom = null;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\t\t// remove the encoded attribute from all nodes that no longer match them\n\t\t\t\t\titem.nodes.forEach(node => {\n\t\t\t\t\t\tif (nodes.indexOf(node) === -1) {\n\t\t\t\t\t\t\tnode.removeAttribute(item.attributeName);\n\n\t\t\t\t\t\t\t// trigger a style refresh in IE and Edge\n\t\t\t\t\t\t\tdocument.documentElement.style.zoom = 1; document.documentElement.style.zoom = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t// update the\n\t\t\t\t\titem.nodes = nodes;\n\t\t\t\t}\n\t\t\t);\n\t\t});\n\t}\n\n\t// remove any observed cssrules that no longer apply\n\tfunction cleanupObservedCssRules() {\n\t\t[].push.apply(\n\t\t\tobservedItems,\n\t\t\tobservedItems.splice(0).filter(\n\t\t\t\titem => item.rule.parentStyleSheet &&\n\t\t\t\t\titem.rule.parentStyleSheet.ownerNode &&\n\t\t\t\t\tdocument.documentElement.contains(item.rule.parentStyleSheet.ownerNode)\n\t\t\t)\n\t\t);\n\t}\n\n\t// walk a stylesheet to collect observed css rules\n\tfunction walkStyleSheet(styleSheet) {\n\t\ttry {\n\t\t\t// walk a css rule to collect observed css rules\n\t\t\t[].forEach.call(styleSheet.cssRules || [], rule => {\n\t\t\t\tif (rule.selectorText) {\n\t\t\t\t\t// decode the selector text in all browsers to:\n\t\t\t\t\t// [1] = :scope, [2] = :not(:has), [3] = :has relative, [4] = :scope relative\n\t\t\t\t\tconst selectors = decodeURIComponent(rule.selectorText.replace(/\\\\(.)/g, '$1')).match(/^(.*?)\\[:(not-)?has\\((.+?)\\)\\](.*?)$/);\n\n\t\t\t\t\tif (selectors) {\n\t\t\t\t\t\tconst attributeName = ':' + (selectors[2] ? 'not-' : '') + 'has(' +\n\t\t\t\t\t\t\t// encode a :has() pseudo selector as an attribute name\n\t\t\t\t\t\t\tencodeURIComponent(selectors[3]).replace(/%3A/g, ':').replace(/%5B/g, '[').replace(/%5D/g, ']').replace(/%2C/g, ',') +\n\t\t\t\t\t\t')';\n\n\t\t\t\t\t\tobservedItems.push({\n\t\t\t\t\t\t\trule,\n\t\t\t\t\t\t\tscopeSelector: selectors[1],\n\t\t\t\t\t\t\tisNot: selectors[2],\n\t\t\t\t\t\t\trelativeSelectors: selectors[3].split(/\\s*,\\s*/),\n\t\t\t\t\t\t\tattributeName,\n\t\t\t\t\t\t\tnodes: []\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\twalkStyleSheet(rule);\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\t/* do nothing and continue */\n\t\t}\n\t}\n}\n"],"names":["cssHasPseudo","document","observedItems","attributeElement","createElement","forEach","call","styleSheets","walkStyleSheet","transformObservedItems","mutationObserver","MutationObserver","mutationsList","mutation","addedNodes","node","nodeType","sheet","cleanupObservedCssRules","observe","childList","subtree","addEventListener","requestAnimationFrame","item","nodes","querySelectorAll","scopeSelector","element","nthChild","indexOf","parentNode","children","relativeSelectors","map","relativeSelector","join","relativeElement","querySelector","shouldElementMatch","isNot","push","innerHTML","attributeName","setAttributeNode","attributes","cloneNode","documentElement","style","zoom","removeAttribute","apply","splice","filter","rule","parentStyleSheet","ownerNode","contains","styleSheet","cssRules","selectorText","selectors","decodeURIComponent","replace","match","encodeURIComponent","split","error"],"mappings":"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"}
|