mirror of
https://github.com/idanoo/GoScrobble.git
synced 2024-11-25 09:55:15 +00:00
574 lines
14 KiB
JavaScript
574 lines
14 KiB
JavaScript
|
import isInBrowser from 'is-in-browser';
|
||
|
import _toConsumableArray from '@babel/runtime/helpers/esm/toConsumableArray';
|
||
|
|
||
|
// Export javascript style and css style vendor prefixes.
|
||
|
var js = '';
|
||
|
var css = '';
|
||
|
var vendor = '';
|
||
|
var browser = '';
|
||
|
var isTouch = isInBrowser && 'ontouchstart' in document.documentElement; // We should not do anything if required serverside.
|
||
|
|
||
|
if (isInBrowser) {
|
||
|
// Order matters. We need to check Webkit the last one because
|
||
|
// other vendors use to add Webkit prefixes to some properties
|
||
|
var jsCssMap = {
|
||
|
Moz: '-moz-',
|
||
|
ms: '-ms-',
|
||
|
O: '-o-',
|
||
|
Webkit: '-webkit-'
|
||
|
};
|
||
|
|
||
|
var _document$createEleme = document.createElement('p'),
|
||
|
style = _document$createEleme.style;
|
||
|
|
||
|
var testProp = 'Transform';
|
||
|
|
||
|
for (var key in jsCssMap) {
|
||
|
if (key + testProp in style) {
|
||
|
js = key;
|
||
|
css = jsCssMap[key];
|
||
|
break;
|
||
|
}
|
||
|
} // Correctly detect the Edge browser.
|
||
|
|
||
|
|
||
|
if (js === 'Webkit' && 'msHyphens' in style) {
|
||
|
js = 'ms';
|
||
|
css = jsCssMap.ms;
|
||
|
browser = 'edge';
|
||
|
} // Correctly detect the Safari browser.
|
||
|
|
||
|
|
||
|
if (js === 'Webkit' && '-apple-trailing-word' in style) {
|
||
|
vendor = 'apple';
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Vendor prefix string for the current browser.
|
||
|
*
|
||
|
* @type {{js: String, css: String, vendor: String, browser: String}}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
|
||
|
var prefix = {
|
||
|
js: js,
|
||
|
css: css,
|
||
|
vendor: vendor,
|
||
|
browser: browser,
|
||
|
isTouch: isTouch
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Test if a keyframe at-rule should be prefixed or not
|
||
|
*
|
||
|
* @param {String} vendor prefix string for the current browser.
|
||
|
* @return {String}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
function supportedKeyframes(key) {
|
||
|
// Keyframes is already prefixed. e.g. key = '@-webkit-keyframes a'
|
||
|
if (key[1] === '-') return key; // No need to prefix IE/Edge. Older browsers will ignore unsupported rules.
|
||
|
// https://caniuse.com/#search=keyframes
|
||
|
|
||
|
if (prefix.js === 'ms') return key;
|
||
|
return "@" + prefix.css + "keyframes" + key.substr(10);
|
||
|
}
|
||
|
|
||
|
// https://caniuse.com/#search=appearance
|
||
|
|
||
|
var appearence = {
|
||
|
noPrefill: ['appearance'],
|
||
|
supportedProperty: function supportedProperty(prop) {
|
||
|
if (prop !== 'appearance') return false;
|
||
|
if (prefix.js === 'ms') return "-webkit-" + prop;
|
||
|
return prefix.css + prop;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// https://caniuse.com/#search=color-adjust
|
||
|
|
||
|
var colorAdjust = {
|
||
|
noPrefill: ['color-adjust'],
|
||
|
supportedProperty: function supportedProperty(prop) {
|
||
|
if (prop !== 'color-adjust') return false;
|
||
|
if (prefix.js === 'Webkit') return prefix.css + "print-" + prop;
|
||
|
return prop;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var regExp = /[-\s]+(.)?/g;
|
||
|
/**
|
||
|
* Replaces the letter with the capital letter
|
||
|
*
|
||
|
* @param {String} match
|
||
|
* @param {String} c
|
||
|
* @return {String}
|
||
|
* @api private
|
||
|
*/
|
||
|
|
||
|
function toUpper(match, c) {
|
||
|
return c ? c.toUpperCase() : '';
|
||
|
}
|
||
|
/**
|
||
|
* Convert dash separated strings to camel-cased.
|
||
|
*
|
||
|
* @param {String} str
|
||
|
* @return {String}
|
||
|
* @api private
|
||
|
*/
|
||
|
|
||
|
|
||
|
function camelize(str) {
|
||
|
return str.replace(regExp, toUpper);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Convert dash separated strings to pascal cased.
|
||
|
*
|
||
|
* @param {String} str
|
||
|
* @return {String}
|
||
|
* @api private
|
||
|
*/
|
||
|
|
||
|
function pascalize(str) {
|
||
|
return camelize("-" + str);
|
||
|
}
|
||
|
|
||
|
// but we can use a longhand property instead.
|
||
|
// https://caniuse.com/#search=mask
|
||
|
|
||
|
var mask = {
|
||
|
noPrefill: ['mask'],
|
||
|
supportedProperty: function supportedProperty(prop, style) {
|
||
|
if (!/^mask/.test(prop)) return false;
|
||
|
|
||
|
if (prefix.js === 'Webkit') {
|
||
|
var longhand = 'mask-image';
|
||
|
|
||
|
if (camelize(longhand) in style) {
|
||
|
return prop;
|
||
|
}
|
||
|
|
||
|
if (prefix.js + pascalize(longhand) in style) {
|
||
|
return prefix.css + prop;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return prop;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// https://caniuse.com/#search=text-orientation
|
||
|
|
||
|
var textOrientation = {
|
||
|
noPrefill: ['text-orientation'],
|
||
|
supportedProperty: function supportedProperty(prop) {
|
||
|
if (prop !== 'text-orientation') return false;
|
||
|
|
||
|
if (prefix.vendor === 'apple' && !prefix.isTouch) {
|
||
|
return prefix.css + prop;
|
||
|
}
|
||
|
|
||
|
return prop;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// https://caniuse.com/#search=transform
|
||
|
|
||
|
var transform = {
|
||
|
noPrefill: ['transform'],
|
||
|
supportedProperty: function supportedProperty(prop, style, options) {
|
||
|
if (prop !== 'transform') return false;
|
||
|
|
||
|
if (options.transform) {
|
||
|
return prop;
|
||
|
}
|
||
|
|
||
|
return prefix.css + prop;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// https://caniuse.com/#search=transition
|
||
|
|
||
|
var transition = {
|
||
|
noPrefill: ['transition'],
|
||
|
supportedProperty: function supportedProperty(prop, style, options) {
|
||
|
if (prop !== 'transition') return false;
|
||
|
|
||
|
if (options.transition) {
|
||
|
return prop;
|
||
|
}
|
||
|
|
||
|
return prefix.css + prop;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// https://caniuse.com/#search=writing-mode
|
||
|
|
||
|
var writingMode = {
|
||
|
noPrefill: ['writing-mode'],
|
||
|
supportedProperty: function supportedProperty(prop) {
|
||
|
if (prop !== 'writing-mode') return false;
|
||
|
|
||
|
if (prefix.js === 'Webkit' || prefix.js === 'ms' && prefix.browser !== 'edge') {
|
||
|
return prefix.css + prop;
|
||
|
}
|
||
|
|
||
|
return prop;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// https://caniuse.com/#search=user-select
|
||
|
|
||
|
var userSelect = {
|
||
|
noPrefill: ['user-select'],
|
||
|
supportedProperty: function supportedProperty(prop) {
|
||
|
if (prop !== 'user-select') return false;
|
||
|
|
||
|
if (prefix.js === 'Moz' || prefix.js === 'ms' || prefix.vendor === 'apple') {
|
||
|
return prefix.css + prop;
|
||
|
}
|
||
|
|
||
|
return prop;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// https://caniuse.com/#search=multicolumn
|
||
|
// https://github.com/postcss/autoprefixer/issues/491
|
||
|
// https://github.com/postcss/autoprefixer/issues/177
|
||
|
|
||
|
var breakPropsOld = {
|
||
|
supportedProperty: function supportedProperty(prop, style) {
|
||
|
if (!/^break-/.test(prop)) return false;
|
||
|
|
||
|
if (prefix.js === 'Webkit') {
|
||
|
var jsProp = "WebkitColumn" + pascalize(prop);
|
||
|
return jsProp in style ? prefix.css + "column-" + prop : false;
|
||
|
}
|
||
|
|
||
|
if (prefix.js === 'Moz') {
|
||
|
var _jsProp = "page" + pascalize(prop);
|
||
|
|
||
|
return _jsProp in style ? "page-" + prop : false;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// See https://github.com/postcss/autoprefixer/issues/324.
|
||
|
|
||
|
var inlineLogicalOld = {
|
||
|
supportedProperty: function supportedProperty(prop, style) {
|
||
|
if (!/^(border|margin|padding)-inline/.test(prop)) return false;
|
||
|
if (prefix.js === 'Moz') return prop;
|
||
|
var newProp = prop.replace('-inline', '');
|
||
|
return prefix.js + pascalize(newProp) in style ? prefix.css + newProp : false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Camelization is required because we can't test using.
|
||
|
// CSS syntax for e.g. in FF.
|
||
|
|
||
|
var unprefixed = {
|
||
|
supportedProperty: function supportedProperty(prop, style) {
|
||
|
return camelize(prop) in style ? prop : false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var prefixed = {
|
||
|
supportedProperty: function supportedProperty(prop, style) {
|
||
|
var pascalized = pascalize(prop); // Return custom CSS variable without prefixing.
|
||
|
|
||
|
if (prop[0] === '-') return prop; // Return already prefixed value without prefixing.
|
||
|
|
||
|
if (prop[0] === '-' && prop[1] === '-') return prop;
|
||
|
if (prefix.js + pascalized in style) return prefix.css + prop; // Try webkit fallback.
|
||
|
|
||
|
if (prefix.js !== 'Webkit' && "Webkit" + pascalized in style) return "-webkit-" + prop;
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// https://caniuse.com/#search=scroll-snap
|
||
|
|
||
|
var scrollSnap = {
|
||
|
supportedProperty: function supportedProperty(prop) {
|
||
|
if (prop.substring(0, 11) !== 'scroll-snap') return false;
|
||
|
|
||
|
if (prefix.js === 'ms') {
|
||
|
return "" + prefix.css + prop;
|
||
|
}
|
||
|
|
||
|
return prop;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// https://caniuse.com/#search=overscroll-behavior
|
||
|
|
||
|
var overscrollBehavior = {
|
||
|
supportedProperty: function supportedProperty(prop) {
|
||
|
if (prop !== 'overscroll-behavior') return false;
|
||
|
|
||
|
if (prefix.js === 'ms') {
|
||
|
return prefix.css + "scroll-chaining";
|
||
|
}
|
||
|
|
||
|
return prop;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var propMap = {
|
||
|
'flex-grow': 'flex-positive',
|
||
|
'flex-shrink': 'flex-negative',
|
||
|
'flex-basis': 'flex-preferred-size',
|
||
|
'justify-content': 'flex-pack',
|
||
|
order: 'flex-order',
|
||
|
'align-items': 'flex-align',
|
||
|
'align-content': 'flex-line-pack' // 'align-self' is handled by 'align-self' plugin.
|
||
|
|
||
|
}; // Support old flex spec from 2012.
|
||
|
|
||
|
var flex2012 = {
|
||
|
supportedProperty: function supportedProperty(prop, style) {
|
||
|
var newProp = propMap[prop];
|
||
|
if (!newProp) return false;
|
||
|
return prefix.js + pascalize(newProp) in style ? prefix.css + newProp : false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var propMap$1 = {
|
||
|
flex: 'box-flex',
|
||
|
'flex-grow': 'box-flex',
|
||
|
'flex-direction': ['box-orient', 'box-direction'],
|
||
|
order: 'box-ordinal-group',
|
||
|
'align-items': 'box-align',
|
||
|
'flex-flow': ['box-orient', 'box-direction'],
|
||
|
'justify-content': 'box-pack'
|
||
|
};
|
||
|
var propKeys = Object.keys(propMap$1);
|
||
|
|
||
|
var prefixCss = function prefixCss(p) {
|
||
|
return prefix.css + p;
|
||
|
}; // Support old flex spec from 2009.
|
||
|
|
||
|
|
||
|
var flex2009 = {
|
||
|
supportedProperty: function supportedProperty(prop, style, _ref) {
|
||
|
var multiple = _ref.multiple;
|
||
|
|
||
|
if (propKeys.indexOf(prop) > -1) {
|
||
|
var newProp = propMap$1[prop];
|
||
|
|
||
|
if (!Array.isArray(newProp)) {
|
||
|
return prefix.js + pascalize(newProp) in style ? prefix.css + newProp : false;
|
||
|
}
|
||
|
|
||
|
if (!multiple) return false;
|
||
|
|
||
|
for (var i = 0; i < newProp.length; i++) {
|
||
|
if (!(prefix.js + pascalize(newProp[0]) in style)) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return newProp.map(prefixCss);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// plugins = [
|
||
|
// ...plugins,
|
||
|
// breakPropsOld,
|
||
|
// inlineLogicalOld,
|
||
|
// unprefixed,
|
||
|
// prefixed,
|
||
|
// scrollSnap,
|
||
|
// flex2012,
|
||
|
// flex2009
|
||
|
// ]
|
||
|
// Plugins without 'noPrefill' value, going last.
|
||
|
// 'flex-*' plugins should be at the bottom.
|
||
|
// 'flex2009' going after 'flex2012'.
|
||
|
// 'prefixed' going after 'unprefixed'
|
||
|
|
||
|
var plugins = [appearence, colorAdjust, mask, textOrientation, transform, transition, writingMode, userSelect, breakPropsOld, inlineLogicalOld, unprefixed, prefixed, scrollSnap, overscrollBehavior, flex2012, flex2009];
|
||
|
var propertyDetectors = plugins.filter(function (p) {
|
||
|
return p.supportedProperty;
|
||
|
}).map(function (p) {
|
||
|
return p.supportedProperty;
|
||
|
});
|
||
|
var noPrefill = plugins.filter(function (p) {
|
||
|
return p.noPrefill;
|
||
|
}).reduce(function (a, p) {
|
||
|
a.push.apply(a, _toConsumableArray(p.noPrefill));
|
||
|
return a;
|
||
|
}, []);
|
||
|
|
||
|
var el;
|
||
|
var cache = {};
|
||
|
|
||
|
if (isInBrowser) {
|
||
|
el = document.createElement('p'); // We test every property on vendor prefix requirement.
|
||
|
// Once tested, result is cached. It gives us up to 70% perf boost.
|
||
|
// http://jsperf.com/element-style-object-access-vs-plain-object
|
||
|
//
|
||
|
// Prefill cache with known css properties to reduce amount of
|
||
|
// properties we need to feature test at runtime.
|
||
|
// http://davidwalsh.name/vendor-prefix
|
||
|
|
||
|
var computed = window.getComputedStyle(document.documentElement, '');
|
||
|
|
||
|
for (var key$1 in computed) {
|
||
|
// eslint-disable-next-line no-restricted-globals
|
||
|
if (!isNaN(key$1)) cache[computed[key$1]] = computed[key$1];
|
||
|
} // Properties that cannot be correctly detected using the
|
||
|
// cache prefill method.
|
||
|
|
||
|
|
||
|
noPrefill.forEach(function (x) {
|
||
|
return delete cache[x];
|
||
|
});
|
||
|
}
|
||
|
/**
|
||
|
* Test if a property is supported, returns supported property with vendor
|
||
|
* prefix if required. Returns `false` if not supported.
|
||
|
*
|
||
|
* @param {String} prop dash separated
|
||
|
* @param {Object} [options]
|
||
|
* @return {String|Boolean}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
|
||
|
function supportedProperty(prop, options) {
|
||
|
if (options === void 0) {
|
||
|
options = {};
|
||
|
}
|
||
|
|
||
|
// For server-side rendering.
|
||
|
if (!el) return prop; // Remove cache for benchmark tests or return property from the cache.
|
||
|
|
||
|
if (process.env.NODE_ENV !== 'benchmark' && cache[prop] != null) {
|
||
|
return cache[prop];
|
||
|
} // Check if 'transition' or 'transform' natively supported in browser.
|
||
|
|
||
|
|
||
|
if (prop === 'transition' || prop === 'transform') {
|
||
|
options[prop] = prop in el.style;
|
||
|
} // Find a plugin for current prefix property.
|
||
|
|
||
|
|
||
|
for (var i = 0; i < propertyDetectors.length; i++) {
|
||
|
cache[prop] = propertyDetectors[i](prop, el.style, options); // Break loop, if value found.
|
||
|
|
||
|
if (cache[prop]) break;
|
||
|
} // Reset styles for current property.
|
||
|
// Firefox can even throw an error for invalid properties, e.g., "0".
|
||
|
|
||
|
|
||
|
try {
|
||
|
el.style[prop] = '';
|
||
|
} catch (err) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return cache[prop];
|
||
|
}
|
||
|
|
||
|
var cache$1 = {};
|
||
|
var transitionProperties = {
|
||
|
transition: 1,
|
||
|
'transition-property': 1,
|
||
|
'-webkit-transition': 1,
|
||
|
'-webkit-transition-property': 1
|
||
|
};
|
||
|
var transPropsRegExp = /(^\s*[\w-]+)|, (\s*[\w-]+)(?![^()]*\))/g;
|
||
|
var el$1;
|
||
|
/**
|
||
|
* Returns prefixed value transition/transform if needed.
|
||
|
*
|
||
|
* @param {String} match
|
||
|
* @param {String} p1
|
||
|
* @param {String} p2
|
||
|
* @return {String}
|
||
|
* @api private
|
||
|
*/
|
||
|
|
||
|
function prefixTransitionCallback(match, p1, p2) {
|
||
|
if (p1 === 'var') return 'var';
|
||
|
if (p1 === 'all') return 'all';
|
||
|
if (p2 === 'all') return ', all';
|
||
|
var prefixedValue = p1 ? supportedProperty(p1) : ", " + supportedProperty(p2);
|
||
|
if (!prefixedValue) return p1 || p2;
|
||
|
return prefixedValue;
|
||
|
}
|
||
|
|
||
|
if (isInBrowser) el$1 = document.createElement('p');
|
||
|
/**
|
||
|
* Returns prefixed value if needed. Returns `false` if value is not supported.
|
||
|
*
|
||
|
* @param {String} property
|
||
|
* @param {String} value
|
||
|
* @return {String|Boolean}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
function supportedValue(property, value) {
|
||
|
// For server-side rendering.
|
||
|
var prefixedValue = value;
|
||
|
if (!el$1 || property === 'content') return value; // It is a string or a number as a string like '1'.
|
||
|
// We want only prefixable values here.
|
||
|
// eslint-disable-next-line no-restricted-globals
|
||
|
|
||
|
if (typeof prefixedValue !== 'string' || !isNaN(parseInt(prefixedValue, 10))) {
|
||
|
return prefixedValue;
|
||
|
} // Create cache key for current value.
|
||
|
|
||
|
|
||
|
var cacheKey = property + prefixedValue; // Remove cache for benchmark tests or return value from cache.
|
||
|
|
||
|
if (process.env.NODE_ENV !== 'benchmark' && cache$1[cacheKey] != null) {
|
||
|
return cache$1[cacheKey];
|
||
|
} // IE can even throw an error in some cases, for e.g. style.content = 'bar'.
|
||
|
|
||
|
|
||
|
try {
|
||
|
// Test value as it is.
|
||
|
el$1.style[property] = prefixedValue;
|
||
|
} catch (err) {
|
||
|
// Return false if value not supported.
|
||
|
cache$1[cacheKey] = false;
|
||
|
return false;
|
||
|
} // If 'transition' or 'transition-property' property.
|
||
|
|
||
|
|
||
|
if (transitionProperties[property]) {
|
||
|
prefixedValue = prefixedValue.replace(transPropsRegExp, prefixTransitionCallback);
|
||
|
} else if (el$1.style[property] === '') {
|
||
|
// Value with a vendor prefix.
|
||
|
prefixedValue = prefix.css + prefixedValue; // Hardcode test to convert "flex" to "-ms-flexbox" for IE10.
|
||
|
|
||
|
if (prefixedValue === '-ms-flex') el$1.style[property] = '-ms-flexbox'; // Test prefixed value.
|
||
|
|
||
|
el$1.style[property] = prefixedValue; // Return false if value not supported.
|
||
|
|
||
|
if (el$1.style[property] === '') {
|
||
|
cache$1[cacheKey] = false;
|
||
|
return false;
|
||
|
}
|
||
|
} // Reset styles for current property.
|
||
|
|
||
|
|
||
|
el$1.style[property] = ''; // Write current value to cache.
|
||
|
|
||
|
cache$1[cacheKey] = prefixedValue;
|
||
|
return cache$1[cacheKey];
|
||
|
}
|
||
|
|
||
|
export { prefix, supportedKeyframes, supportedProperty, supportedValue };
|