UNPKG

21.1 kBJavaScriptView Raw
1'use strict';
2
3function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
4
5var autoprefixer = _interopDefault(require('autoprefixer'));
6var browserslist = _interopDefault(require('browserslist'));
7var cssdb = _interopDefault(require('cssdb'));
8var postcss$1 = _interopDefault(require('postcss'));
9var postcssAttributeCaseInsensitive = _interopDefault(require('postcss-attribute-case-insensitive'));
10var postcssBlankPseudo = _interopDefault(require('css-blank-pseudo/postcss'));
11var postcssColorFunctionalNotation = _interopDefault(require('postcss-color-functional-notation'));
12var postcssColorGray = _interopDefault(require('postcss-color-gray'));
13var postcssColorHexAlpha = _interopDefault(require('postcss-color-hex-alpha'));
14var postcssColorModFunction = _interopDefault(require('postcss-color-mod-function'));
15var postcssColorRebeccapurple = _interopDefault(require('postcss-color-rebeccapurple'));
16var postcssCustomMedia = _interopDefault(require('postcss-custom-media'));
17var postcssCustomProperties = _interopDefault(require('postcss-custom-properties'));
18var postcssCustomSelectors = _interopDefault(require('postcss-custom-selectors'));
19var postcssDirPseudoClass = _interopDefault(require('postcss-dir-pseudo-class'));
20var postcssDoublePositionGradients = _interopDefault(require('postcss-double-position-gradients'));
21var postcssEnvFunction = _interopDefault(require('postcss-env-function'));
22var postcssFocusVisible = _interopDefault(require('postcss-focus-visible'));
23var postcssFocusWithin = _interopDefault(require('postcss-focus-within'));
24var postcssFontVariant = _interopDefault(require('postcss-font-variant'));
25var postcssGapProperties = _interopDefault(require('postcss-gap-properties'));
26var postcssHasPseudo = _interopDefault(require('css-has-pseudo/postcss'));
27var postcssImageSetPolyfill = _interopDefault(require('postcss-image-set-function'));
28var postcssInitial = _interopDefault(require('postcss-initial'));
29var postcssLabFunction = _interopDefault(require('postcss-lab-function'));
30var postcssLogical = _interopDefault(require('postcss-logical'));
31var postcssMediaMinmax = _interopDefault(require('postcss-media-minmax'));
32var postcssNesting = _interopDefault(require('postcss-nesting'));
33var postcssOverflowShorthand = _interopDefault(require('postcss-overflow-shorthand'));
34var postcssPageBreak = _interopDefault(require('postcss-page-break'));
35var postcssPlace = _interopDefault(require('postcss-place'));
36var postcssPrefersColorScheme = _interopDefault(require('css-prefers-color-scheme/postcss'));
37var postcssPseudoClassAnyLink = _interopDefault(require('postcss-pseudo-class-any-link'));
38var postcssReplaceOverflowWrap = _interopDefault(require('postcss-replace-overflow-wrap'));
39var postcssSelectorMatches = _interopDefault(require('postcss-selector-matches'));
40var postcssSelectorNot = _interopDefault(require('postcss-selector-not'));
41var caniuse = require('caniuse-lite');
42var fs = _interopDefault(require('fs'));
43var path = _interopDefault(require('path'));
44
45var postcssFontFamilySystemUi = postcss$1.plugin('postcss-system-ui-font', () => root => {
46 root.walkDecls(propertyRegExp, decl => {
47 decl.value = decl.value.replace(systemUiMatch, systemUiReplace);
48 });
49});
50const propertyRegExp = /(?:^(?:-|\\002d){2})|(?:^font(?:-family)?$)/i;
51const whitespace = '[\\f\\n\\r\\x09\\x20]';
52const systemUiFamily = ['system-ui',
53/* macOS 10.11-10.12 */
54'-apple-system',
55/* Windows 6+ */
56'Segoe UI',
57/* Android 4+ */
58'Roboto',
59/* Ubuntu 10.10+ */
60'Ubuntu',
61/* Gnome 3+ */
62'Cantarell',
63/* KDE Plasma 5+ */
64'Noto Sans',
65/* fallback */
66'sans-serif'];
67const systemUiMatch = new RegExp(`(^|,|${whitespace}+)(?:system-ui${whitespace}*)(?:,${whitespace}*(?:${systemUiFamily.join('|')})${whitespace}*)?(,|$)`, 'i');
68const systemUiReplace = `$1${systemUiFamily.join(', ')}$2`;
69
70var plugins = {
71 'all-property': postcssInitial,
72 'any-link-pseudo-class': postcssPseudoClassAnyLink,
73 'blank-pseudo-class': postcssBlankPseudo,
74 'break-properties': postcssPageBreak,
75 'case-insensitive-attributes': postcssAttributeCaseInsensitive,
76 'color-functional-notation': postcssColorFunctionalNotation,
77 'color-mod-function': postcssColorModFunction,
78 'custom-media-queries': postcssCustomMedia,
79 'custom-properties': postcssCustomProperties,
80 'custom-selectors': postcssCustomSelectors,
81 'dir-pseudo-class': postcssDirPseudoClass,
82 'double-position-gradients': postcssDoublePositionGradients,
83 'environment-variables': postcssEnvFunction,
84 'focus-visible-pseudo-class': postcssFocusVisible,
85 'focus-within-pseudo-class': postcssFocusWithin,
86 'font-variant-property': postcssFontVariant,
87 'gap-properties': postcssGapProperties,
88 'gray-function': postcssColorGray,
89 'has-pseudo-class': postcssHasPseudo,
90 'hexadecimal-alpha-notation': postcssColorHexAlpha,
91 'image-set-function': postcssImageSetPolyfill,
92 'lab-function': postcssLabFunction,
93 'logical-properties-and-values': postcssLogical,
94 'matches-pseudo-class': postcssSelectorMatches,
95 'media-query-ranges': postcssMediaMinmax,
96 'nesting-rules': postcssNesting,
97 'not-pseudo-class': postcssSelectorNot,
98 'overflow-property': postcssOverflowShorthand,
99 'overflow-wrap-property': postcssReplaceOverflowWrap,
100 'place-properties': postcssPlace,
101 'prefers-color-scheme-query': postcssPrefersColorScheme,
102 'rebeccapurple-color': postcssColorRebeccapurple,
103 'system-ui-font-family': postcssFontFamilySystemUi
104};
105
106// return a list of features to be inserted before or after cssdb features
107function getTransformedInsertions(insertions, placement) {
108 return Object.keys(insertions).map(id => [].concat(insertions[id]).map(plugin => ({
109 [placement]: true,
110 plugin,
111 id
112 }))).reduce((array, feature) => array.concat(feature), []);
113}
114
115function getUnsupportedBrowsersByFeature(feature) {
116 const caniuseFeature = caniuse.features[feature]; // if feature support can be determined
117
118 if (caniuseFeature) {
119 const stats = caniuse.feature(caniuseFeature).stats; // return an array of browsers and versions that do not support the feature
120
121 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}`)), []);
122 return results;
123 } else {
124 // otherwise, return that the feature does not work in any browser
125 return ['> 0%'];
126 }
127}
128
129// ids ordered by required execution, then alphabetically
130var idsByExecutionOrder = ['custom-media-queries', 'custom-properties', 'environment-variables', // run environment-variables here to access transpiled custom media params and properties
131'image-set-function', // run images-set-function before nesting-rules so that it may fix nested media
132'media-query-ranges', // run media-query-range and
133'prefers-color-scheme-query', // run prefers-color-scheme-query here to prevent duplicate transpilation after nesting-rules
134'nesting-rules', 'custom-selectors', // run custom-selectors after nesting-rules to correctly transpile &:--custom-selector
135'any-link-pseudo-class', 'case-insensitive-attributes', 'focus-visible-pseudo-class', 'focus-within-pseudo-class', 'matches-pseudo-class', // run matches-pseudo-class and
136'not-pseudo-class', // run not-pseudo-class after other selectors have been transpiled
137'logical-properties-and-values', // run logical-properties-and-values before dir-pseudo-class
138'dir-pseudo-class', 'all-property', // run all-property before other property polyfills
139'color-functional-notation', 'double-position-gradients', 'gray-function', 'hexadecimal-alpha-notation', 'lab-function', 'rebeccapurple-color', 'color-mod-function', // run color-mod after other color modifications have finished
140'blank-pseudo-class', 'break-properties', 'font-variant-property', 'has-pseudo-class', 'gap-properties', 'overflow-property', 'overflow-wrap-property', 'place-properties', 'system-ui-font-family'];
141
142function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
143 try {
144 var info = gen[key](arg);
145 var value = info.value;
146 } catch (error) {
147 reject(error);
148 return;
149 }
150
151 if (info.done) {
152 resolve(value);
153 } else {
154 Promise.resolve(value).then(_next, _throw);
155 }
156}
157
158function _asyncToGenerator(fn) {
159 return function () {
160 var self = this,
161 args = arguments;
162 return new Promise(function (resolve, reject) {
163 var gen = fn.apply(self, args);
164
165 function _next(value) {
166 asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
167 }
168
169 function _throw(err) {
170 asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
171 }
172
173 _next(undefined);
174 });
175 };
176}
177
178/* Write Exports to CSS File
179/* ========================================================================== */
180
181function getCustomMediaAsCss(customMedia) {
182 const cssContent = Object.keys(customMedia).reduce((cssLines, name) => {
183 cssLines.push(`@custom-media ${name} ${customMedia[name]};`);
184 return cssLines;
185 }, []).join('\n');
186 const css = `${cssContent}\n`;
187 return css;
188}
189
190function getCustomPropertiesAsCss(customProperties) {
191 const cssContent = Object.keys(customProperties).reduce((cssLines, name) => {
192 cssLines.push(`\t${name}: ${customProperties[name]};`);
193 return cssLines;
194 }, []).join('\n');
195 const css = `:root {\n${cssContent}\n}\n`;
196 return css;
197}
198
199function getCustomSelectorsAsCss(customSelectors) {
200 const cssContent = Object.keys(customSelectors).reduce((cssLines, name) => {
201 cssLines.push(`@custom-selector ${name} ${customSelectors[name]};`);
202 return cssLines;
203 }, []).join('\n');
204 const css = `${cssContent}\n`;
205 return css;
206}
207
208function writeExportsToCssFile(_x, _x2, _x3, _x4) {
209 return _writeExportsToCssFile.apply(this, arguments);
210}
211/* Write Exports to JSON file
212/* ========================================================================== */
213
214
215function _writeExportsToCssFile() {
216 _writeExportsToCssFile = _asyncToGenerator(function* (to, customMedia, customProperties, customSelectors) {
217 const customPropertiesAsCss = getCustomPropertiesAsCss(customProperties);
218 const customMediaAsCss = getCustomMediaAsCss(customMedia);
219 const customSelectorsAsCss = getCustomSelectorsAsCss(customSelectors);
220 const css = `${customMediaAsCss}\n${customSelectorsAsCss}\n${customPropertiesAsCss}`;
221 yield writeFile(to, css);
222 });
223 return _writeExportsToCssFile.apply(this, arguments);
224}
225
226function writeExportsToJsonFile(_x5, _x6, _x7, _x8) {
227 return _writeExportsToJsonFile.apply(this, arguments);
228}
229/* Write Exports to Common JS file
230/* ========================================================================== */
231
232
233function _writeExportsToJsonFile() {
234 _writeExportsToJsonFile = _asyncToGenerator(function* (to, customMedia, customProperties, customSelectors) {
235 const jsonContent = JSON.stringify({
236 'custom-media': customMedia,
237 'custom-properties': customProperties,
238 'custom-selectors': customSelectors
239 }, null, ' ');
240 const json = `${jsonContent}\n`;
241 yield writeFile(to, json);
242 });
243 return _writeExportsToJsonFile.apply(this, arguments);
244}
245
246function getObjectWithKeyAsCjs(key, object) {
247 const jsContents = Object.keys(object).reduce((jsLines, name) => {
248 jsLines.push(`\t\t'${escapeForJS(name)}': '${escapeForJS(object[name])}'`);
249 return jsLines;
250 }, []).join(',\n');
251 const cjs = `\n\t${key}: {\n${jsContents}\n\t}`;
252 return cjs;
253}
254
255function writeExportsToCjsFile(_x9, _x10, _x11, _x12) {
256 return _writeExportsToCjsFile.apply(this, arguments);
257}
258/* Write Exports to Module JS file
259/* ========================================================================== */
260
261
262function _writeExportsToCjsFile() {
263 _writeExportsToCjsFile = _asyncToGenerator(function* (to, customMedia, customProperties, customSelectors) {
264 const customMediaAsCjs = getObjectWithKeyAsCjs('customMedia', customMedia);
265 const customPropertiesAsCjs = getObjectWithKeyAsCjs('customProperties', customProperties);
266 const customSelectorsAsCjs = getObjectWithKeyAsCjs('customSelectors', customSelectors);
267 const cjs = `module.exports = {${customMediaAsCjs},${customPropertiesAsCjs},${customSelectorsAsCjs}\n};\n`;
268 yield writeFile(to, cjs);
269 });
270 return _writeExportsToCjsFile.apply(this, arguments);
271}
272
273function getObjectWithKeyAsMjs(key, object) {
274 const mjsContents = Object.keys(object).reduce((mjsLines, name) => {
275 mjsLines.push(`\t'${escapeForJS(name)}': '${escapeForJS(object[name])}'`);
276 return mjsLines;
277 }, []).join(',\n');
278 const mjs = `export const ${key} = {\n${mjsContents}\n};\n`;
279 return mjs;
280}
281
282function writeExportsToMjsFile(_x13, _x14, _x15, _x16) {
283 return _writeExportsToMjsFile.apply(this, arguments);
284}
285/* Write Exports to Exports
286/* ========================================================================== */
287
288
289function _writeExportsToMjsFile() {
290 _writeExportsToMjsFile = _asyncToGenerator(function* (to, customMedia, customProperties, customSelectors) {
291 const customMediaAsMjs = getObjectWithKeyAsMjs('customMedia', customMedia);
292 const customPropertiesAsMjs = getObjectWithKeyAsMjs('customProperties', customProperties);
293 const customSelectorsAsMjs = getObjectWithKeyAsMjs('customSelectors', customSelectors);
294 const mjs = `${customMediaAsMjs}\n${customPropertiesAsMjs}\n${customSelectorsAsMjs}`;
295 yield writeFile(to, mjs);
296 });
297 return _writeExportsToMjsFile.apply(this, arguments);
298}
299
300function writeToExports(customExports, destinations) {
301 return Promise.all([].concat(destinations).map(
302 /*#__PURE__*/
303 function () {
304 var _ref = _asyncToGenerator(function* (destination) {
305 if (destination instanceof Function) {
306 yield destination({
307 customMedia: getObjectWithStringifiedKeys(customExports.customMedia),
308 customProperties: getObjectWithStringifiedKeys(customExports.customProperties),
309 customSelectors: getObjectWithStringifiedKeys(customExports.customSelectors)
310 });
311 } else {
312 // read the destination as an object
313 const opts = destination === Object(destination) ? destination : {
314 to: String(destination)
315 }; // transformer for Exports into a JSON-compatible object
316
317 const toJSON = opts.toJSON || getObjectWithStringifiedKeys;
318
319 if ('customMedia' in opts || 'customProperties' in opts || 'customSelectors' in opts) {
320 // write directly to an object as customProperties
321 opts.customMedia = toJSON(customExports.customMedia);
322 opts.customProperties = toJSON(customExports.customProperties);
323 opts.customSelectors = toJSON(customExports.customSelectors);
324 } else if ('custom-media' in opts || 'custom-properties' in opts || 'custom-selectors' in opts) {
325 // write directly to an object as custom-properties
326 opts['custom-media'] = toJSON(customExports.customMedia);
327 opts['custom-properties'] = toJSON(customExports.customProperties);
328 opts['custom-selectors'] = toJSON(customExports.customSelectors);
329 } else {
330 // destination pathname
331 const to = String(opts.to || ''); // type of file being written to
332
333 const type = (opts.type || path.extname(opts.to).slice(1)).toLowerCase(); // transformed Exports
334
335 const customMediaJSON = toJSON(customExports.customMedia);
336 const customPropertiesJSON = toJSON(customExports.customProperties);
337 const customSelectorsJSON = toJSON(customExports.customSelectors);
338
339 if (type === 'css') {
340 yield writeExportsToCssFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON);
341 }
342
343 if (type === 'js') {
344 yield writeExportsToCjsFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON);
345 }
346
347 if (type === 'json') {
348 yield writeExportsToJsonFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON);
349 }
350
351 if (type === 'mjs') {
352 yield writeExportsToMjsFile(to, customMediaJSON, customPropertiesJSON, customSelectorsJSON);
353 }
354 }
355 }
356 });
357
358 return function (_x17) {
359 return _ref.apply(this, arguments);
360 };
361 }()));
362}
363/* Helper utilities
364/* ========================================================================== */
365
366function getObjectWithStringifiedKeys(object) {
367 return Object.keys(object).reduce((objectJSON, key) => {
368 objectJSON[key] = String(object[key]);
369 return objectJSON;
370 }, {});
371}
372
373function writeFile(to, text) {
374 return new Promise((resolve, reject) => {
375 fs.writeFile(to, text, error => {
376 if (error) {
377 reject(error);
378 } else {
379 resolve();
380 }
381 });
382 });
383}
384
385function escapeForJS(string) {
386 return string.replace(/\\([\s\S])|(')/g, '\\$1$2').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
387}
388
389var postcss = postcss$1.plugin('postcss-preset-env', opts => {
390 // initialize options
391 const features = Object(Object(opts).features);
392 const insertBefore = Object(Object(opts).insertBefore);
393 const insertAfter = Object(Object(opts).insertAfter);
394 const browsers = Object(opts).browsers;
395 const stage = 'stage' in Object(opts) ? opts.stage === false ? 5 : parseInt(opts.stage) || 0 : 2;
396 const autoprefixerOptions = Object(opts).autoprefixer;
397 const sharedOpts = initializeSharedOpts(Object(opts));
398 const stagedAutoprefixer = autoprefixerOptions === false ? () => {} : autoprefixer(Object.assign({
399 overrideBrowserslist: browsers
400 }, autoprefixerOptions)); // polyfillable features (those with an available postcss plugin)
401
402 const polyfillableFeatures = cssdb.concat( // additional features to be inserted before cssdb features
403 getTransformedInsertions(insertBefore, 'insertBefore'), // additional features to be inserted after cssdb features
404 getTransformedInsertions(insertAfter, 'insertAfter')).filter( // inserted features or features with an available postcss plugin
405 feature => feature.insertBefore || feature.id in plugins).sort( // features sorted by execution order and then insertion order
406 (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
407 feature => {
408 // target browsers for the polyfill
409 const unsupportedBrowsers = getUnsupportedBrowsersByFeature(feature.caniuse);
410 return feature.insertBefore || feature.insertAfter ? {
411 browsers: unsupportedBrowsers,
412 plugin: feature.plugin,
413 id: `${feature.insertBefore ? 'before' : 'after'}-${feature.id}`,
414 stage: 6
415 } : {
416 browsers: unsupportedBrowsers,
417 plugin: plugins[feature.id],
418 id: feature.id,
419 stage: feature.stage
420 };
421 }); // staged features (those at or above the selected stage)
422
423 const stagedFeatures = polyfillableFeatures.filter(feature => feature.id in features ? features[feature.id] : feature.stage >= stage).map(feature => ({
424 browsers: feature.browsers,
425 plugin: typeof feature.plugin.process === 'function' ? features[feature.id] === true ? sharedOpts // if the plugin is enabled and has shared options
426 ? feature.plugin(Object.assign({}, sharedOpts)) // otherwise, if the plugin is enabled
427 : feature.plugin() : sharedOpts // if the plugin has shared options and individual options
428 ? feature.plugin(Object.assign({}, sharedOpts, features[feature.id])) // if the plugin has individual options
429 : feature.plugin(Object.assign({}, features[feature.id])) // if the plugin is already initialized
430 : feature.plugin,
431 id: feature.id
432 })); // browsers supported by the configuration
433
434 const supportedBrowsers = browserslist(browsers, {
435 ignoreUnknownVersions: true
436 }); // features supported by the stage and browsers
437
438 const supportedFeatures = stagedFeatures.filter(feature => supportedBrowsers.some(supportedBrowser => browserslist(feature.browsers, {
439 ignoreUnknownVersions: true
440 }).some(polyfillBrowser => polyfillBrowser === supportedBrowser)));
441 return (root, result) => {
442 // polyfills run in execution order
443 const polyfills = supportedFeatures.reduce((promise, feature) => promise.then(() => feature.plugin(result.root, result)), Promise.resolve()).then(() => stagedAutoprefixer(result.root, result)).then(() => {
444 if (Object(opts).exportTo) {
445 writeToExports(sharedOpts.exportTo, opts.exportTo);
446 }
447 });
448 return polyfills;
449 };
450});
451
452const initializeSharedOpts = opts => {
453 if ('importFrom' in opts || 'exportTo' in opts || 'preserve' in opts) {
454 const sharedOpts = {};
455
456 if ('importFrom' in opts) {
457 sharedOpts.importFrom = opts.importFrom;
458 }
459
460 if ('exportTo' in opts) {
461 sharedOpts.exportTo = {
462 customMedia: {},
463 customProperties: {},
464 customSelectors: {}
465 };
466 }
467
468 if ('preserve' in opts) {
469 sharedOpts.preserve = opts.preserve;
470 }
471
472 return sharedOpts;
473 }
474
475 return false;
476};
477
478module.exports = postcss;
479//# sourceMappingURL=index.js.map