browser.js
  1  /* eslint-env browser */
  2  
  3  /**
  4   * This is the web browser implementation of `debug()`.
  5   */
  6  
  7  exports.formatArgs = formatArgs;
  8  exports.save = save;
  9  exports.load = load;
 10  exports.useColors = useColors;
 11  exports.storage = localstorage();
 12  exports.destroy = (() => {
 13  	let warned = false;
 14  
 15  	return () => {
 16  		if (!warned) {
 17  			warned = true;
 18  			console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
 19  		}
 20  	};
 21  })();
 22  
 23  /**
 24   * Colors.
 25   */
 26  
 27  exports.colors = [
 28  	'#0000CC',
 29  	'#0000FF',
 30  	'#0033CC',
 31  	'#0033FF',
 32  	'#0066CC',
 33  	'#0066FF',
 34  	'#0099CC',
 35  	'#0099FF',
 36  	'#00CC00',
 37  	'#00CC33',
 38  	'#00CC66',
 39  	'#00CC99',
 40  	'#00CCCC',
 41  	'#00CCFF',
 42  	'#3300CC',
 43  	'#3300FF',
 44  	'#3333CC',
 45  	'#3333FF',
 46  	'#3366CC',
 47  	'#3366FF',
 48  	'#3399CC',
 49  	'#3399FF',
 50  	'#33CC00',
 51  	'#33CC33',
 52  	'#33CC66',
 53  	'#33CC99',
 54  	'#33CCCC',
 55  	'#33CCFF',
 56  	'#6600CC',
 57  	'#6600FF',
 58  	'#6633CC',
 59  	'#6633FF',
 60  	'#66CC00',
 61  	'#66CC33',
 62  	'#9900CC',
 63  	'#9900FF',
 64  	'#9933CC',
 65  	'#9933FF',
 66  	'#99CC00',
 67  	'#99CC33',
 68  	'#CC0000',
 69  	'#CC0033',
 70  	'#CC0066',
 71  	'#CC0099',
 72  	'#CC00CC',
 73  	'#CC00FF',
 74  	'#CC3300',
 75  	'#CC3333',
 76  	'#CC3366',
 77  	'#CC3399',
 78  	'#CC33CC',
 79  	'#CC33FF',
 80  	'#CC6600',
 81  	'#CC6633',
 82  	'#CC9900',
 83  	'#CC9933',
 84  	'#CCCC00',
 85  	'#CCCC33',
 86  	'#FF0000',
 87  	'#FF0033',
 88  	'#FF0066',
 89  	'#FF0099',
 90  	'#FF00CC',
 91  	'#FF00FF',
 92  	'#FF3300',
 93  	'#FF3333',
 94  	'#FF3366',
 95  	'#FF3399',
 96  	'#FF33CC',
 97  	'#FF33FF',
 98  	'#FF6600',
 99  	'#FF6633',
100  	'#FF9900',
101  	'#FF9933',
102  	'#FFCC00',
103  	'#FFCC33'
104  ];
105  
106  /**
107   * Currently only WebKit-based Web Inspectors, Firefox >= v31,
108   * and the Firebug extension (any Firefox version) are known
109   * to support "%c" CSS customizations.
110   *
111   * TODO: add a `localStorage` variable to explicitly enable/disable colors
112   */
113  
114  // eslint-disable-next-line complexity
115  function useColors() {
116  	// NB: In an Electron preload script, document will be defined but not fully
117  	// initialized. Since we know we're in Chrome, we'll just detect this case
118  	// explicitly
119  	if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
120  		return true;
121  	}
122  
123  	// Internet Explorer and Edge do not support colors.
124  	if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
125  		return false;
126  	}
127  
128  	// Is webkit? http://stackoverflow.com/a/16459606/376773
129  	// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
130  	return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
131  		// Is firebug? http://stackoverflow.com/a/398120/376773
132  		(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
133  		// Is firefox >= v31?
134  		// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
135  		(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
136  		// Double check webkit in userAgent just in case we are in a worker
137  		(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
138  }
139  
140  /**
141   * Colorize log arguments if enabled.
142   *
143   * @api public
144   */
145  
146  function formatArgs(args) {
147  	args[0] = (this.useColors ? '%c' : '') +
148  		this.namespace +
149  		(this.useColors ? ' %c' : ' ') +
150  		args[0] +
151  		(this.useColors ? '%c ' : ' ') +
152  		'+' + module.exports.humanize(this.diff);
153  
154  	if (!this.useColors) {
155  		return;
156  	}
157  
158  	const c = 'color: ' + this.color;
159  	args.splice(1, 0, c, 'color: inherit');
160  
161  	// The final "%c" is somewhat tricky, because there could be other
162  	// arguments passed either before or after the %c, so we need to
163  	// figure out the correct index to insert the CSS into
164  	let index = 0;
165  	let lastC = 0;
166  	args[0].replace(/%[a-zA-Z%]/g, match => {
167  		if (match === '%%') {
168  			return;
169  		}
170  		index++;
171  		if (match === '%c') {
172  			// We only are interested in the *last* %c
173  			// (the user may have provided their own)
174  			lastC = index;
175  		}
176  	});
177  
178  	args.splice(lastC, 0, c);
179  }
180  
181  /**
182   * Invokes `console.debug()` when available.
183   * No-op when `console.debug` is not a "function".
184   * If `console.debug` is not available, falls back
185   * to `console.log`.
186   *
187   * @api public
188   */
189  exports.log = console.debug || console.log || (() => {});
190  
191  /**
192   * Save `namespaces`.
193   *
194   * @param {String} namespaces
195   * @api private
196   */
197  function save(namespaces) {
198  	try {
199  		if (namespaces) {
200  			exports.storage.setItem('debug', namespaces);
201  		} else {
202  			exports.storage.removeItem('debug');
203  		}
204  	} catch (error) {
205  		// Swallow
206  		// XXX (@Qix-) should we be logging these?
207  	}
208  }
209  
210  /**
211   * Load `namespaces`.
212   *
213   * @return {String} returns the previously persisted debug modes
214   * @api private
215   */
216  function load() {
217  	let r;
218  	try {
219  		r = exports.storage.getItem('debug');
220  	} catch (error) {
221  		// Swallow
222  		// XXX (@Qix-) should we be logging these?
223  	}
224  
225  	// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
226  	if (!r && typeof process !== 'undefined' && 'env' in process) {
227  		r = process.env.DEBUG;
228  	}
229  
230  	return r;
231  }
232  
233  /**
234   * Localstorage attempts to return the localstorage.
235   *
236   * This is necessary because safari throws
237   * when a user disables cookies/localstorage
238   * and you attempt to access it.
239   *
240   * @return {LocalStorage}
241   * @api private
242   */
243  
244  function localstorage() {
245  	try {
246  		// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
247  		// The Browser also has localStorage in the global context.
248  		return localStorage;
249  	} catch (error) {
250  		// Swallow
251  		// XXX (@Qix-) should we be logging these?
252  	}
253  }
254  
255  module.exports = require('./common')(exports);
256  
257  const {formatters} = module.exports;
258  
259  /**
260   * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
261   */
262  
263  formatters.j = function (v) {
264  	try {
265  		return JSON.stringify(v);
266  	} catch (error) {
267  		return '[UnexpectedJSONParseError]: ' + error.message;
268  	}
269  };