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