browser.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /**
  2. * This is the web browser implementation of `debug()`.
  3. *
  4. * Expose `debug()` as the module.
  5. */
  6. exports = module.exports = require('./debug');
  7. exports.log = log;
  8. exports.formatArgs = formatArgs;
  9. exports.save = save;
  10. exports.load = load;
  11. exports.useColors = useColors;
  12. exports.storage = 'undefined' != typeof chrome
  13. && 'undefined' != typeof chrome.storage
  14. ? chrome.storage.local
  15. : localstorage();
  16. /**
  17. * Colors.
  18. */
  19. exports.colors = [
  20. 'lightseagreen',
  21. 'forestgreen',
  22. 'goldenrod',
  23. 'dodgerblue',
  24. 'darkorchid',
  25. 'crimson'
  26. ];
  27. /**
  28. * Currently only WebKit-based Web Inspectors, Firefox >= v31,
  29. * and the Firebug extension (any Firefox version) are known
  30. * to support "%c" CSS customizations.
  31. *
  32. * TODO: add a `localStorage` variable to explicitly enable/disable colors
  33. */
  34. function useColors() {
  35. // NB: In an Electron preload script, document will be defined but not fully
  36. // initialized. Since we know we're in Chrome, we'll just detect this case
  37. // explicitly
  38. if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
  39. return true;
  40. }
  41. // is webkit? http://stackoverflow.com/a/16459606/376773
  42. // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
  43. return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
  44. // is firebug? http://stackoverflow.com/a/398120/376773
  45. (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
  46. // is firefox >= v31?
  47. // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
  48. (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
  49. // double check webkit in userAgent just in case we are in a worker
  50. (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
  51. }
  52. /**
  53. * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
  54. */
  55. exports.formatters.j = function(v) {
  56. try {
  57. return JSON.stringify(v);
  58. } catch (err) {
  59. return '[UnexpectedJSONParseError]: ' + err.message;
  60. }
  61. };
  62. /**
  63. * Colorize log arguments if enabled.
  64. *
  65. * @api public
  66. */
  67. function formatArgs(args) {
  68. var useColors = this.useColors;
  69. args[0] = (useColors ? '%c' : '')
  70. + this.namespace
  71. + (useColors ? ' %c' : ' ')
  72. + args[0]
  73. + (useColors ? '%c ' : ' ')
  74. + '+' + exports.humanize(this.diff);
  75. if (!useColors) return;
  76. var c = 'color: ' + this.color;
  77. args.splice(1, 0, c, 'color: inherit')
  78. // the final "%c" is somewhat tricky, because there could be other
  79. // arguments passed either before or after the %c, so we need to
  80. // figure out the correct index to insert the CSS into
  81. var index = 0;
  82. var lastC = 0;
  83. args[0].replace(/%[a-zA-Z%]/g, function(match) {
  84. if ('%%' === match) return;
  85. index++;
  86. if ('%c' === match) {
  87. // we only are interested in the *last* %c
  88. // (the user may have provided their own)
  89. lastC = index;
  90. }
  91. });
  92. args.splice(lastC, 0, c);
  93. }
  94. /**
  95. * Invokes `console.log()` when available.
  96. * No-op when `console.log` is not a "function".
  97. *
  98. * @api public
  99. */
  100. function log() {
  101. // this hackery is required for IE8/9, where
  102. // the `console.log` function doesn't have 'apply'
  103. return 'object' === typeof console
  104. && console.log
  105. && Function.prototype.apply.call(console.log, console, arguments);
  106. }
  107. /**
  108. * Save `namespaces`.
  109. *
  110. * @param {String} namespaces
  111. * @api private
  112. */
  113. function save(namespaces) {
  114. try {
  115. if (null == namespaces) {
  116. exports.storage.removeItem('debug');
  117. } else {
  118. exports.storage.debug = namespaces;
  119. }
  120. } catch(e) {}
  121. }
  122. /**
  123. * Load `namespaces`.
  124. *
  125. * @return {String} returns the previously persisted debug modes
  126. * @api private
  127. */
  128. function load() {
  129. var r;
  130. try {
  131. r = exports.storage.debug;
  132. } catch(e) {}
  133. // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
  134. if (!r && typeof process !== 'undefined' && 'env' in process) {
  135. r = process.env.DEBUG;
  136. }
  137. return r;
  138. }
  139. /**
  140. * Enable namespaces listed in `localStorage.debug` initially.
  141. */
  142. exports.enable(load());
  143. /**
  144. * Localstorage attempts to return the localstorage.
  145. *
  146. * This is necessary because safari throws
  147. * when a user disables cookies/localstorage
  148. * and you attempt to access it.
  149. *
  150. * @return {LocalStorage}
  151. * @api private
  152. */
  153. function localstorage() {
  154. try {
  155. return window.localStorage;
  156. } catch (e) {}
  157. }