import { createDebug as _createDebug, enable as _enable, disable, enabled, namespaces, } from './core.ts' import { humanize, selectColor } from './utils.ts' import type { Debugger, DebugOptions } from './types.ts' const colors: string[] = [ '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33', ] /** * Colorize log arguments if enabled. */ function formatArgs( this: Debugger, diff: number, args: [string, ...any[]], ): void { const { useColors } = this args[0] = `${ (useColors ? '%c' : '') + this.namespace + (useColors ? ' %c' : ' ') + args[0] + (useColors ? '%c ' : ' ') }+${this.humanize(diff)}` if (!useColors) { return } const 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 let index = 0 let lastC = 0 args[0].replace(/%[a-z%]/gi, (match: any): any => { if (match === '%%') { return } index++ if (match === '%c') { // We only are interested in the *last* %c // (the user may have provided their own) lastC = index } }) args.splice(lastC, 0, c) } /** * Invokes `console.debug()` when available. * No-op when `console.debug` is not a "function". * If `console.debug` is not available, falls back * to `console.log`. */ const log = console.debug || console.log || (() => {}) const defaultOptions: Omit, 'color'> = { useColors: true, formatArgs, formatters: { /** * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. */ j(v) { try { return JSON.stringify(v) } catch (error: any) { return `[UnexpectedJSONParseError]: ${error.message}` } }, }, inspectOpts: {}, humanize, log, } export function createDebug( namespace: string, options?: DebugOptions, ): Debugger { const color = (options && options.color) ?? selectColor(colors, namespace) return _createDebug( namespace, Object.assign(defaultOptions, { color }, options), ) } function load(): string { let r: string | null | undefined try { // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context. r = localStorage.getItem('debug') || localStorage.getItem('DEBUG') } catch { // Swallow // XXX (@Qix-) should we be logging these? } // 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 } return r || '' } function save(namespaces: string) { try { if (namespaces) { localStorage.setItem('debug', namespaces) } else { localStorage.removeItem('debug') } } catch { // Swallow // XXX (@Qix-) should we be logging these? } } /** * Enables a debug mode by namespaces. This can include modes * separated by a colon and wildcards. */ function enable(namespaces: string): void { save(namespaces) _enable(namespaces) } // eslint-disable-next-line unicorn/no-top-level-side-effects _enable(load()) export type * from './types.ts' export { disable, enable, enabled, namespaces }