postcss-preset-env 6.5.0 → 7.0.1
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/README.md +8 -8
- package/dist/index.js +485 -0
- package/{index.mjs → dist/index.mjs} +157 -206
- package/package.json +95 -61
- package/CHANGELOG.md +0 -253
- package/index.js +0 -480
- package/index.js.map +0 -1
- package/index.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# PostCSS Preset Env [<img src="https://postcss.github.io/postcss/logo.svg" alt="PostCSS" width="90" height="90" align="right">][postcss]
|
|
2
2
|
|
|
3
|
-
[
|
|
4
|
-
[
|
|
5
|
-
[
|
|
3
|
+
[<img alt="npm version" src="https://img.shields.io/npm/v/postcss-preset-env.svg" height="20">][npm-url]
|
|
4
|
+
[<img alt="build status" src="https://github.com/csstools/postcss-preset-env/workflows/test/badge.svg" height="20">][cli-url]
|
|
5
|
+
[<img alt="support chat" src="https://img.shields.io/badge/support-chat-blue.svg" height="20">][git-url]
|
|
6
6
|
|
|
7
7
|
[PostCSS Preset Env] lets you convert modern CSS into something most browsers
|
|
8
8
|
can understand, determining the polyfills you need based on your targeted
|
|
@@ -116,8 +116,8 @@ postcss([
|
|
|
116
116
|
|
|
117
117
|
[PostCSS Preset Env] runs in all Node environments, with special instructions for:
|
|
118
118
|
|
|
119
|
-
| [Node](INSTALL.md#node) | [PostCSS CLI](INSTALL.md#postcss-cli) | [Webpack](INSTALL.md#webpack) | [Create React App](INSTALL.md#create-react-app) | [Gulp](INSTALL.md#gulp) | [Grunt](INSTALL.md#grunt) |
|
|
120
|
-
| --- | --- | --- | --- | --- | --- |
|
|
119
|
+
| [Node](INSTALL.md#node) | [PostCSS CLI](INSTALL.md#postcss-cli) | [Webpack](INSTALL.md#webpack) | [Create React App](INSTALL.md#create-react-app) | [Gulp](INSTALL.md#gulp) | [Grunt](INSTALL.md#grunt) | [Rollup](INSTALL.md#rollup) |
|
|
120
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
121
121
|
|
|
122
122
|
## Options
|
|
123
123
|
|
|
@@ -141,7 +141,7 @@ features.
|
|
|
141
141
|
|
|
142
142
|
The `features` option enables or disables specific polyfills by ID. Passing
|
|
143
143
|
`true` to a specific feature ID will enable its polyfill, while passing `false`
|
|
144
|
-
will disable it.
|
|
144
|
+
will disable it. [List of IDs](https://github.com/csstools/postcss-preset-env/blob/master/src/lib/plugins-by-id.js#L36)
|
|
145
145
|
|
|
146
146
|
```js
|
|
147
147
|
postcssPresetEnv({
|
|
@@ -362,8 +362,8 @@ postcssPresetEnv({
|
|
|
362
362
|
});
|
|
363
363
|
```
|
|
364
364
|
|
|
365
|
-
[cli-img]: https://
|
|
366
|
-
[cli-url]: https://
|
|
365
|
+
[cli-img]: https://github.com/postcss/postcss-preset-env/workflows/test/badge.svg
|
|
366
|
+
[cli-url]: https://github.com/postcss/postcss-preset-env/actions/workflows/test.yml?query=workflow/test
|
|
367
367
|
[git-img]: https://img.shields.io/badge/support-chat-blue.svg
|
|
368
368
|
[git-url]: https://gitter.im/postcss/postcss
|
|
369
369
|
[npm-img]: https://img.shields.io/npm/v/postcss-preset-env.svg
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var autoprefixer = require('autoprefixer');
|
|
4
|
+
var browserslist = require('browserslist');
|
|
5
|
+
var cssdb = require('cssdb');
|
|
6
|
+
var postcssAttributeCaseInsensitive = require('postcss-attribute-case-insensitive');
|
|
7
|
+
var postcssBlankPseudo = require('css-blank-pseudo/postcss');
|
|
8
|
+
var postcssColorFunctionalNotation = require('postcss-color-functional-notation');
|
|
9
|
+
var postcssColorHexAlpha = require('postcss-color-hex-alpha');
|
|
10
|
+
var postcssColorRebeccapurple = require('postcss-color-rebeccapurple');
|
|
11
|
+
var postcssCustomMedia = require('postcss-custom-media');
|
|
12
|
+
var postcssCustomProperties = require('postcss-custom-properties');
|
|
13
|
+
var postcssCustomSelectors = require('postcss-custom-selectors');
|
|
14
|
+
var postcssDirPseudoClass = require('postcss-dir-pseudo-class');
|
|
15
|
+
var postcssDoublePositionGradients = require('postcss-double-position-gradients');
|
|
16
|
+
var postcssEnvFunction = require('postcss-env-function');
|
|
17
|
+
var postcssFocusVisible = require('postcss-focus-visible');
|
|
18
|
+
var postcssFocusWithin = require('postcss-focus-within');
|
|
19
|
+
var postcssFontVariant = require('postcss-font-variant');
|
|
20
|
+
var postcssGapProperties = require('postcss-gap-properties');
|
|
21
|
+
var postcssHasPseudo = require('css-has-pseudo/postcss');
|
|
22
|
+
var postcssImageSetPolyfill = require('postcss-image-set-function');
|
|
23
|
+
var postcssInitial = require('postcss-initial');
|
|
24
|
+
var postcssLabFunction = require('postcss-lab-function');
|
|
25
|
+
var postcssLogical = require('postcss-logical');
|
|
26
|
+
var postcssMediaMinmax = require('postcss-media-minmax');
|
|
27
|
+
var postcssNesting = require('postcss-nesting');
|
|
28
|
+
var postcssOverflowShorthand = require('postcss-overflow-shorthand');
|
|
29
|
+
var postcssPageBreak = require('postcss-page-break');
|
|
30
|
+
var postcssPlace = require('postcss-place');
|
|
31
|
+
var postcssPrefersColorScheme = require('css-prefers-color-scheme/postcss');
|
|
32
|
+
var postcssPseudoClassAnyLink = require('postcss-pseudo-class-any-link');
|
|
33
|
+
var postcssReplaceOverflowWrap = require('postcss-replace-overflow-wrap');
|
|
34
|
+
var postcssSelectorNot = require('postcss-selector-not');
|
|
35
|
+
var caniuse = require('caniuse-lite');
|
|
36
|
+
var fs = require('fs');
|
|
37
|
+
var path = require('path');
|
|
38
|
+
|
|
39
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
40
|
+
|
|
41
|
+
function _interopNamespace(e) {
|
|
42
|
+
if (e && e.__esModule) return e;
|
|
43
|
+
var n = Object.create(null);
|
|
44
|
+
if (e) {
|
|
45
|
+
Object.keys(e).forEach(function (k) {
|
|
46
|
+
if (k !== 'default') {
|
|
47
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
48
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () { return e[k]; }
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
n["default"] = e;
|
|
56
|
+
return Object.freeze(n);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var autoprefixer__default = /*#__PURE__*/_interopDefaultLegacy(autoprefixer);
|
|
60
|
+
var browserslist__default = /*#__PURE__*/_interopDefaultLegacy(browserslist);
|
|
61
|
+
var cssdb__default = /*#__PURE__*/_interopDefaultLegacy(cssdb);
|
|
62
|
+
var postcssAttributeCaseInsensitive__default = /*#__PURE__*/_interopDefaultLegacy(postcssAttributeCaseInsensitive);
|
|
63
|
+
var postcssBlankPseudo__default = /*#__PURE__*/_interopDefaultLegacy(postcssBlankPseudo);
|
|
64
|
+
var postcssColorFunctionalNotation__default = /*#__PURE__*/_interopDefaultLegacy(postcssColorFunctionalNotation);
|
|
65
|
+
var postcssColorHexAlpha__default = /*#__PURE__*/_interopDefaultLegacy(postcssColorHexAlpha);
|
|
66
|
+
var postcssColorRebeccapurple__default = /*#__PURE__*/_interopDefaultLegacy(postcssColorRebeccapurple);
|
|
67
|
+
var postcssCustomMedia__default = /*#__PURE__*/_interopDefaultLegacy(postcssCustomMedia);
|
|
68
|
+
var postcssCustomProperties__default = /*#__PURE__*/_interopDefaultLegacy(postcssCustomProperties);
|
|
69
|
+
var postcssCustomSelectors__default = /*#__PURE__*/_interopDefaultLegacy(postcssCustomSelectors);
|
|
70
|
+
var postcssDirPseudoClass__default = /*#__PURE__*/_interopDefaultLegacy(postcssDirPseudoClass);
|
|
71
|
+
var postcssDoublePositionGradients__default = /*#__PURE__*/_interopDefaultLegacy(postcssDoublePositionGradients);
|
|
72
|
+
var postcssEnvFunction__default = /*#__PURE__*/_interopDefaultLegacy(postcssEnvFunction);
|
|
73
|
+
var postcssFocusVisible__default = /*#__PURE__*/_interopDefaultLegacy(postcssFocusVisible);
|
|
74
|
+
var postcssFocusWithin__default = /*#__PURE__*/_interopDefaultLegacy(postcssFocusWithin);
|
|
75
|
+
var postcssFontVariant__default = /*#__PURE__*/_interopDefaultLegacy(postcssFontVariant);
|
|
76
|
+
var postcssGapProperties__default = /*#__PURE__*/_interopDefaultLegacy(postcssGapProperties);
|
|
77
|
+
var postcssHasPseudo__default = /*#__PURE__*/_interopDefaultLegacy(postcssHasPseudo);
|
|
78
|
+
var postcssImageSetPolyfill__default = /*#__PURE__*/_interopDefaultLegacy(postcssImageSetPolyfill);
|
|
79
|
+
var postcssInitial__default = /*#__PURE__*/_interopDefaultLegacy(postcssInitial);
|
|
80
|
+
var postcssLabFunction__default = /*#__PURE__*/_interopDefaultLegacy(postcssLabFunction);
|
|
81
|
+
var postcssLogical__default = /*#__PURE__*/_interopDefaultLegacy(postcssLogical);
|
|
82
|
+
var postcssMediaMinmax__default = /*#__PURE__*/_interopDefaultLegacy(postcssMediaMinmax);
|
|
83
|
+
var postcssNesting__default = /*#__PURE__*/_interopDefaultLegacy(postcssNesting);
|
|
84
|
+
var postcssOverflowShorthand__default = /*#__PURE__*/_interopDefaultLegacy(postcssOverflowShorthand);
|
|
85
|
+
var postcssPageBreak__default = /*#__PURE__*/_interopDefaultLegacy(postcssPageBreak);
|
|
86
|
+
var postcssPlace__default = /*#__PURE__*/_interopDefaultLegacy(postcssPlace);
|
|
87
|
+
var postcssPrefersColorScheme__default = /*#__PURE__*/_interopDefaultLegacy(postcssPrefersColorScheme);
|
|
88
|
+
var postcssPseudoClassAnyLink__default = /*#__PURE__*/_interopDefaultLegacy(postcssPseudoClassAnyLink);
|
|
89
|
+
var postcssReplaceOverflowWrap__default = /*#__PURE__*/_interopDefaultLegacy(postcssReplaceOverflowWrap);
|
|
90
|
+
var postcssSelectorNot__default = /*#__PURE__*/_interopDefaultLegacy(postcssSelectorNot);
|
|
91
|
+
var caniuse__namespace = /*#__PURE__*/_interopNamespace(caniuse);
|
|
92
|
+
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
93
|
+
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
94
|
+
|
|
95
|
+
function postcssSystemUiFont() {
|
|
96
|
+
return {
|
|
97
|
+
postcssPlugin: 'postcss-system-ui-font',
|
|
98
|
+
|
|
99
|
+
Declaration(
|
|
100
|
+
/** @type {import('postcss').Declaration} */
|
|
101
|
+
node) {
|
|
102
|
+
if (propertyRegExp.test(node.prop)) {
|
|
103
|
+
if (!node.value.includes(systemUiFamily.join(', '))) {
|
|
104
|
+
node.value = node.value.replace(systemUiMatch, systemUiReplace);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
postcssSystemUiFont.postcss = true;
|
|
112
|
+
const propertyRegExp = /(?:^(?:-|\\002d){2})|(?:^font(?:-family)?$)/i;
|
|
113
|
+
const whitespace = '[\\f\\n\\r\\x09\\x20]';
|
|
114
|
+
const systemUiFamily = ['system-ui',
|
|
115
|
+
/* macOS 10.11-10.12 */
|
|
116
|
+
'-apple-system',
|
|
117
|
+
/* Windows 6+ */
|
|
118
|
+
'Segoe UI',
|
|
119
|
+
/* Android 4+ */
|
|
120
|
+
'Roboto',
|
|
121
|
+
/* Ubuntu 10.10+ */
|
|
122
|
+
'Ubuntu',
|
|
123
|
+
/* Gnome 3+ */
|
|
124
|
+
'Cantarell',
|
|
125
|
+
/* KDE Plasma 5+ */
|
|
126
|
+
'Noto Sans',
|
|
127
|
+
/* fallback */
|
|
128
|
+
'sans-serif'];
|
|
129
|
+
const systemUiMatch = new RegExp(`(^|,|${whitespace}+)(?:system-ui${whitespace}*)(?:,${whitespace}*(?:${systemUiFamily.join('|')})${whitespace}*)?(,|$)`, 'i');
|
|
130
|
+
const systemUiReplace = `$1${systemUiFamily.join(', ')}$2`;
|
|
131
|
+
|
|
132
|
+
var plugins = {
|
|
133
|
+
'all-property': postcssInitial__default["default"],
|
|
134
|
+
'any-link-pseudo-class': postcssPseudoClassAnyLink__default["default"],
|
|
135
|
+
'blank-pseudo-class': postcssBlankPseudo__default["default"],
|
|
136
|
+
'break-properties': postcssPageBreak__default["default"],
|
|
137
|
+
'case-insensitive-attributes': postcssAttributeCaseInsensitive__default["default"],
|
|
138
|
+
'color-functional-notation': postcssColorFunctionalNotation__default["default"],
|
|
139
|
+
'custom-media-queries': postcssCustomMedia__default["default"],
|
|
140
|
+
'custom-properties': postcssCustomProperties__default["default"],
|
|
141
|
+
'custom-selectors': postcssCustomSelectors__default["default"],
|
|
142
|
+
'dir-pseudo-class': postcssDirPseudoClass__default["default"],
|
|
143
|
+
'double-position-gradients': postcssDoublePositionGradients__default["default"],
|
|
144
|
+
'environment-variables': postcssEnvFunction__default["default"],
|
|
145
|
+
'focus-visible-pseudo-class': postcssFocusVisible__default["default"],
|
|
146
|
+
'focus-within-pseudo-class': postcssFocusWithin__default["default"],
|
|
147
|
+
'font-variant-property': postcssFontVariant__default["default"],
|
|
148
|
+
'gap-properties': postcssGapProperties__default["default"],
|
|
149
|
+
'has-pseudo-class': postcssHasPseudo__default["default"],
|
|
150
|
+
'hexadecimal-alpha-notation': postcssColorHexAlpha__default["default"],
|
|
151
|
+
'image-set-function': postcssImageSetPolyfill__default["default"],
|
|
152
|
+
'lab-function': postcssLabFunction__default["default"],
|
|
153
|
+
'logical-properties-and-values': postcssLogical__default["default"],
|
|
154
|
+
'media-query-ranges': postcssMediaMinmax__default["default"],
|
|
155
|
+
'nesting-rules': postcssNesting__default["default"],
|
|
156
|
+
'not-pseudo-class': postcssSelectorNot__default["default"],
|
|
157
|
+
'overflow-property': postcssOverflowShorthand__default["default"],
|
|
158
|
+
'overflow-wrap-property': postcssReplaceOverflowWrap__default["default"],
|
|
159
|
+
'place-properties': postcssPlace__default["default"],
|
|
160
|
+
'prefers-color-scheme-query': postcssPrefersColorScheme__default["default"],
|
|
161
|
+
'rebeccapurple-color': postcssColorRebeccapurple__default["default"],
|
|
162
|
+
'system-ui-font-family': postcssSystemUiFont
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// return a list of features to be inserted before or after cssdb features
|
|
166
|
+
function getTransformedInsertions(insertions, placement) {
|
|
167
|
+
return Object.keys(insertions).map(id => [].concat(insertions[id]).map(plugin => ({
|
|
168
|
+
[placement]: true,
|
|
169
|
+
plugin,
|
|
170
|
+
id
|
|
171
|
+
}))).reduce((array, feature) => array.concat(feature), []);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function getUnsupportedBrowsersByFeature(feature) {
|
|
175
|
+
const caniuseFeature = caniuse__namespace.features[feature]; // if feature support can be determined
|
|
176
|
+
|
|
177
|
+
if (caniuseFeature) {
|
|
178
|
+
const stats = caniuse__namespace.feature(caniuseFeature).stats; // return an array of browsers and versions that do not support the feature
|
|
179
|
+
|
|
180
|
+
const results = Object.keys(stats).reduce((browsers, browser) => browsers.concat(Object.keys(stats[browser]).filter(version => stats[browser][version].indexOf('y') !== 0).map(version => `${browser} ${version}`)), []);
|
|
181
|
+
return results;
|
|
182
|
+
} else {
|
|
183
|
+
// otherwise, return that the feature does not work in any browser
|
|
184
|
+
return ['> 0%'];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ids ordered by required execution, then alphabetically
|
|
189
|
+
var idsByExecutionOrder = ['custom-media-queries', 'custom-properties', 'environment-variables', // run environment-variables here to access transpiled custom media params and properties
|
|
190
|
+
'image-set-function', // run images-set-function before nesting-rules so that it may fix nested media
|
|
191
|
+
'media-query-ranges', // run media-query-range and
|
|
192
|
+
'prefers-color-scheme-query', // run prefers-color-scheme-query here to prevent duplicate transpilation after nesting-rules
|
|
193
|
+
'nesting-rules', 'custom-selectors', // run custom-selectors after nesting-rules to correctly transpile &:--custom-selector
|
|
194
|
+
'any-link-pseudo-class', 'case-insensitive-attributes', 'focus-visible-pseudo-class', 'focus-within-pseudo-class', 'matches-pseudo-class', // run matches-pseudo-class and
|
|
195
|
+
'not-pseudo-class', // run not-pseudo-class after other selectors have been transpiled
|
|
196
|
+
'logical-properties-and-values', // run logical-properties-and-values before dir-pseudo-class
|
|
197
|
+
'dir-pseudo-class', 'all-property', // run all-property before other property polyfills
|
|
198
|
+
'color-functional-notation', 'double-position-gradients', 'hexadecimal-alpha-notation', 'lab-function', 'rebeccapurple-color', 'color-mod-function', // run color-mod after other color modifications have finished
|
|
199
|
+
'blank-pseudo-class', 'break-properties', 'font-variant-property', 'has-pseudo-class', 'gap-properties', 'overflow-property', 'overflow-wrap-property', 'place-properties', 'system-ui-font-family'];
|
|
200
|
+
|
|
201
|
+
/* eslint max-params: ["error", 4] */
|
|
202
|
+
/* Write Exports to CSS File
|
|
203
|
+
/* ========================================================================== */
|
|
204
|
+
|
|
205
|
+
function getCustomMediaAsCss(customMedia) {
|
|
206
|
+
const cssContent = Object.keys(customMedia).reduce((cssLines, name) => {
|
|
207
|
+
cssLines.push(`@custom-media ${name} ${customMedia[name]};`);
|
|
208
|
+
return cssLines;
|
|
209
|
+
}, []).join('\n');
|
|
210
|
+
const css = `${cssContent}\n`;
|
|
211
|
+
return css;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function getCustomPropertiesAsCss(customProperties) {
|
|
215
|
+
const cssContent = Object.keys(customProperties).reduce((cssLines, name) => {
|
|
216
|
+
cssLines.push(`\t${name}: ${customProperties[name]};`);
|
|
217
|
+
return cssLines;
|
|
218
|
+
}, []).join('\n');
|
|
219
|
+
const css = `:root {\n${cssContent}\n}\n`;
|
|
220
|
+
return css;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function getCustomSelectorsAsCss(customSelectors) {
|
|
224
|
+
const cssContent = Object.keys(customSelectors).reduce((cssLines, name) => {
|
|
225
|
+
cssLines.push(`@custom-selector ${name} ${customSelectors[name]};`);
|
|
226
|
+
return cssLines;
|
|
227
|
+
}, []).join('\n');
|
|
228
|
+
const css = `${cssContent}\n`;
|
|
229
|
+
return css;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function writeExportsToCssFile(to, customMedia, customProperties, customSelectors) {
|
|
233
|
+
const customPropertiesAsCss = getCustomPropertiesAsCss(customProperties);
|
|
234
|
+
const customMediaAsCss = getCustomMediaAsCss(customMedia);
|
|
235
|
+
const customSelectorsAsCss = getCustomSelectorsAsCss(customSelectors);
|
|
236
|
+
const css = `${customMediaAsCss}\n${customSelectorsAsCss}\n${customPropertiesAsCss}`;
|
|
237
|
+
await writeFile(to, css);
|
|
238
|
+
}
|
|
239
|
+
/* Write Exports to JSON file
|
|
240
|
+
/* ========================================================================== */
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
async function writeExportsToJsonFile(to, customMedia, customProperties, customSelectors) {
|
|
244
|
+
const jsonContent = JSON.stringify({
|
|
245
|
+
'custom-media': customMedia,
|
|
246
|
+
'custom-properties': customProperties,
|
|
247
|
+
'custom-selectors': customSelectors
|
|
248
|
+
}, null, ' ');
|
|
249
|
+
const json = `${jsonContent}\n`;
|
|
250
|
+
await writeFile(to, json);
|
|
251
|
+
}
|
|
252
|
+
/* Write Exports to Common JS file
|
|
253
|
+
/* ========================================================================== */
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
function getObjectWithKeyAsCjs(key, object) {
|
|
257
|
+
const jsContents = Object.keys(object).reduce((jsLines, name) => {
|
|
258
|
+
jsLines.push(`\t\t'${escapeForJS(name)}': '${escapeForJS(object[name])}'`);
|
|
259
|
+
return jsLines;
|
|
260
|
+
}, []).join(',\n');
|
|
261
|
+
const cjs = `\n\t${key}: {\n${jsContents}\n\t}`;
|
|
262
|
+
return cjs;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async function writeExportsToCjsFile(to, customMedia, customProperties, customSelectors) {
|
|
266
|
+
const customMediaAsCjs = getObjectWithKeyAsCjs('customMedia', customMedia);
|
|
267
|
+
const customPropertiesAsCjs = getObjectWithKeyAsCjs('customProperties', customProperties);
|
|
268
|
+
const customSelectorsAsCjs = getObjectWithKeyAsCjs('customSelectors', customSelectors);
|
|
269
|
+
const cjs = `module.exports = {${customMediaAsCjs},${customPropertiesAsCjs},${customSelectorsAsCjs}\n};\n`;
|
|
270
|
+
await writeFile(to, cjs);
|
|
271
|
+
}
|
|
272
|
+
/* Write Exports to Module JS file
|
|
273
|
+
/* ========================================================================== */
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
function getObjectWithKeyAsMjs(key, object) {
|
|
277
|
+
const mjsContents = Object.keys(object).reduce((mjsLines, name) => {
|
|
278
|
+
mjsLines.push(`\t'${escapeForJS(name)}': '${escapeForJS(object[name])}'`);
|
|
279
|
+
return mjsLines;
|
|
280
|
+
}, []).join(',\n');
|
|
281
|
+
const mjs = `export const ${key} = {\n${mjsContents}\n};\n`;
|
|
282
|
+
return mjs;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
async function writeExportsToMjsFile(to, customMedia, customProperties, customSelectors) {
|
|
286
|
+
const customMediaAsMjs = getObjectWithKeyAsMjs('customMedia', customMedia);
|
|
287
|
+
const customPropertiesAsMjs = getObjectWithKeyAsMjs('customProperties', customProperties);
|
|
288
|
+
const customSelectorsAsMjs = getObjectWithKeyAsMjs('customSelectors', customSelectors);
|
|
289
|
+
const mjs = `${customMediaAsMjs}\n${customPropertiesAsMjs}\n${customSelectorsAsMjs}`;
|
|
290
|
+
await writeFile(to, mjs);
|
|
291
|
+
}
|
|
292
|
+
/* Write Exports to Exports
|
|
293
|
+
/* ========================================================================== */
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
function writeToExports(customExports, destinations) {
|
|
297
|
+
return Promise.all([].concat(destinations).map(async destination => {
|
|
298
|
+
if (destination instanceof Function) {
|
|
299
|
+
await destination({
|
|
300
|
+
customMedia: getObjectWithStringifiedKeys(customExports.customMedia),
|
|
301
|
+
customProperties: getObjectWithStringifiedKeys(customExports.customProperties),
|
|
302
|
+
customSelectors: getObjectWithStringifiedKeys(customExports.customSelectors)
|
|
303
|
+
});
|
|
304
|
+
} else {
|
|
305
|
+
// read the destination as an object
|
|
306
|
+
const opts = destination === Object(destination) ? destination : {
|
|
307
|
+
to: String(destination)
|
|
308
|
+
}; // transformer for Exports into a JSON-compatible object
|
|
309
|
+
|
|
310
|
+
const toJSON = opts.toJSON || getObjectWithStringifiedKeys;
|
|
311
|
+
|
|
312
|
+
if ('customMedia' in opts || 'customProperties' in opts || 'customSelectors' in opts) {
|
|
313
|
+
// write directly to an object as customProperties
|
|
314
|
+
opts.customMedia = toJSON(customExports.customMedia);
|
|
315
|
+
opts.customProperties = toJSON(customExports.customProperties);
|
|
316
|
+
opts.customSelectors = toJSON(customExports.customSelectors);
|
|
317
|
+
} else if ('custom-media' in opts || 'custom-properties' in opts || 'custom-selectors' in opts) {
|
|
318
|
+
// write directly to an object as custom-properties
|
|
319
|
+
opts['custom-media'] = toJSON(customExports.customMedia);
|
|
320
|
+
opts['custom-properties'] = toJSON(customExports.customProperties);
|
|
321
|
+
opts['custom-selectors'] = toJSON(customExports.customSelectors);
|
|
322
|
+
} else {
|
|
323
|
+
// destination pathname
|
|
324
|
+
const to = String(opts.to || ''); // type of file being written to
|
|
325
|
+
|
|
326
|
+
const type = (opts.type || path__default["default"].extname(opts.to).slice(1)).toLowerCase(); // transformed Exports
|
|
327
|
+
|
|
328
|
+
const customMediaJSON = toJSON(customExports.customMedia);
|
|
329
|
+
const customPropertiesJSON = toJSON(customExports.customProperties);
|
|
330
|
+
const customSelectorsJSON = toJSON(customExports.customSelectors);
|
|
331
|
+
|
|
332
|
+
if (type === 'css') {
|
|
333
|
+
await writeExportsToCssFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (type === 'js') {
|
|
337
|
+
await writeExportsToCjsFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (type === 'json') {
|
|
341
|
+
await writeExportsToJsonFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (type === 'mjs') {
|
|
345
|
+
await writeExportsToMjsFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}));
|
|
350
|
+
}
|
|
351
|
+
/* Helper utilities
|
|
352
|
+
/* ========================================================================== */
|
|
353
|
+
|
|
354
|
+
function getObjectWithStringifiedKeys(object) {
|
|
355
|
+
return Object.keys(object).reduce((objectJSON, key) => {
|
|
356
|
+
objectJSON[key] = String(object[key]);
|
|
357
|
+
return objectJSON;
|
|
358
|
+
}, {});
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function writeFile(to, text) {
|
|
362
|
+
return new Promise((resolve, reject) => {
|
|
363
|
+
fs__default["default"].writeFile(to, text, error => {
|
|
364
|
+
if (error) {
|
|
365
|
+
reject(error);
|
|
366
|
+
} else {
|
|
367
|
+
resolve();
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function escapeForJS(string) {
|
|
374
|
+
return string.replace(/\\([\s\S])|(')/g, '\\$1$2').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const plugin = opts => {
|
|
378
|
+
// initialize options
|
|
379
|
+
const features = Object(Object(opts).features);
|
|
380
|
+
const insertBefore = Object(Object(opts).insertBefore);
|
|
381
|
+
const insertAfter = Object(Object(opts).insertAfter);
|
|
382
|
+
const browsers = Object(opts).browsers;
|
|
383
|
+
const stage = 'stage' in Object(opts) ? opts.stage === false ? 5 : parseInt(opts.stage) || 0 : 2;
|
|
384
|
+
const autoprefixerOptions = Object(opts).autoprefixer;
|
|
385
|
+
const sharedOpts = initializeSharedOpts(Object(opts));
|
|
386
|
+
const stagedAutoprefixer = autoprefixerOptions === false ? () => {} : autoprefixer__default["default"](Object.assign({
|
|
387
|
+
overrideBrowserslist: browsers
|
|
388
|
+
}, autoprefixerOptions)); // polyfillable features (those with an available postcss plugin)
|
|
389
|
+
|
|
390
|
+
const polyfillableFeatures = cssdb__default["default"].concat( // additional features to be inserted before cssdb features
|
|
391
|
+
getTransformedInsertions(insertBefore, 'insertBefore'), // additional features to be inserted after cssdb features
|
|
392
|
+
getTransformedInsertions(insertAfter, 'insertAfter')).filter( // inserted features or features with an available postcss plugin
|
|
393
|
+
feature => feature.insertBefore || feature.id in plugins).sort( // features sorted by execution order and then insertion order
|
|
394
|
+
(a, b) => idsByExecutionOrder.indexOf(a.id) - idsByExecutionOrder.indexOf(b.id) || (a.insertBefore ? -1 : b.insertBefore ? 1 : 0) || (a.insertAfter ? 1 : b.insertAfter ? -1 : 0)).map( // polyfillable features as an object
|
|
395
|
+
feature => {
|
|
396
|
+
// target browsers for the polyfill
|
|
397
|
+
const unsupportedBrowsers = getUnsupportedBrowsersByFeature(feature.caniuse);
|
|
398
|
+
return feature.insertBefore || feature.insertAfter ? {
|
|
399
|
+
browsers: unsupportedBrowsers,
|
|
400
|
+
plugin: feature.plugin,
|
|
401
|
+
id: `${feature.insertBefore ? 'before' : 'after'}-${feature.id}`,
|
|
402
|
+
stage: 6
|
|
403
|
+
} : {
|
|
404
|
+
browsers: unsupportedBrowsers,
|
|
405
|
+
plugin: plugins[feature.id],
|
|
406
|
+
id: feature.id,
|
|
407
|
+
stage: feature.stage
|
|
408
|
+
};
|
|
409
|
+
}); // staged features (those at or above the selected stage)
|
|
410
|
+
|
|
411
|
+
const stagedFeatures = polyfillableFeatures.filter(feature => feature.id in features ? features[feature.id] : feature.stage >= stage).map(feature => {
|
|
412
|
+
let options;
|
|
413
|
+
let plugin;
|
|
414
|
+
|
|
415
|
+
if (features[feature.id] === true) {
|
|
416
|
+
// if the plugin is enabled
|
|
417
|
+
options = sharedOpts ? Object.assign({}, sharedOpts) : undefined;
|
|
418
|
+
} else {
|
|
419
|
+
options = sharedOpts // if the plugin has shared options and individual options
|
|
420
|
+
? Object.assign({}, sharedOpts, features[feature.id]) // if the plugin has individual options
|
|
421
|
+
: Object.assign({}, features[feature.id]);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (feature.plugin.postcss) {
|
|
425
|
+
plugin = feature.plugin(options);
|
|
426
|
+
} else {
|
|
427
|
+
plugin = feature.plugin;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return {
|
|
431
|
+
browsers: feature.browsers,
|
|
432
|
+
plugin,
|
|
433
|
+
id: feature.id
|
|
434
|
+
};
|
|
435
|
+
}); // browsers supported by the configuration
|
|
436
|
+
|
|
437
|
+
const supportedBrowsers = browserslist__default["default"](browsers, {
|
|
438
|
+
ignoreUnknownVersions: true
|
|
439
|
+
}); // features supported by the stage and browsers
|
|
440
|
+
|
|
441
|
+
const supportedFeatures = stagedFeatures.filter(feature => feature.id in features ? features[feature.id] : supportedBrowsers.some(supportedBrowser => browserslist__default["default"](feature.browsers, {
|
|
442
|
+
ignoreUnknownVersions: true
|
|
443
|
+
}).some(polyfillBrowser => polyfillBrowser === supportedBrowser)));
|
|
444
|
+
const usedPlugins = supportedFeatures.map(feature => feature.plugin);
|
|
445
|
+
usedPlugins.push(stagedAutoprefixer);
|
|
446
|
+
return {
|
|
447
|
+
postcssPlugin: 'postcss-preset-env',
|
|
448
|
+
plugins: usedPlugins,
|
|
449
|
+
OnceExit: function () {
|
|
450
|
+
if (Object(opts).exportTo) {
|
|
451
|
+
writeToExports(sharedOpts.exportTo, opts.exportTo);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
const initializeSharedOpts = opts => {
|
|
458
|
+
if ('importFrom' in opts || 'exportTo' in opts || 'preserve' in opts) {
|
|
459
|
+
const sharedOpts = {};
|
|
460
|
+
|
|
461
|
+
if ('importFrom' in opts) {
|
|
462
|
+
sharedOpts.importFrom = opts.importFrom;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if ('exportTo' in opts) {
|
|
466
|
+
sharedOpts.exportTo = {
|
|
467
|
+
customMedia: {},
|
|
468
|
+
customProperties: {},
|
|
469
|
+
customSelectors: {}
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if ('preserve' in opts) {
|
|
474
|
+
sharedOpts.preserve = opts.preserve;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return sharedOpts;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return false;
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
plugin.postcss = true;
|
|
484
|
+
|
|
485
|
+
module.exports = plugin;
|