@automattic/jetpack-critical-css-gen 1.0.0 → 1.0.2
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 +16 -4
- package/build/browser-interface-iframe.d.ts +31 -0
- package/build/browser-interface-iframe.js +130 -0
- package/build/browser-interface-iframe.js.map +1 -0
- package/build/browser-interface-playwright.d.ts +53 -0
- package/build/browser-interface-playwright.js +94 -0
- package/build/browser-interface-playwright.js.map +1 -0
- package/build/browser-interface.d.ts +77 -0
- package/build/browser-interface.js +124 -0
- package/build/browser-interface.js.map +1 -0
- package/build/browser.d.ts +5 -0
- package/build/browser.js +6 -0
- package/build/browser.js.map +1 -0
- package/build/css-file-set.d.ts +100 -0
- package/build/css-file-set.js +210 -0
- package/build/css-file-set.js.map +1 -0
- package/build/errors.d.ts +101 -0
- package/build/errors.js +103 -0
- package/build/errors.js.map +1 -0
- package/build/generate-critical-css.d.ts +24 -0
- package/build/generate-critical-css.js +162 -0
- package/build/generate-critical-css.js.map +1 -0
- package/build/ignored-pseudo-elements.d.ts +8 -0
- package/build/ignored-pseudo-elements.js +35 -0
- package/build/ignored-pseudo-elements.js.map +1 -0
- package/build/minify-css.d.ts +11 -0
- package/build/minify-css.js +19 -0
- package/build/minify-css.js.map +1 -0
- package/build/object-promise-all.d.ts +12 -0
- package/build/object-promise-all.js +16 -0
- package/build/object-promise-all.js.map +1 -0
- package/build/playwright.d.ts +5 -0
- package/build/playwright.js +6 -0
- package/build/playwright.js.map +1 -0
- package/build/style-ast.d.ts +164 -0
- package/build/style-ast.js +540 -0
- package/build/style-ast.js.map +1 -0
- package/build/types.d.ts +14 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/package.json +4 -3
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { BrowserInterface } from './browser-interface.js';
|
|
2
|
+
import { CSSFileSet } from './css-file-set.js';
|
|
3
|
+
import { SuccessTargetError, EmptyCSSError } from './errors.js';
|
|
4
|
+
import { removeIgnoredPseudoElements } from './ignored-pseudo-elements.js';
|
|
5
|
+
import { minifyCss } from './minify-css.js';
|
|
6
|
+
const noop = () => {
|
|
7
|
+
// No op.
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Collate and return a CSSFileSet object describing all the CSS files used by
|
|
11
|
+
* the set of URLs provided.
|
|
12
|
+
*
|
|
13
|
+
* Errors that occur during this process are collated, but not thrown yet.
|
|
14
|
+
*
|
|
15
|
+
* @param {BrowserInterface} browserInterface - interface to access pages
|
|
16
|
+
* @param {string[]} urls - list of URLs to scan for CSS files
|
|
17
|
+
* @param {number} maxPages - number of pages to process at most
|
|
18
|
+
* @return {Array} - Two member array; CSSFileSet, and an object containing errors that occurred at each URL.
|
|
19
|
+
*/
|
|
20
|
+
async function collateCssFiles(browserInterface, urls, maxPages) {
|
|
21
|
+
const cssFiles = new CSSFileSet(browserInterface);
|
|
22
|
+
const errors = {};
|
|
23
|
+
let successes = 0;
|
|
24
|
+
for (const url of urls) {
|
|
25
|
+
try {
|
|
26
|
+
const cssIncludes = await browserInterface.getCssIncludes(url);
|
|
27
|
+
// Convert relative URLs to absolute.
|
|
28
|
+
const relativeUrls = Object.keys(cssIncludes);
|
|
29
|
+
const absoluteIncludes = relativeUrls.reduce((set, relative) => {
|
|
30
|
+
try {
|
|
31
|
+
const absolute = new URL(relative, url).toString();
|
|
32
|
+
set[absolute] = cssIncludes[relative];
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
// Ignore invalid URLs.
|
|
36
|
+
// eslint-disable-next-line no-console
|
|
37
|
+
console.log(`Could not absolutify URL: ${relative}`);
|
|
38
|
+
}
|
|
39
|
+
return set;
|
|
40
|
+
}, {});
|
|
41
|
+
await cssFiles.addMultiple(url, absoluteIncludes);
|
|
42
|
+
const internalStyles = await browserInterface.getInternalStyles(url);
|
|
43
|
+
await cssFiles.addInternalStyles(url, internalStyles);
|
|
44
|
+
// Abort early if we hit the critical mass
|
|
45
|
+
successes++;
|
|
46
|
+
if (successes >= maxPages) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
errors[url] = err;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return [cssFiles, errors];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get CSS selectors for above the fold content for the valid URLs.
|
|
58
|
+
*
|
|
59
|
+
* @param {object} param - All the parameters as object.
|
|
60
|
+
* @param {BrowserInterface} param.browserInterface - Interface to access pages
|
|
61
|
+
* @param {object} param.selectorPages - All the CSS selectors to URLs map object
|
|
62
|
+
* @param {string[]} param.validUrls - List of all the valid URLs
|
|
63
|
+
* @param {Array} param.viewports - Browser viewports
|
|
64
|
+
* @param {number} param.maxPages - Maximum number of pages to process
|
|
65
|
+
* @param {Function} param.updateProgress - Update progress callback function
|
|
66
|
+
*
|
|
67
|
+
* @return {Set<string>} - List of above the fold selectors.
|
|
68
|
+
*/
|
|
69
|
+
async function getAboveFoldSelectors({ browserInterface, selectorPages, validUrls, viewports, maxPages, updateProgress, }) {
|
|
70
|
+
// For each selector string, create a "trimmed" version with the stuff JavaScript can't handle cut out.
|
|
71
|
+
const trimmedSelectors = Object.keys(selectorPages).reduce((set, selector) => {
|
|
72
|
+
set[selector] = removeIgnoredPseudoElements(selector);
|
|
73
|
+
return set;
|
|
74
|
+
}, {});
|
|
75
|
+
// Go through all the URLs looking for above-the-fold selectors, and selectors which may be "dangerous"
|
|
76
|
+
// i.e.: may match elements on pages that do not include their CSS file.
|
|
77
|
+
const aboveFoldSelectors = new Set();
|
|
78
|
+
const dangerousSelectors = new Set();
|
|
79
|
+
for (const url of validUrls.slice(0, maxPages)) {
|
|
80
|
+
// Work out which CSS selectors match any element on this page.
|
|
81
|
+
const pageSelectors = await browserInterface.runInPage(url, null, BrowserInterface.innerFindMatchingSelectors, trimmedSelectors);
|
|
82
|
+
// Check for selectors which may match this page, but are not included in this page's CSS.
|
|
83
|
+
pageSelectors
|
|
84
|
+
.filter(s => !selectorPages[s].has(url))
|
|
85
|
+
.forEach(s => dangerousSelectors.add(s));
|
|
86
|
+
// Collate all above-fold selectors for all viewport sizes.
|
|
87
|
+
for (const size of viewports) {
|
|
88
|
+
updateProgress();
|
|
89
|
+
const pageAboveFold = await browserInterface.runInPage(url, size, BrowserInterface.innerFindAboveFoldSelectors, trimmedSelectors, pageSelectors);
|
|
90
|
+
pageAboveFold.forEach(s => aboveFoldSelectors.add(s));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Remove dangerous selectors from above fold set.
|
|
94
|
+
for (const dangerousSelector of dangerousSelectors) {
|
|
95
|
+
aboveFoldSelectors.delete(dangerousSelector);
|
|
96
|
+
}
|
|
97
|
+
return aboveFoldSelectors;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Generates critical CSS for the given URLs and viewports.
|
|
101
|
+
*
|
|
102
|
+
* @param {object} root0 - The options object
|
|
103
|
+
* @param {BrowserInterface} root0.browserInterface - Interface to interact with the browser
|
|
104
|
+
* @param {Function} root0.progressCallback - Optional callback function to report progress
|
|
105
|
+
* @param {string[]} root0.urls - Array of URLs to generate critical CSS for
|
|
106
|
+
* @param {Viewport[]} root0.viewports - Array of viewport sizes to consider
|
|
107
|
+
* @param {FilterSpec} root0.filters - Optional filters to apply to the CSS
|
|
108
|
+
* @param {number} root0.successRatio - Ratio of successful URLs required (default: 1)
|
|
109
|
+
* @param {number} root0.maxPages - Maximum number of pages to process (default: 10)
|
|
110
|
+
* @return {Promise<[string, Error[]]>} A promise that resolves to an array containing the critical CSS string and an array of errors.
|
|
111
|
+
*/
|
|
112
|
+
export async function generateCriticalCSS({ browserInterface, progressCallback, urls, viewports, filters, successRatio = 1, maxPages = 10, }) {
|
|
113
|
+
// Success threshold is calculated based on the success ratio of "the number of URLs provided", or "maxPages" whichever is lower.
|
|
114
|
+
// See 268-gh-Automattic/boost-cloud
|
|
115
|
+
const successUrlsThreshold = Math.ceil(Math.min(urls.length, maxPages) * successRatio);
|
|
116
|
+
try {
|
|
117
|
+
progressCallback = progressCallback || noop;
|
|
118
|
+
let progress = 0;
|
|
119
|
+
const progressSteps = 1 + urls.length * viewports.length;
|
|
120
|
+
const updateProgress = () => progressCallback(++progress, progressSteps);
|
|
121
|
+
// Collate all CSS Files used by all valid URLs.
|
|
122
|
+
const [cssFiles, cssFileErrors] = await collateCssFiles(browserInterface, urls, maxPages);
|
|
123
|
+
updateProgress();
|
|
124
|
+
// Verify there are enough valid URLs to carry on with.
|
|
125
|
+
const validUrls = browserInterface.filterValidUrls(urls);
|
|
126
|
+
if (validUrls.length < successUrlsThreshold) {
|
|
127
|
+
throw new SuccessTargetError(cssFileErrors);
|
|
128
|
+
}
|
|
129
|
+
// Trim ignored rules out of all CSS ASTs.
|
|
130
|
+
cssFiles.applyFilters(filters || {});
|
|
131
|
+
// Gather a record of all selectors, and which page URLs each is referenced by.
|
|
132
|
+
const selectorPages = cssFiles.collateSelectorPages();
|
|
133
|
+
// Get CSS selectors for above the fold.
|
|
134
|
+
const aboveFoldSelectors = await getAboveFoldSelectors({
|
|
135
|
+
browserInterface,
|
|
136
|
+
selectorPages,
|
|
137
|
+
validUrls,
|
|
138
|
+
viewports,
|
|
139
|
+
maxPages,
|
|
140
|
+
updateProgress,
|
|
141
|
+
});
|
|
142
|
+
// Prune each AST for above-fold selector list. Note: this prunes a clone.
|
|
143
|
+
const asts = cssFiles.prunedAsts(aboveFoldSelectors);
|
|
144
|
+
// Convert ASTs to CSS.
|
|
145
|
+
const [css, cssErrors] = minifyCss(asts.map(ast => ast.toCSS()).join('\n'));
|
|
146
|
+
// If there is no Critical CSS, it means the URLs did not have any CSS in their external style sheet(s).
|
|
147
|
+
if (!css) {
|
|
148
|
+
const emptyCSSErrors = {};
|
|
149
|
+
for (const url of validUrls) {
|
|
150
|
+
emptyCSSErrors[url] = new EmptyCSSError({ url });
|
|
151
|
+
}
|
|
152
|
+
throw new SuccessTargetError(emptyCSSErrors);
|
|
153
|
+
}
|
|
154
|
+
// Collect warnings / errors together.
|
|
155
|
+
const warnings = cssFiles.getErrors().concat(cssErrors.map(s => new Error(s)));
|
|
156
|
+
return [css, warnings];
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
browserInterface.cleanup();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=generate-critical-css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-critical-css.js","sourceRoot":"","sources":["../src/generate-critical-css.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove pseudo elements that are ignored while matching elements above the fold.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} selector - selector to filter.
|
|
5
|
+
*
|
|
6
|
+
* @return {string} selector with ignored pseudo elements removed.
|
|
7
|
+
*/
|
|
8
|
+
export declare function removeIgnoredPseudoElements(selector: string): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const ignoredPseudoElements = [
|
|
2
|
+
'after',
|
|
3
|
+
'before',
|
|
4
|
+
'first-(line|letter)',
|
|
5
|
+
'(input-)?placeholder',
|
|
6
|
+
'scrollbar',
|
|
7
|
+
'search(results-)?decoration',
|
|
8
|
+
'search-(cancel|results)-button',
|
|
9
|
+
];
|
|
10
|
+
let removePseudoElementRegex;
|
|
11
|
+
/**
|
|
12
|
+
* Builds a RegExp for finding pseudo elements that should be ignored while matching
|
|
13
|
+
* elements that are above the fold.
|
|
14
|
+
*
|
|
15
|
+
* @return {RegExp} A RegExp to use when removing unwanted pseudo elements.
|
|
16
|
+
*/
|
|
17
|
+
function getRemovePseudoElementRegex() {
|
|
18
|
+
if (removePseudoElementRegex) {
|
|
19
|
+
return removePseudoElementRegex;
|
|
20
|
+
}
|
|
21
|
+
const allIgnored = ignoredPseudoElements.join('|');
|
|
22
|
+
removePseudoElementRegex = new RegExp('::?(-(moz|ms|webkit)-)?(' + allIgnored + ')');
|
|
23
|
+
return removePseudoElementRegex;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Remove pseudo elements that are ignored while matching elements above the fold.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} selector - selector to filter.
|
|
29
|
+
*
|
|
30
|
+
* @return {string} selector with ignored pseudo elements removed.
|
|
31
|
+
*/
|
|
32
|
+
export function removeIgnoredPseudoElements(selector) {
|
|
33
|
+
return selector.replace(getRemovePseudoElementRegex(), '').trim();
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=ignored-pseudo-elements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignored-pseudo-elements.js","sourceRoot":"","sources":["../src/ignored-pseudo-elements.ts"],"names":[],"mappings":"AAAA,MAAM,qBAAqB,GAAG;IAC7B,OAAO;IACP,QAAQ;IACR,qBAAqB;IACrB,sBAAsB;IACtB,WAAW;IACX,6BAA6B;IAC7B,gCAAgC;CAChC,CAAC;AAEF,IAAI,wBAAgC,CAAC;AAErC;;;;;GAKG;AACH,SAAS,2BAA2B;IACnC,IAAK,wBAAwB,EAAG;QAC/B,OAAO,wBAAwB,CAAC;KAChC;IAED,MAAM,UAAU,GAAG,qBAAqB,CAAC,IAAI,CAAE,GAAG,CAAE,CAAC;IACrD,wBAAwB,GAAG,IAAI,MAAM,CAAE,0BAA0B,GAAG,UAAU,GAAG,GAAG,CAAE,CAAC;IAEvF,OAAO,wBAAwB,CAAC;AACjC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B,CAAE,QAAgB;IAC5D,OAAO,QAAQ,CAAC,OAAO,CAAE,2BAA2B,EAAE,EAAE,EAAE,CAAE,CAAC,IAAI,EAAE,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minifies the given CSS, returning it as a string. Any errors that occur are returned
|
|
3
|
+
* in the second positional return value.
|
|
4
|
+
*
|
|
5
|
+
* If the CSS fails to minify, the original content will be returned instead.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} css - CSS to minify.
|
|
8
|
+
*
|
|
9
|
+
* @return {[ string, string[] ]} - Minified CSS and a list of errors returned.
|
|
10
|
+
*/
|
|
11
|
+
export declare function minifyCss(css: string): [string, string[]];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import CleanCSS from 'clean-css';
|
|
2
|
+
/**
|
|
3
|
+
* Minifies the given CSS, returning it as a string. Any errors that occur are returned
|
|
4
|
+
* in the second positional return value.
|
|
5
|
+
*
|
|
6
|
+
* If the CSS fails to minify, the original content will be returned instead.
|
|
7
|
+
*
|
|
8
|
+
* @param {string} css - CSS to minify.
|
|
9
|
+
*
|
|
10
|
+
* @return {[ string, string[] ]} - Minified CSS and a list of errors returned.
|
|
11
|
+
*/
|
|
12
|
+
export function minifyCss(css) {
|
|
13
|
+
const result = new CleanCSS().minify(css);
|
|
14
|
+
if (!result.styles) {
|
|
15
|
+
return [css, result.errors];
|
|
16
|
+
}
|
|
17
|
+
return [result.styles, result.errors];
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=minify-css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minify-css.js","sourceRoot":"","sources":["../src/minify-css.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,WAAW,CAAC;AAEjC;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CAAE,GAAW;IACrC,MAAM,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC,MAAM,CAAE,GAAG,CAAE,CAAC;IAE5C,IAAK,CAAE,MAAM,CAAC,MAAM,EAAG;QACtB,OAAO,CAAE,GAAG,EAAE,MAAM,CAAC,MAAM,CAAE,CAAC;KAC9B;IAED,OAAO,CAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAE,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Given an object full of promises, resolves all of them and returns an object containing resultant values.
|
|
3
|
+
* Roughly equivalent of Promise.all, but applies to an object.
|
|
4
|
+
*
|
|
5
|
+
* @param {object} object - containing promises to resolve
|
|
6
|
+
* @return {object} - Promise which resolves to an object containing resultant values
|
|
7
|
+
*/
|
|
8
|
+
export declare function objectPromiseAll<ValueType>(object: {
|
|
9
|
+
[key: string]: Promise<ValueType>;
|
|
10
|
+
}): Promise<{
|
|
11
|
+
[key: string]: ValueType;
|
|
12
|
+
}>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Given an object full of promises, resolves all of them and returns an object containing resultant values.
|
|
3
|
+
* Roughly equivalent of Promise.all, but applies to an object.
|
|
4
|
+
*
|
|
5
|
+
* @param {object} object - containing promises to resolve
|
|
6
|
+
* @return {object} - Promise which resolves to an object containing resultant values
|
|
7
|
+
*/
|
|
8
|
+
export async function objectPromiseAll(object) {
|
|
9
|
+
const keys = Object.keys(object);
|
|
10
|
+
const values = await Promise.all(keys.map(key => object[key]));
|
|
11
|
+
return keys.reduce((acc, key, index) => {
|
|
12
|
+
acc[key] = values[index];
|
|
13
|
+
return acc;
|
|
14
|
+
}, {});
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=object-promise-all.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object-promise-all.js","sourceRoot":"","sources":["../src/object-promise-all.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAe,MAEpD;IACA,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAE,MAAM,CAAE,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAE,IAAI,CAAC,GAAG,CAAE,GAAG,CAAC,EAAE,CAAC,MAAM,CAAE,GAAG,CAAE,CAAE,CAAE,CAAC;IAErE,OAAO,IAAI,CAAC,MAAM,CACjB,CAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAG,EAAE;QACrB,GAAG,CAAE,GAAG,CAAE,GAAG,MAAM,CAAE,KAAK,CAAE,CAAC;QAC7B,OAAO,GAAG,CAAC;IACZ,CAAC,EACD,EAAoC,CACpC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { BrowserInterfacePlaywright } from './browser-interface-playwright.js';
|
|
2
|
+
export { BrowserInterface } from './browser-interface.js';
|
|
3
|
+
export { generateCriticalCSS } from './generate-critical-css.js';
|
|
4
|
+
export * from './errors.js';
|
|
5
|
+
export declare const version = "0.0.11";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { BrowserInterfacePlaywright } from './browser-interface-playwright.js';
|
|
2
|
+
export { BrowserInterface } from './browser-interface.js';
|
|
3
|
+
export { generateCriticalCSS } from './generate-critical-css.js';
|
|
4
|
+
export * from './errors.js';
|
|
5
|
+
export const version = '0.0.11';
|
|
6
|
+
//# sourceMappingURL=playwright.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright.js","sourceRoot":"","sources":["../src/playwright.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,cAAc,aAAa,CAAC;AAE5B,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1,164 @@
|
|
|
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
|
+
}
|