Upgrade to Prettier 3 (#25902)

This commit is contained in:
Renaud Chaput 2023-07-13 11:26:45 +02:00 committed by GitHub
parent 0d7340380c
commit 73b64b8917
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 82 additions and 56 deletions

View file

@ -32,7 +32,7 @@ export const AnimatedNumber: React.FC<Props> = ({ value, obfuscate }) => {
const willEnter = useCallback(() => ({ y: -1 * direction }), [direction]); const willEnter = useCallback(() => ({ y: -1 * direction }), [direction]);
const willLeave = useCallback( const willLeave = useCallback(
() => ({ y: spring(1 * direction, { damping: 35, stiffness: 400 }) }), () => ({ y: spring(1 * direction, { damping: 35, stiffness: 400 }) }),
[direction] [direction],
); );
if (reduceMotion) { if (reduceMotion) {

View file

@ -4,7 +4,7 @@ import { FormattedMessage } from 'react-intl';
export const StatusesCounter = ( export const StatusesCounter = (
displayNumber: React.ReactNode, displayNumber: React.ReactNode,
pluralReady: number pluralReady: number,
) => ( ) => (
<FormattedMessage <FormattedMessage
id='account.statuses_counter' id='account.statuses_counter'
@ -18,7 +18,7 @@ export const StatusesCounter = (
export const FollowingCounter = ( export const FollowingCounter = (
displayNumber: React.ReactNode, displayNumber: React.ReactNode,
pluralReady: number pluralReady: number,
) => ( ) => (
<FormattedMessage <FormattedMessage
id='account.following_counter' id='account.following_counter'
@ -32,7 +32,7 @@ export const FollowingCounter = (
export const FollowersCounter = ( export const FollowersCounter = (
displayNumber: React.ReactNode, displayNumber: React.ReactNode,
pluralReady: number pluralReady: number,
) => ( ) => (
<FormattedMessage <FormattedMessage
id='account.followers_counter' id='account.followers_counter'

View file

@ -32,7 +32,7 @@ export const GIFV: React.FC<Props> = ({
onClick(); onClick();
} }
}, },
[onClick] [onClick],
); );
return ( return (

View file

@ -108,7 +108,7 @@ export const timeAgoString = (
now: number, now: number,
year: number, year: number,
timeGiven: boolean, timeGiven: boolean,
short?: boolean short?: boolean,
) => { ) => {
const delta = now - date.getTime(); const delta = now - date.getTime();
@ -118,28 +118,28 @@ export const timeAgoString = (
relativeTime = intl.formatMessage(messages.today); relativeTime = intl.formatMessage(messages.today);
} else if (delta < 10 * SECOND) { } else if (delta < 10 * SECOND) {
relativeTime = intl.formatMessage( relativeTime = intl.formatMessage(
short ? messages.just_now : messages.just_now_full short ? messages.just_now : messages.just_now_full,
); );
} else if (delta < 7 * DAY) { } else if (delta < 7 * DAY) {
if (delta < MINUTE) { if (delta < MINUTE) {
relativeTime = intl.formatMessage( relativeTime = intl.formatMessage(
short ? messages.seconds : messages.seconds_full, short ? messages.seconds : messages.seconds_full,
{ number: Math.floor(delta / SECOND) } { number: Math.floor(delta / SECOND) },
); );
} else if (delta < HOUR) { } else if (delta < HOUR) {
relativeTime = intl.formatMessage( relativeTime = intl.formatMessage(
short ? messages.minutes : messages.minutes_full, short ? messages.minutes : messages.minutes_full,
{ number: Math.floor(delta / MINUTE) } { number: Math.floor(delta / MINUTE) },
); );
} else if (delta < DAY) { } else if (delta < DAY) {
relativeTime = intl.formatMessage( relativeTime = intl.formatMessage(
short ? messages.hours : messages.hours_full, short ? messages.hours : messages.hours_full,
{ number: Math.floor(delta / HOUR) } { number: Math.floor(delta / HOUR) },
); );
} else { } else {
relativeTime = intl.formatMessage( relativeTime = intl.formatMessage(
short ? messages.days : messages.days_full, short ? messages.days : messages.days_full,
{ number: Math.floor(delta / DAY) } { number: Math.floor(delta / DAY) },
); );
} }
} else if (date.getFullYear() === year) { } else if (date.getFullYear() === year) {
@ -158,7 +158,7 @@ const timeRemainingString = (
intl: IntlShape, intl: IntlShape,
date: Date, date: Date,
now: number, now: number,
timeGiven = true timeGiven = true,
) => { ) => {
const delta = date.getTime() - now; const delta = date.getTime() - now;

View file

@ -6,7 +6,7 @@ import { toShortNumber, pluralReady, DECIMAL_UNITS } from '../utils/numbers';
type ShortNumberRenderer = ( type ShortNumberRenderer = (
displayNumber: JSX.Element, displayNumber: JSX.Element,
pluralReady: number pluralReady: number,
) => JSX.Element; ) => JSX.Element;
interface ShortNumberProps { interface ShortNumberProps {
@ -25,7 +25,7 @@ export const ShortNumberRenderer: React.FC<ShortNumberProps> = ({
if (children && renderer) { if (children && renderer) {
console.warn( console.warn(
'Both renderer prop and renderer as a child provided. This is a mistake and you really should fix that. Only renderer passed as a child will be used.' 'Both renderer prop and renderer as a child provided. This is a mistake and you really should fix that. Only renderer passed as a child will be used.',
); );
} }

View file

@ -25,7 +25,7 @@ export type SearchData = [
BaseEmoji['native'], BaseEmoji['native'],
Emoji['short_names'], Emoji['short_names'],
Search, Search,
Emoji['unified'] Emoji['unified'],
]; ];
export interface ShortCodesToEmojiData { export interface ShortCodesToEmojiData {
@ -38,7 +38,7 @@ export type EmojiCompressed = [
Skins, Skins,
Category[], Category[],
Data['aliases'], Data['aliases'],
EmojisWithoutShortCodes EmojisWithoutShortCodes,
]; ];
/* /*

View file

@ -12,7 +12,7 @@ if (!HTMLCanvasElement.prototype.toBlob) {
this: HTMLCanvasElement, this: HTMLCanvasElement,
callback: BlobCallback, callback: BlobCallback,
type = 'image/png', type = 'image/png',
quality: unknown quality: unknown,
) { ) {
const dataURL: string = this.toDataURL(type, quality); const dataURL: string = this.toDataURL(type, quality);
let data; let data;

View file

@ -99,7 +99,7 @@ const initialRootState = Object.fromEntries(
reducer(undefined, { reducer(undefined, {
// empty action // empty action
}), }),
]) ]),
); );
const RootStateRecord = ImmutableRecord(initialRootState, 'RootState'); const RootStateRecord = ImmutableRecord(initialRootState, 'RootState');

View file

@ -35,7 +35,7 @@ interface PopModalOption {
} }
const popModal = ( const popModal = (
state: State, state: State,
{ modalType, ignoreFocus }: PopModalOption { modalType, ignoreFocus }: PopModalOption,
): State => { ): State => {
if ( if (
modalType === undefined || modalType === undefined ||
@ -52,12 +52,12 @@ const popModal = (
const pushModal = ( const pushModal = (
state: State, state: State,
modalType: ModalType, modalType: ModalType,
modalProps: ModalProps modalProps: ModalProps,
): State => { ): State => {
return state.withMutations((record) => { return state.withMutations((record) => {
record.set('ignoreFocus', false); record.set('ignoreFocus', false);
record.update('stack', (stack) => record.update('stack', (stack) =>
stack.unshift(Modal({ modalType, modalProps })) stack.unshift(Modal({ modalType, modalProps })),
); );
}); });
}; };
@ -68,14 +68,14 @@ export function modalReducer(
modalType: ModalType; modalType: ModalType;
ignoreFocus: boolean; ignoreFocus: boolean;
modalProps: Record<string, unknown>; modalProps: Record<string, unknown>;
}> }>,
) { ) {
switch (action.type) { switch (action.type) {
case openModal.type: case openModal.type:
return pushModal( return pushModal(
state, state,
action.payload.modalType, action.payload.modalType,
action.payload.modalProps action.payload.modalProps,
); );
case closeModal.type: case closeModal.type:
return popModal(state, action.payload); return popModal(state, action.payload);
@ -85,8 +85,8 @@ export function modalReducer(
return state.update('stack', (stack) => return state.update('stack', (stack) =>
stack.filterNot( stack.filterNot(
// @ts-expect-error TIMELINE_DELETE action is not typed yet. // @ts-expect-error TIMELINE_DELETE action is not typed yet.
(modal) => modal.get('modalProps').statusId === action.id (modal) => modal.get('modalProps').statusId === action.id,
) ),
); );
default: default:
return state; return state;

View file

@ -3,12 +3,12 @@ const easingOutQuint = (
t: number, t: number,
b: number, b: number,
c: number, c: number,
d: number d: number,
) => c * ((t = t / d - 1) * t * t * t * t + 1) + b; ) => c * ((t = t / d - 1) * t * t * t * t + 1) + b;
const scroll = ( const scroll = (
node: Element, node: Element,
key: 'scrollTop' | 'scrollLeft', key: 'scrollTop' | 'scrollLeft',
target: number target: number,
) => { ) => {
const startTime = Date.now(); const startTime = Date.now();
const offset = node[key]; const offset = node[key];

View file

@ -30,7 +30,7 @@ export const store = configureStore({
.concat( .concat(
loadingBarMiddleware({ loadingBarMiddleware({
promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'], promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'],
}) }),
) )
.concat(errorsMiddleware) .concat(errorsMiddleware)
.concat(soundsMiddleware()), .concat(soundsMiddleware()),

View file

@ -14,7 +14,7 @@ const defaultTypeSuffixes: Config['promiseTypeSuffixes'] = [
]; ];
export const loadingBarMiddleware = ( export const loadingBarMiddleware = (
config: Config = {} config: Config = {},
): Middleware<Record<string, never>, RootState> => { ): Middleware<Record<string, never>, RootState> => {
const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypeSuffixes; const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypeSuffixes;

View file

@ -6,7 +6,7 @@ const buildHashtagPatternRegex = () => {
try { try {
return new RegExp( return new RegExp(
`(?:^|[^\\/\\)\\w])#(([${WORD}_][${WORD}${HASHTAG_SEPARATORS}]*[${ALPHA}${HASHTAG_SEPARATORS}][${WORD}${HASHTAG_SEPARATORS}]*[${WORD}_])|([${WORD}_]*[${ALPHA}][${WORD}_]*))`, `(?:^|[^\\/\\)\\w])#(([${WORD}_][${WORD}${HASHTAG_SEPARATORS}]*[${ALPHA}${HASHTAG_SEPARATORS}][${WORD}${HASHTAG_SEPARATORS}]*[${WORD}_])|([${WORD}_]*[${ALPHA}][${WORD}_]*))`,
'iu' 'iu',
); );
} catch { } catch {
return /(?:^|[^/)\w])#(\w*[a-zA-Z·]\w*)/i; return /(?:^|[^/)\w])#(\w*[a-zA-Z·]\w*)/i;
@ -17,7 +17,7 @@ const buildHashtagRegex = () => {
try { try {
return new RegExp( return new RegExp(
`^(([${WORD}_][${WORD}${HASHTAG_SEPARATORS}]*[${ALPHA}${HASHTAG_SEPARATORS}][${WORD}${HASHTAG_SEPARATORS}]*[${WORD}_])|([${WORD}_]*[${ALPHA}][${WORD}_]*))$`, `^(([${WORD}_][${WORD}${HASHTAG_SEPARATORS}]*[${ALPHA}${HASHTAG_SEPARATORS}][${WORD}${HASHTAG_SEPARATORS}]*[${WORD}_])|([${WORD}_]*[${ALPHA}][${WORD}_]*))$`,
'iu' 'iu',
); );
} catch { } catch {
return /^(\w*[a-zA-Z·]\w*)$/i; return /^(\w*[a-zA-Z·]\w*)$/i;

View file

@ -55,7 +55,7 @@ export function toShortNumber(sourceNumber: number): ShortNumber {
*/ */
export function pluralReady( export function pluralReady(
sourceNumber: number, sourceNumber: number,
division: DecimalUnits division: DecimalUnits,
): number { ): number {
if (division == null || division < DECIMAL_UNITS.HUNDRED) { if (division == null || division < DECIMAL_UNITS.HUNDRED) {
return sourceNumber; return sourceNumber;

View file

@ -1,6 +1,7 @@
@font-face { @font-face {
font-family: mastodon-font-monospace; font-family: mastodon-font-monospace;
src: local('Roboto Mono'), src:
local('Roboto Mono'),
url('../fonts/roboto-mono/robotomono-regular-webfont.woff2') format('woff2'), url('../fonts/roboto-mono/robotomono-regular-webfont.woff2') format('woff2'),
url('../fonts/roboto-mono/robotomono-regular-webfont.woff') format('woff'), url('../fonts/roboto-mono/robotomono-regular-webfont.woff') format('woff'),
url('../fonts/roboto-mono/robotomono-regular-webfont.ttf') url('../fonts/roboto-mono/robotomono-regular-webfont.ttf')

View file

@ -1,6 +1,7 @@
@font-face { @font-face {
font-family: mastodon-font-sans-serif; font-family: mastodon-font-sans-serif;
src: local('Roboto Italic'), src:
local('Roboto Italic'),
url('../fonts/roboto/roboto-italic-webfont.woff2') format('woff2'), url('../fonts/roboto/roboto-italic-webfont.woff2') format('woff2'),
url('../fonts/roboto/roboto-italic-webfont.woff') format('woff'), url('../fonts/roboto/roboto-italic-webfont.woff') format('woff'),
url('../fonts/roboto/roboto-italic-webfont.ttf') format('truetype'), url('../fonts/roboto/roboto-italic-webfont.ttf') format('truetype'),
@ -13,7 +14,8 @@
@font-face { @font-face {
font-family: mastodon-font-sans-serif; font-family: mastodon-font-sans-serif;
src: local('Roboto Bold'), src:
local('Roboto Bold'),
url('../fonts/roboto/roboto-bold-webfont.woff2') format('woff2'), url('../fonts/roboto/roboto-bold-webfont.woff2') format('woff2'),
url('../fonts/roboto/roboto-bold-webfont.woff') format('woff'), url('../fonts/roboto/roboto-bold-webfont.woff') format('woff'),
url('../fonts/roboto/roboto-bold-webfont.ttf') format('truetype'), url('../fonts/roboto/roboto-bold-webfont.ttf') format('truetype'),
@ -26,7 +28,8 @@
@font-face { @font-face {
font-family: mastodon-font-sans-serif; font-family: mastodon-font-sans-serif;
src: local('Roboto Medium'), src:
local('Roboto Medium'),
url('../fonts/roboto/roboto-medium-webfont.woff2') format('woff2'), url('../fonts/roboto/roboto-medium-webfont.woff2') format('woff2'),
url('../fonts/roboto/roboto-medium-webfont.woff') format('woff'), url('../fonts/roboto/roboto-medium-webfont.woff') format('woff'),
url('../fonts/roboto/roboto-medium-webfont.ttf') format('truetype'), url('../fonts/roboto/roboto-medium-webfont.ttf') format('truetype'),
@ -39,7 +42,8 @@
@font-face { @font-face {
font-family: mastodon-font-sans-serif; font-family: mastodon-font-sans-serif;
src: local('Roboto'), src:
local('Roboto'),
url('../fonts/roboto/roboto-regular-webfont.woff2') format('woff2'), url('../fonts/roboto/roboto-regular-webfont.woff2') format('woff2'),
url('../fonts/roboto/roboto-regular-webfont.woff') format('woff'), url('../fonts/roboto/roboto-regular-webfont.woff') format('woff'),
url('../fonts/roboto/roboto-regular-webfont.ttf') format('truetype'), url('../fonts/roboto/roboto-regular-webfont.ttf') format('truetype'),

View file

@ -31,9 +31,19 @@ body {
// Droid Sans => Older Androids (<4.0) // Droid Sans => Older Androids (<4.0)
// Helvetica Neue => Older macOS <10.11 // Helvetica Neue => Older macOS <10.11
// $font-sans-serif => web-font (Roboto) fallback and newer Androids (>=4.0) // $font-sans-serif => web-font (Roboto) fallback and newer Androids (>=4.0)
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', font-family:
Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', system-ui,
$font-sans-serif, sans-serif; -apple-system,
BlinkMacSystemFont,
'Segoe UI',
Oxygen,
Ubuntu,
Cantarell,
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
$font-sans-serif,
sans-serif;
} }
&.app-body { &.app-body {

View file

@ -747,7 +747,9 @@ body > [data-popper-placement] {
} }
.no-reduce-motion .spoiler-input { .no-reduce-motion .spoiler-input {
transition: height 0.4s ease, opacity 0.4s ease; transition:
height 0.4s ease,
opacity 0.4s ease;
} }
.sign-in-banner { .sign-in-banner {
@ -3954,7 +3956,9 @@ a.status-card.compact:hover {
overflow-y: auto; overflow-y: auto;
border-bottom: 1px solid lighten($ui-base-color, 8%); border-bottom: 1px solid lighten($ui-base-color, 8%);
color: $darker-text-color; color: $darker-text-color;
transition: max-height 150ms ease-in-out, opacity 300ms linear; transition:
max-height 150ms ease-in-out,
opacity 300ms linear;
opacity: 1; opacity: 1;
z-index: 1; z-index: 1;
position: relative; position: relative;
@ -6935,7 +6939,8 @@ noscript {
.navigation-bar { .navigation-bar {
& > a:first-child { & > a:first-child {
will-change: margin-top, margin-inline-start, margin-inline-end, width; will-change: margin-top, margin-inline-start, margin-inline-end, width;
transition: margin-top $duration $delay, transition:
margin-top $duration $delay,
margin-inline-start $duration ($duration + $delay), margin-inline-start $duration ($duration + $delay),
margin-inline-end $duration ($duration + $delay); margin-inline-end $duration ($duration + $delay);
} }
@ -6948,12 +6953,15 @@ noscript {
.navigation-bar__actions { .navigation-bar__actions {
& > .icon-button.close { & > .icon-button.close {
will-change: opacity transform; will-change: opacity transform;
transition: opacity $duration * 0.5 $delay, transform $duration $delay; transition:
opacity $duration * 0.5 $delay,
transform $duration $delay;
} }
& > .compose__action-bar .icon-button { & > .compose__action-bar .icon-button {
will-change: opacity transform; will-change: opacity transform;
transition: opacity $duration * 0.5 $delay + $duration * 0.5, transition:
opacity $duration * 0.5 $delay + $duration * 0.5,
transform $duration $delay; transform $duration $delay;
} }
} }
@ -9094,7 +9102,8 @@ noscript {
backdrop-filter: blur(8px); backdrop-filter: blur(8px);
border: 1px solid rgba(lighten($classic-base-color, 4%), 0.85); border: 1px solid rgba(lighten($classic-base-color, 4%), 0.85);
border-radius: 8px; border-radius: 8px;
box-shadow: 0 10px 15px -3px rgba($base-shadow-color, 0.25), box-shadow:
0 10px 15px -3px rgba($base-shadow-color, 0.25),
0 4px 6px -4px rgba($base-shadow-color, 0.25); 0 4px 6px -4px rgba($base-shadow-color, 0.25);
cursor: default; cursor: default;
transition: 0.5s cubic-bezier(0.89, 0.01, 0.5, 1.1); transition: 0.5s cubic-bezier(0.89, 0.01, 0.5, 1.1);

View file

@ -191,7 +191,7 @@
"eslint-plugin-import": "~2.27.5", "eslint-plugin-import": "~2.27.5",
"eslint-plugin-jsdoc": "^46.1.0", "eslint-plugin-jsdoc": "^46.1.0",
"eslint-plugin-jsx-a11y": "~6.7.1", "eslint-plugin-jsx-a11y": "~6.7.1",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-promise": "~6.1.1", "eslint-plugin-promise": "~6.1.1",
"eslint-plugin-react": "~7.32.2", "eslint-plugin-react": "~7.32.2",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
@ -199,7 +199,7 @@
"jest": "^29.5.0", "jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0", "jest-environment-jsdom": "^29.5.0",
"lint-staged": "^13.2.2", "lint-staged": "^13.2.2",
"prettier": "^2.8.8", "prettier": "^3.0.0",
"react-test-renderer": "^18.2.0", "react-test-renderer": "^18.2.0",
"stylelint": "^15.10.1", "stylelint": "^15.10.1",
"stylelint-config-standard-scss": "^10.0.0", "stylelint-config-standard-scss": "^10.0.0",

View file

@ -5140,12 +5140,13 @@ eslint-plugin-jsx-a11y@~6.7.1:
object.fromentries "^2.0.6" object.fromentries "^2.0.6"
semver "^6.3.0" semver "^6.3.0"
eslint-plugin-prettier@^4.2.1: eslint-plugin-prettier@^5.0.0:
version "4.2.1" version "5.0.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz#6887780ed95f7708340ec79acfdf60c35b9be57a"
integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== integrity sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==
dependencies: dependencies:
prettier-linter-helpers "^1.0.0" prettier-linter-helpers "^1.0.0"
synckit "^0.8.5"
eslint-plugin-promise@~6.1.1: eslint-plugin-promise@~6.1.1:
version "6.1.1" version "6.1.1"
@ -9305,10 +9306,10 @@ prettier-linter-helpers@^1.0.0:
dependencies: dependencies:
fast-diff "^1.1.2" fast-diff "^1.1.2"
prettier@^2.8.8: prettier@^3.0.0:
version "2.8.8" version "3.0.0"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.0.tgz#e7b19f691245a21d618c68bc54dc06122f6105ae"
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== integrity sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==
pretty-bytes@^5.3.0, pretty-bytes@^5.4.1: pretty-bytes@^5.3.0, pretty-bytes@^5.4.1:
version "5.6.0" version "5.6.0"
@ -10901,6 +10902,7 @@ stringz@^2.1.0:
char-regex "^1.0.2" char-regex "^1.0.2"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
name strip-ansi-cjs
version "6.0.1" version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==