|
1 | 1 | import multimatch from 'multimatch'; |
2 | 2 |
|
| 3 | +import postcss from 'postcss'; |
3 | 4 | import BrowserSelection from './BrowserSelection.js'; |
4 | 5 | import Detector from './Detector.js'; |
5 | 6 |
|
@@ -101,6 +102,38 @@ export default class DoIUse { |
101 | 102 | if (overwritees.length > 0) { |
102 | 103 | return; |
103 | 104 | } |
| 105 | + |
| 106 | + // find the closest @supports parent |
| 107 | + /** @type {any} TODO Type this */ |
| 108 | + let supports = usage.parent; |
| 109 | + while (supports && supports.type !== 'atrule' && supports.name !== 'supports') { |
| 110 | + supports = supports.parent; |
| 111 | + } |
| 112 | + if (supports) { |
| 113 | + // FIXME This is a very, VERY dirty hack |
| 114 | + // FIXME Handle e.g. `@supporst (content: ') and ('`) |
| 115 | + // TODO Report an warning if condition is too complex for us to understand |
| 116 | + // TODO Support `or`? |
| 117 | + // TODO Support nested brackets? |
| 118 | + const temporaryDeclarations = supports.params |
| 119 | + .split(/(?<=\))\s*and\s*(?=\()/g) |
| 120 | + .map((part) => part.trim().replaceAll(/^\(|\)$/g, '')) |
| 121 | + .filter((part) => !/^\s*not\s+/i.test(part)); |
| 122 | + |
| 123 | + const temporaryCss = `i { ${temporaryDeclarations.join(';\n')} }`; |
| 124 | + const temporaryCssTree = postcss.parse(temporaryCss); |
| 125 | + const supportsDetector = new Detector([feature]); |
| 126 | + const safeToUseFeatures = []; |
| 127 | + supportsDetector.process( |
| 128 | + temporaryCssTree, |
| 129 | + ({ feature: supportsFeature }) => { |
| 130 | + safeToUseFeatures.push(supportsFeature); |
| 131 | + }, |
| 132 | + ); |
| 133 | + if (safeToUseFeatures.includes(feature)) { |
| 134 | + return; |
| 135 | + } |
| 136 | + } |
104 | 137 | } |
105 | 138 |
|
106 | 139 | const messages = []; |
|
0 commit comments