You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
8.3 KiB

4 years ago
  1. /*! loglevel - v1.6.6 - https://github.com/pimterry/loglevel - (c) 2019 Tim Perry - licensed MIT */
  2. (function (root, definition) {
  3. "use strict";
  4. if (typeof define === 'function' && define.amd) {
  5. define(definition);
  6. } else if (typeof module === 'object' && module.exports) {
  7. module.exports = definition();
  8. } else {
  9. root.log = definition();
  10. }
  11. }(this, function () {
  12. "use strict";
  13. // Slightly dubious tricks to cut down minimized file size
  14. var noop = function() {};
  15. var undefinedType = "undefined";
  16. var isIE = (typeof window !== undefinedType) && (
  17. /Trident\/|MSIE /.test(window.navigator.userAgent)
  18. );
  19. var logMethods = [
  20. "trace",
  21. "debug",
  22. "info",
  23. "warn",
  24. "error"
  25. ];
  26. // Cross-browser bind equivalent that works at least back to IE6
  27. function bindMethod(obj, methodName) {
  28. var method = obj[methodName];
  29. if (typeof method.bind === 'function') {
  30. return method.bind(obj);
  31. } else {
  32. try {
  33. return Function.prototype.bind.call(method, obj);
  34. } catch (e) {
  35. // Missing bind shim or IE8 + Modernizr, fallback to wrapping
  36. return function() {
  37. return Function.prototype.apply.apply(method, [obj, arguments]);
  38. };
  39. }
  40. }
  41. }
  42. // Trace() doesn't print the message in IE, so for that case we need to wrap it
  43. function traceForIE() {
  44. if (console.log) {
  45. if (console.log.apply) {
  46. console.log.apply(console, arguments);
  47. } else {
  48. // In old IE, native console methods themselves don't have apply().
  49. Function.prototype.apply.apply(console.log, [console, arguments]);
  50. }
  51. }
  52. if (console.trace) console.trace();
  53. }
  54. // Build the best logging method possible for this env
  55. // Wherever possible we want to bind, not wrap, to preserve stack traces
  56. function realMethod(methodName) {
  57. if (methodName === 'debug') {
  58. methodName = 'log';
  59. }
  60. if (typeof console === undefinedType) {
  61. return false; // No method possible, for now - fixed later by enableLoggingWhenConsoleArrives
  62. } else if (methodName === 'trace' && isIE) {
  63. return traceForIE;
  64. } else if (console[methodName] !== undefined) {
  65. return bindMethod(console, methodName);
  66. } else if (console.log !== undefined) {
  67. return bindMethod(console, 'log');
  68. } else {
  69. return noop;
  70. }
  71. }
  72. // These private functions always need `this` to be set properly
  73. function replaceLoggingMethods(level, loggerName) {
  74. /*jshint validthis:true */
  75. for (var i = 0; i < logMethods.length; i++) {
  76. var methodName = logMethods[i];
  77. this[methodName] = (i < level) ?
  78. noop :
  79. this.methodFactory(methodName, level, loggerName);
  80. }
  81. // Define log.log as an alias for log.debug
  82. this.log = this.debug;
  83. }
  84. // In old IE versions, the console isn't present until you first open it.
  85. // We build realMethod() replacements here that regenerate logging methods
  86. function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {
  87. return function () {
  88. if (typeof console !== undefinedType) {
  89. replaceLoggingMethods.call(this, level, loggerName);
  90. this[methodName].apply(this, arguments);
  91. }
  92. };
  93. }
  94. // By default, we use closely bound real methods wherever possible, and
  95. // otherwise we wait for a console to appear, and then try again.
  96. function defaultMethodFactory(methodName, level, loggerName) {
  97. /*jshint validthis:true */
  98. return realMethod(methodName) ||
  99. enableLoggingWhenConsoleArrives.apply(this, arguments);
  100. }
  101. function Logger(name, defaultLevel, factory) {
  102. var self = this;
  103. var currentLevel;
  104. var storageKey = "loglevel";
  105. if (name) {
  106. storageKey += ":" + name;
  107. }
  108. function persistLevelIfPossible(levelNum) {
  109. var levelName = (logMethods[levelNum] || 'silent').toUpperCase();
  110. if (typeof window === undefinedType) return;
  111. // Use localStorage if available
  112. try {
  113. window.localStorage[storageKey] = levelName;
  114. return;
  115. } catch (ignore) {}
  116. // Use session cookie as fallback
  117. try {
  118. window.document.cookie =
  119. encodeURIComponent(storageKey) + "=" + levelName + ";";
  120. } catch (ignore) {}
  121. }
  122. function getPersistedLevel() {
  123. var storedLevel;
  124. if (typeof window === undefinedType) return;
  125. try {
  126. storedLevel = window.localStorage[storageKey];
  127. } catch (ignore) {}
  128. // Fallback to cookies if local storage gives us nothing
  129. if (typeof storedLevel === undefinedType) {
  130. try {
  131. var cookie = window.document.cookie;
  132. var location = cookie.indexOf(
  133. encodeURIComponent(storageKey) + "=");
  134. if (location !== -1) {
  135. storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];
  136. }
  137. } catch (ignore) {}
  138. }
  139. // If the stored level is not valid, treat it as if nothing was stored.
  140. if (self.levels[storedLevel] === undefined) {
  141. storedLevel = undefined;
  142. }
  143. return storedLevel;
  144. }
  145. /*
  146. *
  147. * Public logger API - see https://github.com/pimterry/loglevel for details
  148. *
  149. */
  150. self.name = name;
  151. self.levels = { "TRACE": 0, "DEBUG": 1, "INFO": 2, "WARN": 3,
  152. "ERROR": 4, "SILENT": 5};
  153. self.methodFactory = factory || defaultMethodFactory;
  154. self.getLevel = function () {
  155. return currentLevel;
  156. };
  157. self.setLevel = function (level, persist) {
  158. if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
  159. level = self.levels[level.toUpperCase()];
  160. }
  161. if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
  162. currentLevel = level;
  163. if (persist !== false) { // defaults to true
  164. persistLevelIfPossible(level);
  165. }
  166. replaceLoggingMethods.call(self, level, name);
  167. if (typeof console === undefinedType && level < self.levels.SILENT) {
  168. return "No console available for logging";
  169. }
  170. } else {
  171. throw "log.setLevel() called with invalid level: " + level;
  172. }
  173. };
  174. self.setDefaultLevel = function (level) {
  175. if (!getPersistedLevel()) {
  176. self.setLevel(level, false);
  177. }
  178. };
  179. self.enableAll = function(persist) {
  180. self.setLevel(self.levels.TRACE, persist);
  181. };
  182. self.disableAll = function(persist) {
  183. self.setLevel(self.levels.SILENT, persist);
  184. };
  185. // Initialize with the right level
  186. var initialLevel = getPersistedLevel();
  187. if (initialLevel == null) {
  188. initialLevel = defaultLevel == null ? "WARN" : defaultLevel;
  189. }
  190. self.setLevel(initialLevel, false);
  191. }
  192. /*
  193. *
  194. * Top-level API
  195. *
  196. */
  197. var defaultLogger = new Logger();
  198. var _loggersByName = {};
  199. defaultLogger.getLogger = function getLogger(name) {
  200. if (typeof name !== "string" || name === "") {
  201. throw new TypeError("You must supply a name when creating a logger.");
  202. }
  203. var logger = _loggersByName[name];
  204. if (!logger) {
  205. logger = _loggersByName[name] = new Logger(
  206. name, defaultLogger.getLevel(), defaultLogger.methodFactory);
  207. }
  208. return logger;
  209. };
  210. // Grab the current global log variable in case of overwrite
  211. var _log = (typeof window !== undefinedType) ? window.log : undefined;
  212. defaultLogger.noConflict = function() {
  213. if (typeof window !== undefinedType &&
  214. window.log === defaultLogger) {
  215. window.log = _log;
  216. }
  217. return defaultLogger;
  218. };
  219. defaultLogger.getLoggers = function getLoggers() {
  220. return _loggersByName;
  221. };
  222. return defaultLogger;
  223. }));