@automattic/jetpack-critical-css-gen 0.1.0 → 1.0.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +15 -1
  2. package/package.json +17 -20
  3. package/build-browser/bundle.full.js +0 -37567
  4. package/build-browser/bundle.full.js.map +0 -1
  5. package/build-browser/bundle.js +0 -4
  6. package/build-browser/bundle.js.map +0 -1
  7. package/build-node/browser-interface-playwright.d.ts +0 -53
  8. package/build-node/browser-interface-playwright.js +0 -94
  9. package/build-node/browser-interface-playwright.js.map +0 -1
  10. package/build-node/browser-interface.d.ts +0 -77
  11. package/build-node/browser-interface.js +0 -124
  12. package/build-node/browser-interface.js.map +0 -1
  13. package/build-node/css-file-set.d.ts +0 -100
  14. package/build-node/css-file-set.js +0 -210
  15. package/build-node/css-file-set.js.map +0 -1
  16. package/build-node/errors.d.ts +0 -101
  17. package/build-node/errors.js +0 -103
  18. package/build-node/errors.js.map +0 -1
  19. package/build-node/generate-critical-css.d.ts +0 -24
  20. package/build-node/generate-critical-css.js +0 -162
  21. package/build-node/generate-critical-css.js.map +0 -1
  22. package/build-node/ignored-pseudo-elements.d.ts +0 -8
  23. package/build-node/ignored-pseudo-elements.js +0 -35
  24. package/build-node/ignored-pseudo-elements.js.map +0 -1
  25. package/build-node/minify-css.d.ts +0 -11
  26. package/build-node/minify-css.js +0 -19
  27. package/build-node/minify-css.js.map +0 -1
  28. package/build-node/node.d.ts +0 -5
  29. package/build-node/node.js +0 -6
  30. package/build-node/node.js.map +0 -1
  31. package/build-node/object-promise-all.d.ts +0 -12
  32. package/build-node/object-promise-all.js +0 -16
  33. package/build-node/object-promise-all.js.map +0 -1
  34. package/build-node/style-ast.d.ts +0 -164
  35. package/build-node/style-ast.js +0 -540
  36. package/build-node/style-ast.js.map +0 -1
  37. package/build-node/types.d.ts +0 -14
  38. package/build-node/types.js +0 -2
  39. package/build-node/types.js.map +0 -1
@@ -1,164 +0,0 @@
1
- import * as csstree from 'css-tree';
2
- import { AtRuleFilter, FilterSpec, PropertiesFilter } from './types.js';
3
- /**
4
- * Represents an Abstract Syntax Tree for a CSS file (as generated by css-tree) and contains helper
5
- * methods for pruning and rearranging it.
6
- */
7
- export declare class StyleAST {
8
- private css;
9
- private ast;
10
- private errors;
11
- constructor(css: string, ast: csstree.CssNode, errors: Error[]);
12
- /**
13
- * Given a base URL (where the CSS file this AST was built from), find all relative URLs and
14
- * convert them to absolute.
15
- *
16
- * @param {string} base - base URL for relative URLs.
17
- */
18
- absolutifyUrls(base: string): void;
19
- /**
20
- * Returns a new StyleAST with content from this one pruned based on the specified contentWindow
21
- * and criticalSelectors to keep.
22
- *
23
- * Removes:
24
- * - Irrelevant media queries
25
- * - Selectors not included in criticalSelectors
26
- * - Excluded properties
27
- * - Large embeds
28
- * - Empty rules
29
- *
30
- * @param {Set< string >} criticalSelectors - Set of selectors to keep in the new AST.
31
- *
32
- * @return {StyleAST} - New AST with pruned contents.
33
- */
34
- pruned(criticalSelectors: Set<string>): StyleAST;
35
- /**
36
- * Given an AST node, returns the original text it was compiled from in the source CSS.
37
- *
38
- * @param {object} node - Node from the AST.
39
- * @return {string} original text the node was compiled from.
40
- */
41
- originalText(node: csstree.CssNode): string;
42
- /**
43
- * Applies filters to the properties or atRules in this AST. Mutates the AST in-place.
44
- *
45
- * @param {FilterSpec} filters - Object containing property and atRule filter functions.
46
- */
47
- applyFilters(filters: FilterSpec): void;
48
- /**
49
- * Applies a filter to the properties in this AST. Mutates the AST in-place.
50
- *
51
- * @param {Function} filter - to apply.
52
- */
53
- applyPropertiesFilter(filter: PropertiesFilter): void;
54
- /**
55
- * Applies a filter to the atRules in this AST. Mutates the AST in-place.
56
- *
57
- * @param {Function} filter - to apply.
58
- */
59
- applyAtRulesFilter(filter: AtRuleFilter): void;
60
- /**
61
- * Remove variables that do not appear in the usedVariables set. Returns a count of variables
62
- * that were removed.
63
- *
64
- * @param {Set< string >} usedVariables - Set of used variables to keep.
65
- * @return {number} variables pruned.
66
- */
67
- pruneUnusedVariables(usedVariables: Set<string>): number;
68
- /**
69
- * Find all variables that are used and return them as a Set.
70
- * @return {Set< string >} Set of used variables.
71
- */
72
- getUsedVariables(): Set<string>;
73
- /**
74
- * Remove all comments from the syntax tree.
75
- */
76
- pruneComments(): void;
77
- /**
78
- * Remove media queries that only apply to print.
79
- */
80
- pruneMediaQueries(): void;
81
- /**
82
- * Remove unwanted at-rules.
83
- *
84
- * @param { string[] } names - Names of at-rules to remove, excluding the at symbol.
85
- */
86
- pruneAtRules(names: string[]): void;
87
- /**
88
- * Returns true if the given CSS rule object relates to animation keyframes.
89
- *
90
- * @param {csstree.WalkContext} rule - CSS rule.
91
- * @return {boolean} True if the rule is a keyframe rule, false otherwise.
92
- */
93
- static isKeyframeRule(rule: csstree.WalkContext): boolean;
94
- /**
95
- * Walks this AST and calls the specified callback with each selector found (as text).
96
- * Skips any selectors in the excludedSelectors constant.
97
- *
98
- * @param {Function} callback - Callback to call with each selector.
99
- */
100
- forEachSelector(callback: (selector: string) => void): void;
101
- /**
102
- * Remove any selectors not listed in the criticalSelectors set, deleting any
103
- * rules that no longer have any selectors in their prelude.
104
- *
105
- * @param {Set< string >} criticalSelector - Set of critical selectors.
106
- */
107
- pruneNonCriticalSelectors(criticalSelector: Set<string>): void;
108
- /**
109
- * Remove any Base64 embedded content which exceeds maxBase64Length.
110
- */
111
- pruneLargeBase64Embeds(): void;
112
- /**
113
- * Remove any properties that match the regular expressions in the excludedProperties constant.
114
- */
115
- pruneExcludedProperties(): void;
116
- /**
117
- * Remove any fonts which are not in the specified whitelist.
118
- *
119
- * @param {Set< string >} fontWhitelist - Whitelisted font.
120
- */
121
- pruneNonCriticalFonts(fontWhitelist: Set<string>): void;
122
- /**
123
- * Returns a count of the rules in this Style AST.
124
- *
125
- * @return {number} rules in this AST.
126
- */
127
- ruleCount(): number;
128
- /**
129
- * Returns a list of font families that are used by any rule in this AST.
130
- *
131
- * @return {Set<string>} Set of used fonts.
132
- */
133
- getUsedFontFamilies(): Set<string>;
134
- /**
135
- * Given an AST node, read it as a value based on its type. Removes quote marks from
136
- * string types if present.
137
- *
138
- * @param {csstree.CssNode} node - AST node.
139
- * @return {string} The value of the node as a string.
140
- */
141
- static readValue(node: csstree.CssNode): string;
142
- /**
143
- * Returns true if the specified media query node is relevant to screen rendering.
144
- *
145
- * @param {object} mediaQueryNode - Media Query AST node to examine.
146
- *
147
- * @return {boolean} true if the media query is relevant to screens.
148
- */
149
- static isUsefulMediaQuery(mediaQueryNode: csstree.MediaQuery): boolean;
150
- /**
151
- * Returns this AST converted to CSS.
152
- *
153
- * @return {string} this AST represented in CSS.
154
- */
155
- toCSS(): string;
156
- /**
157
- * Static method to parse a block of CSS and return a new StyleAST object which represents it.
158
- *
159
- * @param {string} css - CSS to parse.
160
- *
161
- * @return {StyleAST} new parse AST based on the CSS.
162
- */
163
- static parse(css: string): StyleAST;
164
- }
@@ -1,540 +0,0 @@
1
- import * as csstree from 'css-tree';
2
- const validMediaTypes = ['all', 'print', 'screen', 'speech'];
3
- const base64Pattern = /data:[^,]*;base64,/;
4
- const stringPattern = /^(["']).*\1$/;
5
- const maxBase64Length = 1000;
6
- const excludedSelectors = [/::?(?:-moz-)?selection/];
7
- const excludedProperties = [
8
- /(.*)animation/,
9
- /(.*)transition(.*)/,
10
- /cursor/,
11
- /pointer-events/,
12
- /(-webkit-)?tap-highlight-color/,
13
- /(.*)user-select/,
14
- ];
15
- /**
16
- * Checks if the given node is a CSS declaration.
17
- * @param {csstree.CssNode} node - The CSS node to check.
18
- * @return {boolean} True if the node is a CSS declaration, false otherwise.
19
- */
20
- function isDeclaration(node) {
21
- return node.type === 'Declaration';
22
- }
23
- /**
24
- * Checks if the given node has an empty child list.
25
- * @param {csstree.CssNode} node - The CSS node to check.
26
- * @return {boolean} True if the node has an empty child list, false otherwise.
27
- */
28
- function hasEmptyChildList(node) {
29
- if ('children' in node && node.children instanceof csstree.List) {
30
- return node.children.isEmpty;
31
- }
32
- return false;
33
- }
34
- /**
35
- * Represents an Abstract Syntax Tree for a CSS file (as generated by css-tree) and contains helper
36
- * methods for pruning and rearranging it.
37
- */
38
- export class StyleAST {
39
- // eslint-disable-next-line no-useless-constructor
40
- constructor(css, ast, errors) {
41
- this.css = css;
42
- this.ast = ast;
43
- this.errors = errors;
44
- }
45
- /**
46
- * Given a base URL (where the CSS file this AST was built from), find all relative URLs and
47
- * convert them to absolute.
48
- *
49
- * @param {string} base - base URL for relative URLs.
50
- */
51
- absolutifyUrls(base) {
52
- csstree.walk(this.ast, {
53
- visit: 'Url',
54
- enter: url => {
55
- if (url.value) {
56
- const value = StyleAST.readValue(url);
57
- const absolute = new URL(value, base).toString();
58
- if (absolute !== value) {
59
- url.value = absolute;
60
- }
61
- }
62
- },
63
- });
64
- }
65
- /**
66
- * Returns a new StyleAST with content from this one pruned based on the specified contentWindow
67
- * and criticalSelectors to keep.
68
- *
69
- * Removes:
70
- * - Irrelevant media queries
71
- * - Selectors not included in criticalSelectors
72
- * - Excluded properties
73
- * - Large embeds
74
- * - Empty rules
75
- *
76
- * @param {Set< string >} criticalSelectors - Set of selectors to keep in the new AST.
77
- *
78
- * @return {StyleAST} - New AST with pruned contents.
79
- */
80
- pruned(criticalSelectors) {
81
- const clone = new StyleAST(this.css, csstree.clone(this.ast), this.errors);
82
- clone.pruneMediaQueries();
83
- clone.pruneAtRules(['keyframes', 'charset', 'import']);
84
- clone.pruneNonCriticalSelectors(criticalSelectors);
85
- clone.pruneExcludedProperties();
86
- clone.pruneLargeBase64Embeds();
87
- clone.pruneComments();
88
- return clone;
89
- }
90
- /**
91
- * Given an AST node, returns the original text it was compiled from in the source CSS.
92
- *
93
- * @param {object} node - Node from the AST.
94
- * @return {string} original text the node was compiled from.
95
- */
96
- originalText(node) {
97
- if (node.loc && node.loc.start && node.loc.end) {
98
- return this.css.substring(node.loc.start.offset, node.loc.end.offset);
99
- }
100
- return '';
101
- }
102
- /**
103
- * Applies filters to the properties or atRules in this AST. Mutates the AST in-place.
104
- *
105
- * @param {FilterSpec} filters - Object containing property and atRule filter functions.
106
- */
107
- applyFilters(filters) {
108
- if (!filters) {
109
- return;
110
- }
111
- if (filters.properties) {
112
- this.applyPropertiesFilter(filters.properties);
113
- }
114
- if (filters.atRules) {
115
- this.applyAtRulesFilter(filters.atRules);
116
- }
117
- }
118
- /**
119
- * Applies a filter to the properties in this AST. Mutates the AST in-place.
120
- *
121
- * @param {Function} filter - to apply.
122
- */
123
- applyPropertiesFilter(filter) {
124
- csstree.walk(this.ast, {
125
- visit: 'Declaration',
126
- enter: (declaration, item, list) => {
127
- if (filter(declaration.property, this.originalText(declaration.value)) === false) {
128
- list.remove(item);
129
- }
130
- },
131
- });
132
- }
133
- /**
134
- * Applies a filter to the atRules in this AST. Mutates the AST in-place.
135
- *
136
- * @param {Function} filter - to apply.
137
- */
138
- applyAtRulesFilter(filter) {
139
- csstree.walk(this.ast, {
140
- visit: 'Atrule',
141
- enter: (atrule, item, list) => {
142
- if (filter(atrule.name) === false) {
143
- list.remove(item);
144
- }
145
- },
146
- });
147
- }
148
- /**
149
- * Remove variables that do not appear in the usedVariables set. Returns a count of variables
150
- * that were removed.
151
- *
152
- * @param {Set< string >} usedVariables - Set of used variables to keep.
153
- * @return {number} variables pruned.
154
- */
155
- pruneUnusedVariables(usedVariables) {
156
- let pruned = 0;
157
- csstree.walk(this.ast, {
158
- visit: 'Declaration',
159
- enter: (declaration, item, list) => {
160
- // Ignore declarations that aren't defining variables.
161
- if (!declaration.property.startsWith('--')) {
162
- return;
163
- }
164
- // Check if this declared variable is used.
165
- if (usedVariables.has(declaration.property)) {
166
- return;
167
- }
168
- // Prune unused variable.
169
- list.remove(item);
170
- pruned++;
171
- },
172
- });
173
- return pruned;
174
- }
175
- /**
176
- * Find all variables that are used and return them as a Set.
177
- * @return {Set< string >} Set of used variables.
178
- */
179
- getUsedVariables() {
180
- const usedVariables = new Set();
181
- csstree.walk(this.ast, {
182
- visit: 'Function',
183
- enter: func => {
184
- // Ignore functions that aren't var()
185
- if (csstree.keyword(func.name).name !== 'var') {
186
- return;
187
- }
188
- const names = func.children.map(StyleAST.readValue);
189
- names.forEach(name => usedVariables.add(name));
190
- },
191
- });
192
- return usedVariables;
193
- }
194
- /**
195
- * Remove all comments from the syntax tree.
196
- */
197
- pruneComments() {
198
- csstree.walk(this.ast, {
199
- visit: 'Comment',
200
- enter: (_, item, list) => {
201
- list.remove(item);
202
- },
203
- });
204
- }
205
- /**
206
- * Remove media queries that only apply to print.
207
- */
208
- pruneMediaQueries() {
209
- csstree.walk(this.ast, {
210
- visit: 'Atrule',
211
- enter: (atrule, atitem, atlist) => {
212
- // Ignore non-media and invalid atrules.
213
- if (csstree.keyword(atrule.name).name !== 'media' || !atrule.prelude) {
214
- return;
215
- }
216
- // Go through all MediaQueryLists (should be one, but let's be sure).
217
- csstree.walk(atrule, {
218
- visit: 'MediaQueryList',
219
- enter: (mqrule, mqitem, mqlist) => {
220
- // Filter out MediaQueries that aren't interesting.
221
- csstree.walk(mqrule, {
222
- visit: 'MediaQuery',
223
- enter: (mediaQuery, mediaItem, mediaList) => {
224
- if (!StyleAST.isUsefulMediaQuery(mediaQuery)) {
225
- mediaList.remove(mediaItem);
226
- }
227
- },
228
- });
229
- // If empty MQ, remove from parent.
230
- if (hasEmptyChildList(mqrule)) {
231
- mqlist.remove(mqitem);
232
- }
233
- },
234
- });
235
- // If there are no useful media query lists left, throw away the block.
236
- if (hasEmptyChildList(atrule.prelude)) {
237
- atlist.remove(atitem);
238
- }
239
- },
240
- });
241
- }
242
- /**
243
- * Remove unwanted at-rules.
244
- *
245
- * @param { string[] } names - Names of at-rules to remove, excluding the at symbol.
246
- */
247
- pruneAtRules(names) {
248
- csstree.walk(this.ast, {
249
- visit: 'Atrule',
250
- enter: (atrule, atitem, atlist) => {
251
- if (names.includes(csstree.keyword(atrule.name).basename)) {
252
- atlist.remove(atitem);
253
- }
254
- },
255
- });
256
- }
257
- /**
258
- * Returns true if the given CSS rule object relates to animation keyframes.
259
- *
260
- * @param {csstree.WalkContext} rule - CSS rule.
261
- * @return {boolean} True if the rule is a keyframe rule, false otherwise.
262
- */
263
- static isKeyframeRule(rule) {
264
- return (rule.atrule && csstree.keyword(rule.atrule.name).basename === 'keyframes') || false;
265
- }
266
- /**
267
- * Walks this AST and calls the specified callback with each selector found (as text).
268
- * Skips any selectors in the excludedSelectors constant.
269
- *
270
- * @param {Function} callback - Callback to call with each selector.
271
- */
272
- forEachSelector(callback) {
273
- csstree.walk(this.ast, {
274
- visit: 'Rule',
275
- enter(rule) {
276
- // Ignore rules inside @keyframes.
277
- if (StyleAST.isKeyframeRule(this)) {
278
- return;
279
- }
280
- // Ignore invalid rules.
281
- if (rule.prelude.type !== 'SelectorList') {
282
- return;
283
- }
284
- // Go through all selectors, filtering out unwanted ones.
285
- rule.prelude.children.forEach(child => {
286
- const selector = csstree.generate(child);
287
- if (!excludedSelectors.some(s => s.test(selector))) {
288
- callback(selector);
289
- }
290
- });
291
- },
292
- });
293
- }
294
- /**
295
- * Remove any selectors not listed in the criticalSelectors set, deleting any
296
- * rules that no longer have any selectors in their prelude.
297
- *
298
- * @param {Set< string >} criticalSelector - Set of critical selectors.
299
- */
300
- pruneNonCriticalSelectors(criticalSelector) {
301
- csstree.walk(this.ast, {
302
- visit: 'Rule',
303
- enter(rule, item, list) {
304
- // Ignore rules inside @keyframes... until later.
305
- if (this.atrule && csstree.keyword(this.atrule.name).basename === 'keyframes') {
306
- return;
307
- }
308
- // Remove invalid rules.
309
- if (rule.prelude.type !== 'SelectorList') {
310
- list.remove(item);
311
- return;
312
- }
313
- // Always include any rule that uses the grid-area property.
314
- if (rule.block.children.some(propertyNode => isDeclaration(propertyNode) && propertyNode.property === 'grid-area')) {
315
- return;
316
- }
317
- // Prune any selectors that aren't used.
318
- rule.prelude.children = rule.prelude.children.filter(selector => {
319
- // Prune selectors marked to always remove.
320
- if (excludedSelectors.some(s => s.test(csstree.generate(selector)))) {
321
- return false;
322
- }
323
- const selectorText = csstree.generate(selector);
324
- return criticalSelector.has(selectorText);
325
- });
326
- // If the selector list is empty, prune the whole rule.
327
- if (hasEmptyChildList(rule.prelude)) {
328
- list.remove(item);
329
- }
330
- },
331
- });
332
- }
333
- /**
334
- * Remove any Base64 embedded content which exceeds maxBase64Length.
335
- */
336
- pruneLargeBase64Embeds() {
337
- csstree.walk(this.ast, {
338
- visit: 'Declaration',
339
- enter: (declaration, item, list) => {
340
- let tooLong = false;
341
- csstree.walk(declaration, {
342
- visit: 'Url',
343
- enter(url) {
344
- const value = url.value;
345
- if (base64Pattern.test(value) && value.length > maxBase64Length) {
346
- tooLong = true;
347
- }
348
- },
349
- });
350
- if (tooLong) {
351
- list.remove(item);
352
- }
353
- },
354
- });
355
- }
356
- /**
357
- * Remove any properties that match the regular expressions in the excludedProperties constant.
358
- */
359
- pruneExcludedProperties() {
360
- csstree.walk(this.ast, {
361
- visit: 'Declaration',
362
- enter: (declaration, item, list) => {
363
- if (declaration.property) {
364
- const property = csstree.property(declaration.property).name;
365
- if (excludedProperties.some(e => e.test(property))) {
366
- list.remove(item);
367
- }
368
- }
369
- },
370
- });
371
- }
372
- /**
373
- * Remove any fonts which are not in the specified whitelist.
374
- *
375
- * @param {Set< string >} fontWhitelist - Whitelisted font.
376
- */
377
- pruneNonCriticalFonts(fontWhitelist) {
378
- csstree.walk(this.ast, {
379
- visit: 'Atrule',
380
- enter: (atrule, item, list) => {
381
- // Skip rules that aren't @font-face...
382
- if (csstree.keyword(atrule.name).basename !== 'font-face') {
383
- return;
384
- }
385
- // Find src and font-family.
386
- const properties = {};
387
- csstree.walk(atrule, {
388
- visit: 'Declaration',
389
- enter: (declaration, decItem, decList) => {
390
- const property = csstree.property(declaration.property).name;
391
- if (['src', 'font-family'].includes(property) &&
392
- 'children' in declaration.value) {
393
- const values = declaration.value.children.toArray();
394
- properties[property] = values.map(StyleAST.readValue);
395
- }
396
- // Prune out src from result.
397
- if (property === 'src') {
398
- decList.remove(decItem);
399
- }
400
- },
401
- });
402
- // Remove font-face rules without a src and font-family.
403
- if (!properties.src || !properties['font-family']) {
404
- list.remove(item);
405
- return;
406
- }
407
- // Prune if none of the font-family values are in the whitelist.
408
- if (!properties['font-family'].some(family => fontWhitelist.has(family))) {
409
- list.remove(item);
410
- }
411
- },
412
- });
413
- }
414
- /**
415
- * Returns a count of the rules in this Style AST.
416
- *
417
- * @return {number} rules in this AST.
418
- */
419
- ruleCount() {
420
- let rules = 0;
421
- csstree.walk(this.ast, {
422
- visit: 'Rule',
423
- enter: () => {
424
- rules++;
425
- },
426
- });
427
- return rules;
428
- }
429
- /**
430
- * Returns a list of font families that are used by any rule in this AST.
431
- *
432
- * @return {Set<string>} Set of used fonts.
433
- */
434
- getUsedFontFamilies() {
435
- const fontFamilies = new Set();
436
- csstree.walk(this.ast, {
437
- visit: 'Declaration',
438
- enter(node) {
439
- // Ignore declarations not inside rules.
440
- if (!this.rule) {
441
- return;
442
- }
443
- // Pull the lexer out of csstree. Note: the types don't include
444
- // this, so we have to hack it with any :(
445
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
446
- const lexer = csstree.lexer;
447
- // Gather family-name values.
448
- const frags = lexer.findDeclarationValueFragments(node, 'Type', 'family-name');
449
- const nodes = frags.map(frag => frag.nodes.toArray()).flat();
450
- const names = nodes.map(StyleAST.readValue);
451
- names.forEach(name => fontFamilies.add(name));
452
- },
453
- });
454
- return fontFamilies;
455
- }
456
- /**
457
- * Given an AST node, read it as a value based on its type. Removes quote marks from
458
- * string types if present.
459
- *
460
- * @param {csstree.CssNode} node - AST node.
461
- * @return {string} The value of the node as a string.
462
- */
463
- static readValue(node) {
464
- if (node.type === 'String' && stringPattern.test(node.value)) {
465
- return node.value.substr(1, node.value.length - 2);
466
- }
467
- else if (node.type === 'Identifier') {
468
- return node.name;
469
- }
470
- else if ('value' in node) {
471
- return node.value;
472
- }
473
- return '';
474
- }
475
- /**
476
- * Returns true if the specified media query node is relevant to screen rendering.
477
- *
478
- * @param {object} mediaQueryNode - Media Query AST node to examine.
479
- *
480
- * @return {boolean} true if the media query is relevant to screens.
481
- */
482
- static isUsefulMediaQuery(mediaQueryNode) {
483
- // Find media types.
484
- let lastIdentifierNot = false;
485
- const mediaTypes = {};
486
- csstree.walk(mediaQueryNode, {
487
- visit: 'Identifier',
488
- enter: node => {
489
- const identifier = csstree.keyword(node.name).name;
490
- if (identifier === 'not') {
491
- lastIdentifierNot = true;
492
- return;
493
- }
494
- if (validMediaTypes.includes(identifier)) {
495
- mediaTypes[identifier] = !lastIdentifierNot;
496
- }
497
- lastIdentifierNot = false;
498
- },
499
- });
500
- // If no media types specified, assume screen.
501
- if (Object.keys(mediaTypes).length === 0) {
502
- return true;
503
- }
504
- // If 'screen' or 'all' explicitly specified, use those (preference screen).
505
- for (const mediaType of ['screen', 'all']) {
506
- if (Object.prototype.hasOwnProperty.call(mediaTypes, mediaType)) {
507
- return mediaTypes[mediaType];
508
- }
509
- }
510
- // If any other media type specified, only true if 'not'. e.g.: 'not print'.
511
- return Object.values(mediaTypes).some(value => !value);
512
- }
513
- /**
514
- * Returns this AST converted to CSS.
515
- *
516
- * @return {string} this AST represented in CSS.
517
- */
518
- toCSS() {
519
- return csstree.generate(this.ast);
520
- }
521
- /**
522
- * Static method to parse a block of CSS and return a new StyleAST object which represents it.
523
- *
524
- * @param {string} css - CSS to parse.
525
- *
526
- * @return {StyleAST} new parse AST based on the CSS.
527
- */
528
- static parse(css) {
529
- const errors = [];
530
- const ast = csstree.parse(css, {
531
- parseCustomProperty: true,
532
- positions: true,
533
- onParseError: err => {
534
- errors.push(err);
535
- },
536
- });
537
- return new StyleAST(css, ast, errors);
538
- }
539
- }
540
- //# sourceMappingURL=style-ast.js.map