informed
Version:
A lightweight framework and utility for building powerful forms in React applications
192 lines (177 loc) • 6.34 kB
JavaScript
/* eslint-disable no-undef */
/**
*
* I stole most of this code from the debug lib
* https://github.com/visionmedia/debug
*
* Just wanted it to be easy to debug without relying on the dependency!
*/
/**
* Selects a color for a debug namespace
* @param {String} namespace The namespace string for the for the debug instance to be colored
* @param {String} colors color pallette to choose from
* @return {Number|String} An ANSI color code for the given namespace
* @api private
*/
function selectColor(namespace, colors) {
var hash = 0;
for (var i = 0; i < namespace.length; i++) {
hash = (hash << 5) - hash + namespace.charCodeAt(i);
hash |= 0; // Convert to 32bit integer
}
return colors[Math.abs(hash) % colors.length];
}
/**
* Adds ANSI color escape codes if enabled.
*
* @api public
*/
function formatNodeArgs(args, config) {
var name = config.namespace;
if (config.useColors) {
var c = config.color;
var colorCode = "\x1B[3" + (c < 8 ? c : '8;5;' + c);
var prefix = " ".concat(colorCode, ";1m").concat(name, " \x1B[0m");
args[0] = prefix + args[0].split('\n').join('\n' + prefix);
} else {
args[0] = name + ' ' + args[0];
}
}
/**
* Colorize log arguments if enabled.
*
*/
function formatBrowserArgs(args, config) {
args[0] = (config.useColors ? '%c' : '') + config.namespace;
if (!config.useColors) {
return;
}
var c = 'color: ' + config.color;
// The final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
// figure out the correct index to insert the CSS into
var index = 0;
var lastC = 0;
args[0].replace(/%[a-zA-Z%]/g, function (match) {
if (match === '%%') {
return;
}
index++;
if (match === '%c') {
// We only are interested in the *last* %c
// (the user may have provided their own)
lastC = index;
}
});
args.splice(lastC, 0, c);
}
var browserColors = ['#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33'];
/**
* Load `namespaces`.
*
* @return {String} returns the debug modes
* @api private
*/
function loadBrowser() {
var namespaces;
try {
namespaces = localStorage.getItem('debug');
} catch (error) {
// Swallow
// XXX (@Qix-) should we be logging these?
}
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
// eslint-disable-next-line no-undef
if (!namespaces && typeof process !== 'undefined' && 'env' in process) {
// eslint-disable-next-line no-undef
namespaces = process.env.DEBUG;
}
return {
namespaces: namespaces || '',
colors: browserColors,
useColors: true,
formatArgs: formatBrowserArgs
};
}
/**
* Load `namespaces`.
*
* @return {String} returns the debug modes
* @api private
*/
function loadNode() {
return {
namespaces: process.env.DEBUG || '',
colors: [6, 2, 3, 4, 5, 1],
useColors: true,
formatArgs: formatNodeArgs
};
}
function createLogger() {
var prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var config = arguments.length > 1 ? arguments[1] : undefined;
return function () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
if (prefix) {
args.unshift(prefix);
}
// Create a namespace regex for each namespace
var matches = config.namespaces.split(',').map(function (namespace) {
// Remove wildcard and add to regex if wildcard
if (namespace[namespace.length - 1] === '*') {
return new RegExp('^' + namespace.slice(0, namespace.length - 1) + '.*' + '$');
}
return new RegExp('^' + namespace + '$');
});
// Does the prefix match a namespace
var match = matches.some(function (regex) {
return regex.test(prefix);
});
var conf = {
color: selectColor(prefix, config.colors),
namespace: prefix,
useColors: config.useColors
};
if (process.env.NODE_ENV !== 'production' && match) {
var _console;
config.formatArgs(args, conf);
(_console = console).log.apply(_console, args);
}
};
}
function nodeLogger(prefix) {
return createLogger(prefix, loadNode());
}
function browserLogger(prefix) {
return createLogger(prefix, loadBrowser());
}
var Debug = function Debug(prefix) {
/**
* Detect Electron renderer / nwjs process, which is node, but we should
* treat as a browser.
*/
if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
return browserLogger(prefix);
} else if (typeof window !== 'undefined' && typeof window.navigator !== 'undefined' && window.navigator.product === 'ReactNative' && typeof global !== 'undefined' && __DEV__ === true) {
console.log('informed:debug: Detected React Native Environment');
// https://github.com/debug-js/debug/issues/640#issuecomment-441263230
// Shim process and window.localStorage to enable logging via react native debugger
process.type = 'renderer';
// only override localStorage if missing
if (!window.localStorage || !window.localStorage.getItem) {
window.localStorage = {
debug: global.DEBUG_INFORMED || '',
getItem: function getItem() {
// we only expect 1 key in logger, always return that
return global.DEBUG_INFORMED || '';
}
};
}
return browserLogger(prefix);
} else {
return nodeLogger(prefix);
}
};
export { Debug };