browser.js 4.62 KB
Newer Older
Rosanny Sihombing's avatar
Rosanny Sihombing committed
1
2
/**
 * This is the web browser implementation of `debug()`.
3
4
 *
 * Expose `debug()` as the module.
Rosanny Sihombing's avatar
Rosanny Sihombing committed
5
6
 */

7
8
exports = module.exports = require('./debug');
exports.log = log;
Rosanny Sihombing's avatar
Rosanny Sihombing committed
9
10
11
12
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
13
14
15
16
exports.storage = 'undefined' != typeof chrome
               && 'undefined' != typeof chrome.storage
                  ? chrome.storage.local
                  : localstorage();
Rosanny Sihombing's avatar
Rosanny Sihombing committed
17
18
19
20
21
22

/**
 * Colors.
 */

exports.colors = [
23
24
25
26
27
28
  'lightseagreen',
  'forestgreen',
  'goldenrod',
  'dodgerblue',
  'darkorchid',
  'crimson'
Rosanny Sihombing's avatar
Rosanny Sihombing committed
29
30
31
32
33
34
35
36
37
38
39
];

/**
 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
 * and the Firebug extension (any Firefox version) are known
 * to support "%c" CSS customizations.
 *
 * TODO: add a `localStorage` variable to explicitly enable/disable colors
 */

function useColors() {
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  // NB: In an Electron preload script, document will be defined but not fully
  // initialized. Since we know we're in Chrome, we'll just detect this case
  // explicitly
  if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
    return true;
  }

  // is webkit? http://stackoverflow.com/a/16459606/376773
  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
  return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
    // is firebug? http://stackoverflow.com/a/398120/376773
    (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
    // is firefox >= v31?
    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
    // double check webkit in userAgent just in case we are in a worker
    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
}
Rosanny Sihombing's avatar
Rosanny Sihombing committed
58

59
60
61
62
63
64
65
66
67
68
69
/**
 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
 */

exports.formatters.j = function(v) {
  try {
    return JSON.stringify(v);
  } catch (err) {
    return '[UnexpectedJSONParseError]: ' + err.message;
  }
};
Rosanny Sihombing's avatar
Rosanny Sihombing committed
70
71
72
73
74
75
76
77
78


/**
 * Colorize log arguments if enabled.
 *
 * @api public
 */

function formatArgs(args) {
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  var useColors = this.useColors;

  args[0] = (useColors ? '%c' : '')
    + this.namespace
    + (useColors ? ' %c' : ' ')
    + args[0]
    + (useColors ? '%c ' : ' ')
    + '+' + exports.humanize(this.diff);

  if (!useColors) return;

  var c = 'color: ' + this.color;
  args.splice(1, 0, c, 'color: inherit')

  // 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 ('%c' === match) {
      // we only are interested in the *last* %c
      // (the user may have provided their own)
      lastC = index;
    }
  });

  args.splice(lastC, 0, c);
Rosanny Sihombing's avatar
Rosanny Sihombing committed
109
110
111
}

/**
112
113
 * Invokes `console.log()` when available.
 * No-op when `console.log` is not a "function".
Rosanny Sihombing's avatar
Rosanny Sihombing committed
114
115
116
 *
 * @api public
 */
117
118
119
120
121
122
123
124

function log() {
  // this hackery is required for IE8/9, where
  // the `console.log` function doesn't have 'apply'
  return 'object' === typeof console
    && console.log
    && Function.prototype.apply.call(console.log, console, arguments);
}
Rosanny Sihombing's avatar
Rosanny Sihombing committed
125
126
127
128
129
130
131

/**
 * Save `namespaces`.
 *
 * @param {String} namespaces
 * @api private
 */
132

Rosanny Sihombing's avatar
Rosanny Sihombing committed
133
function save(namespaces) {
134
135
136
137
138
139
140
  try {
    if (null == namespaces) {
      exports.storage.removeItem('debug');
    } else {
      exports.storage.debug = namespaces;
    }
  } catch(e) {}
Rosanny Sihombing's avatar
Rosanny Sihombing committed
141
142
143
144
145
146
147
148
}

/**
 * Load `namespaces`.
 *
 * @return {String} returns the previously persisted debug modes
 * @api private
 */
149

Rosanny Sihombing's avatar
Rosanny Sihombing committed
150
function load() {
151
152
153
154
  var r;
  try {
    r = exports.storage.debug;
  } catch(e) {}
Rosanny Sihombing's avatar
Rosanny Sihombing committed
155

156
157
158
159
  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
  if (!r && typeof process !== 'undefined' && 'env' in process) {
    r = process.env.DEBUG;
  }
Rosanny Sihombing's avatar
Rosanny Sihombing committed
160

161
  return r;
Rosanny Sihombing's avatar
Rosanny Sihombing committed
162
163
}

164
165
166
167
168
169
/**
 * Enable namespaces listed in `localStorage.debug` initially.
 */

exports.enable(load());

Rosanny Sihombing's avatar
Rosanny Sihombing committed
170
171
172
173
174
175
176
177
178
179
180
181
/**
 * Localstorage attempts to return the localstorage.
 *
 * This is necessary because safari throws
 * when a user disables cookies/localstorage
 * and you attempt to access it.
 *
 * @return {LocalStorage}
 * @api private
 */

function localstorage() {
182
183
184
  try {
    return window.localStorage;
  } catch (e) {}
Rosanny Sihombing's avatar
Rosanny Sihombing committed
185
}