browser.js 5.9 KB

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