@vime/core
Version:
Customizable, extensible, accessible and framework agnostic media player.
219 lines (215 loc) • 7.29 kB
JavaScript
const support = require('./support-e1714cb5.js');
const withComponentRegistry = require('./withComponentRegistry-90ec334c.js');
/**
* Attempt to parse json into a POJO.
*/
function tryParseJSON(json) {
if (!withComponentRegistry.isString(json))
return undefined;
try {
return JSON.parse(json);
}
catch (e) {
return undefined;
}
}
/**
* Check if the given input is json or a plain object.
*/
const isObjOrJSON = (input) => !withComponentRegistry.isNil(input) &&
(withComponentRegistry.isObject(input) || (withComponentRegistry.isString(input) && input.startsWith('{')));
/**
* If an object return otherwise try to parse it as json.
*/
const objOrParseJSON = (input) => withComponentRegistry.isObject(input) ? input : tryParseJSON(input);
/**
* Load image avoiding xhr/fetch CORS issues. Server status can't be obtained this way
* unfortunately, so this uses "naturalWidth" to determine if the image has been loaded. By
* default it checks if it is at least 1px.
*/
const loadImage = (src, minWidth = 1) => new Promise((resolve, reject) => {
const image = new Image();
const handler = () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
delete image.onload;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
delete image.onerror;
image.naturalWidth >= minWidth ? resolve(image) : reject(image);
};
Object.assign(image, { onload: handler, onerror: handler, src });
});
const loadScript = (src, onLoad, onError = withComponentRegistry.noop) => {
var _a;
const script = document.createElement('script');
script.src = src;
script.onload = onLoad;
script.onerror = onError;
const firstScriptTag = document.getElementsByTagName('script')[0];
(_a = firstScriptTag.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(script, firstScriptTag);
};
/**
* Tries to parse json and return a object.
*/
const decodeJSON = (data) => {
if (!isObjOrJSON(data))
return undefined;
return objOrParseJSON(data);
};
/**
* Attempts to safely decode a URI component, on failure it returns the given fallback.
*/
const tryDecodeURIComponent = (component, fallback = '') => {
if (!support.IS_CLIENT)
return fallback;
try {
return window.decodeURIComponent(component);
}
catch (e) {
return fallback;
}
};
/**
* Returns a simple key/value map and duplicate keys are merged into an array.
*
* @see https://github.com/ampproject/amphtml/blob/c7c46cec71bac92f5c5da31dcc6366c18577f566/src/url-parse-query-string.js#L31
*/
const QUERY_STRING_REGEX = /(?:^[#?]?|&)([^=&]+)(?:=([^&]*))?/g;
const parseQueryString = (qs) => {
const params = Object.create(null);
if (withComponentRegistry.isUndefined(qs))
return params;
let match;
// eslint-disable-next-line no-cond-assign
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
while ((match = QUERY_STRING_REGEX.exec(qs))) {
const name = tryDecodeURIComponent(match[1], match[1]).replace('[]', '');
const value = withComponentRegistry.isString(match[2])
? tryDecodeURIComponent(match[2].replace(/\+/g, ' '), match[2])
: '';
const currValue = params[name];
if (currValue && !withComponentRegistry.isArray(currValue))
params[name] = [currValue];
currValue ? params[name].push(value) : (params[name] = value);
}
return params;
};
/**
* Serializes the given params into a query string.
*/
const serializeQueryString = (params) => {
const qs = [];
const appendQueryParam = (param, v) => {
qs.push(`${encodeURIComponent(param)}=${encodeURIComponent(v)}`);
};
Object.keys(params).forEach(param => {
const value = params[param];
if (withComponentRegistry.isNil(value))
return;
if (withComponentRegistry.isArray(value)) {
value.forEach((v) => appendQueryParam(param, v));
}
else {
appendQueryParam(param, value);
}
});
return qs.join('&');
};
/**
* Notifies the browser to start establishing a connection with the given URL.
*/
const preconnect = (url, rel = 'preconnect', as) => {
if (!support.IS_CLIENT)
return false;
const link = document.createElement('link');
link.rel = rel;
link.href = url;
if (!withComponentRegistry.isUndefined(as))
link.as = as;
link.crossOrigin = 'true';
document.head.append(link);
return true;
};
/**
* Safely appends the given query string to the given URL.
*/
const appendQueryStringToURL = (url, qs) => {
if (withComponentRegistry.isUndefined(qs) || qs.length === 0)
return url;
const mainAndQuery = url.split('?', 2);
return (mainAndQuery[0] +
(!withComponentRegistry.isUndefined(mainAndQuery[1]) ? `?${mainAndQuery[1]}&${qs}` : `?${qs}`));
};
/**
* Serializes the given params into a query string and appends them to the given URL.
*/
const appendParamsToURL = (url, params) => appendQueryStringToURL(url, withComponentRegistry.isObject(params)
? serializeQueryString(params)
: params);
/**
* Tries to convert a query string into a object.
*/
const decodeQueryString = (qs) => {
if (!withComponentRegistry.isString(qs))
return undefined;
return parseQueryString(qs);
};
const pendingSDKRequests = {};
/**
* Loads an SDK into the global window namespace.
*
* @see https://github.com/CookPete/react-player/blob/master/src/utils.js#L77
*/
const loadSDK = (url, sdkGlobalVar, sdkReadyVar, isLoaded = () => true, loadScriptFn = loadScript) => {
const getGlobal = (key) => {
if (!withComponentRegistry.isUndefined(window[key]))
return window[key];
if (window.exports && window.exports[key])
return window.exports[key];
if (window.module && window.module.exports && window.module.exports[key]) {
return window.module.exports[key];
}
return undefined;
};
const existingGlobal = getGlobal(sdkGlobalVar);
if (existingGlobal && isLoaded(existingGlobal)) {
return Promise.resolve(existingGlobal);
}
return new Promise((resolve, reject) => {
if (!withComponentRegistry.isUndefined(pendingSDKRequests[url])) {
pendingSDKRequests[url].push({ resolve, reject });
return;
}
pendingSDKRequests[url] = [{ resolve, reject }];
const onLoaded = (sdk) => {
pendingSDKRequests[url].forEach(request => request.resolve(sdk));
};
if (!withComponentRegistry.isUndefined(sdkReadyVar)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const previousOnReady = window[sdkReadyVar];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
window[sdkReadyVar] = function () {
if (!withComponentRegistry.isUndefined(previousOnReady))
previousOnReady();
onLoaded(getGlobal(sdkGlobalVar));
};
}
loadScriptFn(url, () => {
if (withComponentRegistry.isUndefined(sdkReadyVar))
onLoaded(getGlobal(sdkGlobalVar));
}, e => {
pendingSDKRequests[url].forEach(request => {
request.reject(e);
});
delete pendingSDKRequests[url];
});
});
};
exports.appendParamsToURL = appendParamsToURL;
exports.decodeJSON = decodeJSON;
exports.decodeQueryString = decodeQueryString;
exports.loadImage = loadImage;
exports.loadSDK = loadSDK;
exports.preconnect = preconnect;
;