UNPKG

3.65 kBPlain TextView Raw
1// this cannot be located at source/brower.ts as otherwise it would become the browser entry
2
3// Imports
4import { Transform } from '../transform.js'
5
6/** Mapping of ANSI color codes into a CSS style */
7export interface Styles {
8 [key: string]: {
9 /** The ANSI color code used to start the style */
10 start: string
11 /** The ANSI color code used to end the style */
12 end: string
13 /** The CSS style value */
14 value: string
15 }
16}
17
18/** Configuration optons for the Caterpillar Browser Transform */
19export interface BrowserOptions {
20 /** Use to override the default value of {@link Filter.color} */
21 color?: boolean
22 /** Use to override the default value of {@link Filter.console} */
23 output?: boolean
24 /** Use to override the default value of {@link Filter.styles} */
25 styles?: Styles
26}
27
28/**
29 * Convert human readable Caterpillar entries into browser compatible entries.
30 * @example
31 * ``` javascript
32 * import { Logger, Human, Browser } from 'caterpillar'
33 * const logger = new Logger()
34 * logger.pipe(new Human()).pipe(new Browser())
35 * logger.log('info', 'some', {data: 'oh yeah'}, 42)
36 * ```
37 */
38export class Browser extends Transform {
39 /** Whether or not we should use color. */
40 public color: boolean = true
41
42 /** Whether or not we should write to the browser console. */
43 public output: boolean = true
44
45 /** The objects that tell our browser transform how to convert terminal colours into console colours. */
46 public styles: Styles = {
47 red: {
48 start: '31',
49 end: '39',
50 value: 'color:red',
51 },
52 yellow: {
53 start: '33',
54 end: '39',
55 value: 'color:orange',
56 },
57 green: {
58 start: '32',
59 end: '39',
60 value: 'color:green',
61 },
62 bright: {
63 start: '1',
64 end: '22',
65 value: 'font-weight:bold',
66 },
67 dim: {
68 start: '2',
69 end: '22',
70 value: 'color:lightGray',
71 },
72 italic: {
73 start: '3',
74 end: '23',
75 value: 'font-style:italic',
76 },
77 underline: {
78 start: '4',
79 end: '24',
80 value: 'text-decoration:underline',
81 },
82 }
83
84 /** Create our instance and apply our configuraiton options. */
85 constructor(opts?: BrowserOptions) {
86 super()
87
88 // options
89 if (opts?.color != null) this.color = opts.color
90 if (opts?.output != null) this.output = opts.output
91 if (opts?.styles != null) this.styles = opts.styles
92 }
93
94 /**
95 * Convert a human readable Caterpillar entry into a format that browser consoles can understand.
96 * And if the `write` config property is `true` (it is by default), write the result to the browser console.
97 */
98 format(message: string): string[] {
99 // Prepare
100 const { color, styles, output } = this
101
102 // Replace caterpillar-human formatted entry
103 /* eslint no-control-regex:0 */
104 const args: string[] = []
105 const result = message.replace(
106 /\u001b\[([0-9]+)m(.+?)\u001b\[([0-9]+)m/g,
107 function (match, start, content, end) {
108 // Check
109 if (color === false) return content
110
111 // Prepare
112 let matchedStyle, style
113
114 // Find the matcing style for this combination
115 for (const key in styles) {
116 if (styles.hasOwnProperty(key)) {
117 style = styles[key]
118 if (
119 String(style.start) === String(start) &&
120 String(style.end) === String(end)
121 ) {
122 matchedStyle = style
123 break
124 }
125 }
126 }
127
128 // Check
129 if (!matchedStyle) return content
130
131 // Push the style
132 args.push(matchedStyle.value)
133 args.push(content)
134 args.push('color:default; font:default; text-decoration:default')
135 return '%c%s%c'
136 }
137 )
138
139 // Final format
140 const parts = [result.trim()].concat(args)
141
142 // Write
143 /* eslint no-console:0 */
144 if (output) console.log(...parts)
145
146 // Return
147 return parts
148 }
149}
150
151export default Browser