123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- 'use strict';
- const browserslist = require('browserslist');
- const valueParser = require('postcss-value-parser');
- const regexLowerCaseUPrefix = /^u(?=\+)/;
- /**
- * @param {string} range
- * @return {string}
- */
- function unicode(range) {
- const values = range.slice(2).split('-');
- if (values.length < 2) {
- return range;
- }
- const left = values[0].split('');
- const right = values[1].split('');
- if (left.length !== right.length) {
- return range;
- }
- const merged = mergeRangeBounds(left, right);
- if (merged) {
- return merged;
- }
- return range;
- }
- /**
- * @param {string[]} left
- * @param {string[]} right
- * @return {false|string}
- */
- function mergeRangeBounds(left, right) {
- let questionCounter = 0;
- let group = 'u+';
- for (const [index, value] of left.entries()) {
- if (value === right[index] && questionCounter === 0) {
- group = group + value;
- } else if (value === '0' && right[index] === 'f') {
- questionCounter++;
- group = group + '?';
- } else {
- return false;
- }
- }
- // The maximum number of wildcard characters (?) for ranges is 5.
- if (questionCounter < 6) {
- return group;
- } else {
- return false;
- }
- }
- /**
- * IE and Edge before 16 version ignore the unicode-range if the 'U' is lowercase
- *
- * https://caniuse.com/#search=unicode-range
- *
- * @param {string} browser
- * @return {boolean}
- */
- function hasLowerCaseUPrefixBug(browser) {
- return browserslist('ie <=11, edge <= 15').includes(browser);
- }
- /**
- * @param {string} value
- * @return {string}
- */
- function transform(value, isLegacy = false) {
- return valueParser(value)
- .walk((child) => {
- if (child.type === 'unicode-range') {
- const transformed = unicode(child.value.toLowerCase());
- child.value = isLegacy
- ? transformed.replace(regexLowerCaseUPrefix, 'U')
- : transformed;
- }
- return false;
- })
- .toString();
- }
- /**
- * @type {import('postcss').PluginCreator<void>}
- * @return {import('postcss').Plugin}
- */
- function pluginCreator() {
- return {
- postcssPlugin: 'postcss-normalize-unicode',
- /** @param {import('postcss').Result & {opts: browserslist.Options}} result*/
- prepare(result) {
- const cache = new Map();
- const resultOpts = result.opts || {};
- const browsers = browserslist(null, {
- stats: resultOpts.stats,
- path: __dirname,
- env: resultOpts.env,
- });
- const isLegacy = browsers.some(hasLowerCaseUPrefixBug);
- return {
- OnceExit(css) {
- css.walkDecls(/^unicode-range$/i, (decl) => {
- const value = decl.value;
- if (cache.has(value)) {
- decl.value = cache.get(value);
- return;
- }
- const newValue = transform(value, isLegacy);
- decl.value = newValue;
- cache.set(value, newValue);
- });
- },
- };
- },
- };
- }
- pluginCreator.postcss = true;
- module.exports = pluginCreator;
|