-
Notifications
You must be signed in to change notification settings - Fork 47.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore[react-devtools]: extract some utils into separate modules to un…
…ify implementations (#30597) Stacked on #30596. See [this commit](4ba5e78). Moving `formatWithStyles` and `formatConsoleArguments` to its own modules, so that we can finally have a single implementation for these and stop inlining them in RDT global hook object.
- Loading branch information
Showing
4 changed files
with
150 additions
and
216 deletions.
There are no files selected for viewing
72 changes: 72 additions & 0 deletions
72
packages/react-devtools-shared/src/backend/utils/formatConsoleArguments.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/** | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
// Do not add / import anything to this file. | ||
// This function could be used from multiple places, including hook. | ||
|
||
// Skips CSS and object arguments, inlines other in the first argument as a template string | ||
export default function formatConsoleArguments( | ||
maybeMessage: any, | ||
...inputArgs: $ReadOnlyArray<any> | ||
): $ReadOnlyArray<any> { | ||
if (inputArgs.length === 0 || typeof maybeMessage !== 'string') { | ||
return [maybeMessage, ...inputArgs]; | ||
} | ||
|
||
const args = inputArgs.slice(); | ||
|
||
let template = ''; | ||
let argumentsPointer = 0; | ||
for (let i = 0; i < maybeMessage.length; ++i) { | ||
const currentChar = maybeMessage[i]; | ||
if (currentChar !== '%') { | ||
template += currentChar; | ||
continue; | ||
} | ||
|
||
const nextChar = maybeMessage[i + 1]; | ||
++i; | ||
|
||
// Only keep CSS and objects, inline other arguments | ||
switch (nextChar) { | ||
case 'c': | ||
case 'O': | ||
case 'o': { | ||
++argumentsPointer; | ||
template += `%${nextChar}`; | ||
|
||
break; | ||
} | ||
case 'd': | ||
case 'i': { | ||
const [arg] = args.splice(argumentsPointer, 1); | ||
template += parseInt(arg, 10).toString(); | ||
|
||
break; | ||
} | ||
case 'f': { | ||
const [arg] = args.splice(argumentsPointer, 1); | ||
template += parseFloat(arg).toString(); | ||
|
||
break; | ||
} | ||
case 's': { | ||
const [arg] = args.splice(argumentsPointer, 1); | ||
template += arg.toString(); | ||
|
||
break; | ||
} | ||
|
||
default: | ||
template += `%${nextChar}`; | ||
} | ||
} | ||
|
||
return [template, ...args]; | ||
} |
67 changes: 67 additions & 0 deletions
67
packages/react-devtools-shared/src/backend/utils/formatWithStyles.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
// Do not add / import anything to this file. | ||
// This function could be used from multiple places, including hook. | ||
|
||
// Formats an array of args with a style for console methods, using | ||
// the following algorithm: | ||
// 1. The first param is a string that contains %c | ||
// - Bail out and return the args without modifying the styles. | ||
// We don't want to affect styles that the developer deliberately set. | ||
// 2. The first param is a string that doesn't contain %c but contains | ||
// string formatting | ||
// - [`%c${args[0]}`, style, ...args.slice(1)] | ||
// - Note: we assume that the string formatting that the developer uses | ||
// is correct. | ||
// 3. The first param is a string that doesn't contain string formatting | ||
// OR is not a string | ||
// - Create a formatting string where: | ||
// boolean, string, symbol -> %s | ||
// number -> %f OR %i depending on if it's an int or float | ||
// default -> %o | ||
export default function formatWithStyles( | ||
inputArgs: $ReadOnlyArray<any>, | ||
style?: string, | ||
): $ReadOnlyArray<any> { | ||
if ( | ||
inputArgs === undefined || | ||
inputArgs === null || | ||
inputArgs.length === 0 || | ||
// Matches any of %c but not %%c | ||
(typeof inputArgs[0] === 'string' && inputArgs[0].match(/([^%]|^)(%c)/g)) || | ||
style === undefined | ||
) { | ||
return inputArgs; | ||
} | ||
|
||
// Matches any of %(o|O|d|i|s|f), but not %%(o|O|d|i|s|f) | ||
const REGEXP = /([^%]|^)((%%)*)(%([oOdisf]))/g; | ||
if (typeof inputArgs[0] === 'string' && inputArgs[0].match(REGEXP)) { | ||
return [`%c${inputArgs[0]}`, style, ...inputArgs.slice(1)]; | ||
} else { | ||
const firstArg = inputArgs.reduce((formatStr, elem, i) => { | ||
if (i > 0) { | ||
formatStr += ' '; | ||
} | ||
switch (typeof elem) { | ||
case 'string': | ||
case 'boolean': | ||
case 'symbol': | ||
return (formatStr += '%s'); | ||
case 'number': | ||
const formatting = Number.isInteger(elem) ? '%i' : '%f'; | ||
return (formatStr += formatting); | ||
default: | ||
return (formatStr += '%o'); | ||
} | ||
}, '%c'); | ||
return [firstArg, style, ...inputArgs]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.