main
js 68 lines 2.34 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @flow
8 */
9
10 // Do not add / import anything to this file.
11 // This function could be used from multiple places, including hook.
12
13 // Formats an array of args with a style for console methods, using
14 // the following algorithm:
15 // 1. The first param is a string that contains %c
16 // - Bail out and return the args without modifying the styles.
17 // We don't want to affect styles that the developer deliberately set.
18 // 2. The first param is a string that doesn't contain %c but contains
19 // string formatting
20 // - [`%c${args[0]}`, style, ...args.slice(1)]
21 // - Note: we assume that the string formatting that the developer uses
22 // is correct.
23 // 3. The first param is a string that doesn't contain string formatting
24 // OR is not a string
25 // - Create a formatting string where:
26 // boolean, string, symbol -> %s
27 // number -> %f OR %i depending on if it's an int or float
28 // default -> %o
29 export default function formatWithStyles(
30 inputArgs: $ReadOnlyArray<any>,
31 style?: string,
32 ): $ReadOnlyArray<any> {
33 if (
34 inputArgs === undefined ||
35 // $FlowFixMe[invalid-compare]
36 inputArgs === null ||
37 inputArgs.length === 0 ||
38 // Matches any of %c but not %%c
39 (typeof inputArgs[0] === 'string' && inputArgs[0].match(/([^%]|^)(%c)/g)) ||
40 style === undefined
41 ) {
42 return inputArgs;
43 }
44
45 // Matches any of %(o|O|d|i|s|f), but not %%(o|O|d|i|s|f)
46 const REGEXP = /([^%]|^)((%%)*)(%([oOdisf]))/g;
47 if (typeof inputArgs[0] === 'string' && inputArgs[0].match(REGEXP)) {
48 return [`%c${inputArgs[0]}`, style, ...inputArgs.slice(1)];
49 } else {
50 const firstArg = inputArgs.reduce((formatStr, elem, i) => {
51 if (i > 0) {
52 formatStr += ' ';
53 }
54 switch (typeof elem) {
55 case 'string':
56 case 'boolean':
57 case 'symbol':
58 return (formatStr += '%s');
59 case 'number':
60 const formatting = Number.isInteger(elem) ? '%i' : '%f';
61 return (formatStr += formatting);
62 default:
63 return (formatStr += '%o');
64 }
65 }, '%c');
66 return [firstArg, style, ...inputArgs];
67 }
68 }