Updated ESLint config for React+Typescript packages

refs https://github.com/TryGhost/DevOps/issues/50

- `react-app` comes from `eslint-config-react-app`, which is a CRA package
- we're moving away from that so this commit switches the linting over
  to a more recently updated plugin
- once that was removed, we started using a newer version of
  `@typescript-eslint/eslint-plugin`, so there were plenty of
  updates/exemptions to make
This commit is contained in:
Daniel Lockyer 2023-07-27 09:49:51 +02:00 committed by Daniel Lockyer
parent 5875962392
commit c97cc08455
99 changed files with 280 additions and 670 deletions

View File

@ -2,24 +2,44 @@
module.exports = {
root: true,
extends: [
'react-app',
'plugin:ghost/browser'
'plugin:ghost/ts',
'plugin:react/recommended',
'plugin:react-hooks/recommended'
],
plugins: [
'ghost',
'react-refresh',
'tailwindcss'
],
settings: {
react: {
version: 'detect'
}
},
rules: {
// sort multiple import lines into alphabetical groups
'ghost/sort-imports-es6-autofix/sort-imports-es6': ['error', {
memberSyntaxSortOrder: ['none', 'all', 'single', 'multiple']
}],
// TODO: enable this when we have the time to retroactively go and fix the issues
'prefer-const': 'off',
// TODO: re-enable this (maybe fixed fast refresh?)
'react-refresh/only-export-components': 'off',
// suppress errors for missing 'import React' in JSX files, as we don't need it
'react/react-in-jsx-scope': 'off',
// ignore prop-types for now
'react/prop-types': 'off',
// TODO: re-enable this because otherwise we're just skirting TS
'@typescript-eslint/no-explicit-any': 'warn',
// TODO: re-enable these if deemed useful
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-empty-function': 'off',
// custom react rules
'react/jsx-sort-props': ['error', {
reservedFirst: true,
@ -29,6 +49,7 @@ module.exports = {
}],
'react/button-has-type': 'error',
'react/no-array-index-key': 'error',
'react/jsx-key': 'off',
'tailwindcss/classnames-order': ['error', {config: 'tailwind.config.cjs'}],
'tailwindcss/enforces-negative-arbitrary-values': ['warn', {config: 'tailwind.config.cjs'}],

View File

@ -13,7 +13,7 @@ const meta = {
export default meta;
type Story = StoryObj<typeof List>;
const {id, ...listItemProps} = ListItemStories.HiddenActions.args || {};
const {/*id,*/ ...listItemProps} = ListItemStories.HiddenActions.args || {};
const listItems = (
<>

View File

@ -12,6 +12,8 @@ export interface SortableItemContainerProps {
setRef?: (element: HTMLElement | null) => void;
isDragging: boolean;
dragHandleAttributes?: DraggableAttributes;
// TODO: figure out a stricter alternative for Function
// eslint-disable-next-line @typescript-eslint/ban-types
dragHandleListeners?: Record<string, Function>;
dragHandleClass?: string;
style?: React.CSSProperties;

View File

@ -1,4 +1,4 @@
import React, {ChangeEvent, useState} from 'react';
import React, {CSSProperties, ChangeEvent, useState} from 'react';
export interface FileUploadProps {
id: string;
@ -11,7 +11,7 @@ export interface FileUploadProps {
children?: string | React.ReactNode;
className?: string;
onUpload: (file: File) => void;
style?: {}
style?: CSSProperties;
unstyled?: boolean;
}
@ -39,4 +39,4 @@ const FileUpload: React.FC<FileUploadProps> = ({id, onUpload, children, style, u
);
};
export default FileUpload;
export default FileUpload;

View File

@ -76,6 +76,8 @@ const MultiSelect: React.FC<MultiSelectProps> = ({
};
const dropdownIndicatorComponent = useMemo(() => {
// TODO: fix "Component definition is missing display name"
// eslint-disable-next-line react/display-name
return (ddiProps: DropdownIndicatorProps<MultiSelectOption, true>) => <DropdownIndicator {...ddiProps} clearBg={clearBg} />;
}, [clearBg]);

View File

@ -29,7 +29,7 @@ const TextField: React.FC<TextFieldProps> = ({
type = 'text',
inputRef,
title,
titleColor = 'grey',
//titleColor = 'grey',
hideTitle,
value,
error,

View File

@ -4,7 +4,7 @@ import React from 'react';
import Button from '../Button';
import Modal, {ModalProps} from './Modal';
const ModalContainer: React.FC<ModalProps> = ({children, onCancel, ...props}) => {
const ModalContainer: React.FC<ModalProps> = ({children, ...props}) => {
const modal = NiceModal.create<ModalProps>(() => {
return (
<Modal {...props}>
@ -23,4 +23,4 @@ const ModalContainer: React.FC<ModalProps> = ({children, onCancel, ...props}) =>
);
};
export default ModalContainer;
export default ModalContainer;

View File

@ -16,6 +16,8 @@ import TextField from '../../../../admin-x-ds/global/form/TextField';
import Toggle from '../../../../admin-x-ds/global/form/Toggle';
import {PreviewModalContent} from '../../../../admin-x-ds/global/modal/PreviewModal';
// TODO: do we need this interface?
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface NewsletterDetailModalProps {
}
@ -213,4 +215,4 @@ const NewsletterDetailModal: React.FC<NewsletterDetailModalProps> = () => {
/>;
};
export default NiceModal.create(NewsletterDetailModal);
export default NiceModal.create(NewsletterDetailModal);

View File

@ -43,7 +43,7 @@ const NewsletterPreview: React.FC = () => {
<div className="max-w-[600px] border-b border-grey-200 py-5 text-[1.6rem] leading-[1.7] text-black">
<p className="mb-5">This is what your content will look like when you send one of your posts as an email newsletter to your subscribers.</p>
<p className="mb-5">Over there on the left you'll see some settings that allow you to customize the look and feel of this template to make it perfectly suited to your brand. Email templates are exceptionally finnicky to make, but we've spent a long time optimising this one to make it work beautifully across devices, email clients and content types.</p>
<p className="mb-5">Over there on the left you&apos;ll see some settings that allow you to customize the look and feel of this template to make it perfectly suited to your brand. Email templates are exceptionally finnicky to make, but we&apos;ve spent a long time optimising this one to make it work beautifully across devices, email clients and content types.</p>
<p className="mb-5">So, you can trust that every email you send with Ghost will look great and work well. Just like the rest of your site.</p>
</div>
@ -140,4 +140,4 @@ const NewsletterPreview: React.FC = () => {
);
};
export default NewsletterPreview;
export default NewsletterPreview;

View File

@ -87,7 +87,7 @@ const PortalModal: React.FC = () => {
NiceModal.show(ConfirmationModal, {
title: 'Confirm email address',
prompt: <>
We've sent a confirmation email to <strong>{newEmail}</strong>.
We&apos;ve sent a confirmation email to <strong>{newEmail}</strong>.
Until verified, your support address will remain {fullEmailAddress(currentEmail?.toString() || 'noreply', siteData!)}.
</>,
okLabel: 'Close',

View File

@ -121,7 +121,7 @@ const SignupOptions: React.FC<{
<HtmlField
config={config as { editor: any }}
error={Boolean(errors.portal_signup_terms_html)}
hint={errors.portal_signup_terms_html || <>Recommended: <strong>115</strong> characters. You've used <strong className="text-green">{signupTermsLength}</strong></>}
hint={errors.portal_signup_terms_html || <>Recommended: <strong>115</strong> characters. You&apos;ve used <strong className="text-green">{signupTermsLength}</strong></>}
nodes='MINIMAL_NODES'
placeholder={`By signing up, I agree to receive emails from ...`}
title='Display notice at signup'

View File

@ -23,7 +23,7 @@ const Start: React.FC<{onNext?: () => void}> = ({onNext}) => {
<div className='mb-7 mt-6'>
Stripe is our exclusive direct payments partner. Ghost collects <strong>no fees</strong> on any payments! If you dont have a Stripe account yet, you can <a className='underline' href="https://stripe.com" rel="noopener noreferrer" target="_blank">sign up here</a>.
</div>
<StripeButton label={<>I have a Stripe account, let's go &rarr;</>} onClick={onNext} />
<StripeButton label={<>I have a Stripe account, let&apos;s go &rarr;</>} onClick={onNext} />
</div>
);
};
@ -158,4 +158,4 @@ const StripeConnectModal: React.FC = () => {
</Modal>;
};
export default NiceModal.create(StripeConnectModal);
export default NiceModal.create(StripeConnectModal);

View File

@ -65,7 +65,7 @@ const TierDetailModal: React.FC<TierDetailModalProps> = ({tier}) => {
values.currency = currency;
values.monthly_price = currencyFromDecimal(parseFloat(monthlyPrice));
values.yearly_price = currencyFromDecimal(parseFloat(yearlyPrice));
values.trial_days = parseInt(formState.trial_days);
values.trial_days = parseInt(trialDays);
}
if (tier?.id) {

View File

@ -85,7 +85,7 @@ async function handleThemeUpload({
title = `Upload successful with ${hasErrors ? 'errors' : 'warnings'}`;
prompt = <>
The theme <strong>"{uploadedTheme.name}"</strong> was installed successfully but we detected some {hasErrors ? 'errors' : 'warnings'}.
The theme <strong>&quot;{uploadedTheme.name}&quot;</strong> was installed successfully but we detected some {hasErrors ? 'errors' : 'warnings'}.
</>;
if (!uploadedTheme.active) {
@ -250,7 +250,7 @@ const ChangeThemeModal = NiceModal.create(() => {
title = `Installed with ${hasErrors ? 'errors' : 'warnings'}`;
prompt = <>
The theme <strong>"{newlyInstalledTheme.name}"</strong> was installed successfully but we detected some {hasErrors ? 'errors' : 'warnings'}.
The theme <strong>&quot;{newlyInstalledTheme.name}&quot;</strong> was installed successfully but we detected some {hasErrors ? 'errors' : 'warnings'}.
</>;
if (!newlyInstalledTheme.active) {

View File

@ -21,6 +21,8 @@ export interface FormHook<State> {
reset: () => void;
}
// TODO: figure out if we need to extend `any`?
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
const useForm = <State extends any>({initialState, onSave}: {
initialState: State,
onSave: () => void | Promise<void>

View File

@ -11,6 +11,8 @@ export type SortableIndexedList<Item> = {
setNewItem: (item: Item) => void;
}
// TODO: figure out if we need to extend `unknown`?
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
const useSortableIndexedList = <Item extends unknown>({items, setItems, blank, canAddNewItem}: {
items: Item[];
setItems: (newItems: Item[]) => void;

View File

@ -51,7 +51,7 @@ export function generateAvatarColor(name: string) {
const s = 70;
const l = 40;
let hash = 0;
for (var i = 0; i < name.length; i++) {
for (let i = 0; i < name.length; i++) {
hash = name.charCodeAt(i) + ((hash << 5) - hash);
}
@ -146,4 +146,4 @@ export function getArchivedTiers(tiers: Tier[]) {
export function numberWithCommas(x: number) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
}

View File

@ -36,14 +36,29 @@
"prepublishOnly": "yarn build"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest",
"plugin:ghost/browser"
],
"plugins": [
"ghost"
]
"env": {
"browser": true,
"jest": true
},
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2022
},
"extends": [
"plugin:ghost/browser",
"plugin:react/recommended"
],
"plugins": [
"ghost"
],
"rules": {
"react/prop-types": "off"
},
"settings": {
"react": {
"version": "detect"
}
}
},
"browserslist": {
"production": [
@ -66,8 +81,6 @@
},
"devDependencies": {
"@vitejs/plugin-react": "4.0.3",
"eslint-plugin-jest": "27.2.3",
"eslint-plugin-react": "7.33.0",
"vite": "4.4.7",
"vite-plugin-svgr": "3.2.0",
"vitest": "0.33.0"

View File

@ -2,19 +2,27 @@
module.exports = {
root: true,
extends: [
'react-app',
'plugin:ghost/browser'
'plugin:ghost/ts',
'plugin:react/recommended'
],
plugins: [
'ghost',
'tailwindcss'
],
settings: {
react: {
version: 'detect'
}
},
rules: {
// sort multiple import lines into alphabetical groups
'ghost/sort-imports-es6-autofix/sort-imports-es6': ['error', {
memberSyntaxSortOrder: ['none', 'all', 'single', 'multiple']
}],
// TODO: fix + remove this
'@typescript-eslint/no-explicit-any': 'warn',
// suppress errors for missing 'import React' in JSX files, as we don't need it
'react/react-in-jsx-scope': 'off',
// ignore prop-types for now

View File

@ -70,6 +70,7 @@ export type AppContextType = {
popup: Page | null,
// This part makes sure we can add automatic data and return types to the actions when using context.dispatchAction('actionName', data)
// eslint-disable-next-line @typescript-eslint/ban-types
dispatchAction: <T extends ActionType | SyncActionType>(action: T, data: Parameters<(typeof Actions & typeof SyncActions)[T]>[0] extends {data: any} ? Parameters<(typeof Actions & typeof SyncActions)[T]>[0]['data'] : {}) => T extends ActionType ? Promise<void> : void
}

View File

@ -177,7 +177,7 @@ async function likeComment({state, api, data: comment}: {state: AppContextType,
};
}
async function reportComment({state, api, data: comment}: {state: AppContextType, api: GhostApi, data: {id: string}}) {
async function reportComment({api, data: comment}: {api: GhostApi, data: {id: string}}) {
await api.comments.report({comment});
return {};

View File

@ -9,7 +9,7 @@ type Props = {
};
const ContentBox: React.FC<Props> = ({done}) => {
const luminance = (r: number, g: number, b: number) => {
var a = [r, g, b].map(function (v) {
const a = [r, g, b].map(function (v) {
v /= 255;
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
});
@ -17,10 +17,10 @@ const ContentBox: React.FC<Props> = ({done}) => {
};
const contrast = (rgb1: [number, number, number], rgb2: [number, number, number]) => {
var lum1 = luminance(rgb1[0], rgb1[1], rgb1[2]);
var lum2 = luminance(rgb2[0], rgb2[1], rgb2[2]);
var brightest = Math.max(lum1, lum2);
var darkest = Math.min(lum1, lum2);
const lum1 = luminance(rgb1[0], rgb1[1], rgb1[2]);
const lum2 = luminance(rgb2[0], rgb2[1], rgb2[2]);
const brightest = Math.max(lum1, lum2);
const darkest = Math.min(lum1, lum2);
return (brightest + 0.05) / (darkest + 0.05);
};
const {accentColor, colorScheme} = useAppContext();

View File

@ -36,6 +36,7 @@ export default class IFrame extends Component<any> {
this.forceUpdate();
if (this.props.onResize) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(new ResizeObserver(_ => this.props.onResize(this.iframeRoot)))?.observe?.(this.iframeRoot);
}
@ -57,7 +58,7 @@ export default class IFrame extends Component<any> {
}
render() {
const {children, head, title = '', style = {}, onResize, ...rest} = this.props;
const {children, head, title = '', style = {}, ...rest} = this.props;
return (
<iframe srcDoc={`<!DOCTYPE html>`} {...rest} ref={this.setNode} frameBorder="0" style={style} title={title}>
{this.iframeHead && createPortal(head, this.iframeHead)}

View File

@ -3,7 +3,10 @@ import {Pages} from '../pages';
import {useAppContext} from '../AppContext';
import {useEffect, useState} from 'react';
// TODO: figure out what this type should be?
// eslint-disable-next-line @typescript-eslint/ban-types
type Props = {};
const PopupBox: React.FC<Props> = () => {
const {popup} = useAppContext();

View File

@ -40,7 +40,7 @@ export const Avatar: React.FC<AvatarProps> = ({comment}) => {
};
const generateHSL = (): [number, number, number] => {
let commentMember = (comment ? comment.member : member);
const commentMember = (comment ? comment.member : member);
if (!commentMember || !commentMember.name) {
return [0,0,10];
@ -69,7 +69,7 @@ export const Avatar: React.FC<AvatarProps> = ({comment}) => {
return getInitials('Deleted member');
}
let commentMember = (comment ? comment.member : member);
const commentMember = (comment ? comment.member : member);
if (!commentMember || !commentMember.name) {
return getInitials('Anonymous');
@ -77,14 +77,14 @@ export const Avatar: React.FC<AvatarProps> = ({comment}) => {
return getInitials(commentMember.name);
};
let commentMember = (comment ? comment.member : member);
const commentMember = (comment ? comment.member : member);
const bgColor = HSLtoString(generateHSL());
const avatarStyle = {
background: bgColor
};
let avatarEl = (
const avatarEl = (
<>
{memberName ?
(<div className={`flex items-center justify-center rounded-full ${dimensionClasses}`} data-testid="avatar-background" style={avatarStyle}>

View File

@ -93,10 +93,10 @@ const AddDetailsPopup = (props: Props) => {
);
};
let returnable = [];
const returnable = [];
// using URLS over real images for avatars as serving JPG images was not optimal (based on discussion with team)
let exampleProfiles = [
const exampleProfiles = [
{avatar: 'https://randomuser.me/api/portraits/men/32.jpg', name: 'James Fletcher', expertise: 'Full-time parent'},
{avatar: 'https://randomuser.me/api/portraits/women/30.jpg', name: 'Naomi Schiff', expertise: 'Founder @ Acme Inc'},
{avatar: 'https://randomuser.me/api/portraits/men/4.jpg', name: 'Franz Tost', expertise: 'Neurosurgeon'},
@ -172,7 +172,7 @@ const AddDetailsPopup = (props: Props) => {
type="text"
value={expertise}
onChange={(e) => {
let expertiseText = e.currentTarget.value;
const expertiseText = e.currentTarget.value;
setExpertiseCharsLeft(maxExpertiseChars - expertiseText.length);
setExpertise(expertiseText);
}}

View File

@ -273,7 +273,7 @@ function setupGhostApi({siteUrl = window.location.origin, apiUrl, apiKey}: {site
};
api.init = async () => {
let [member] = await Promise.all([
const [member] = await Promise.all([
api.member.sessionData()
]);

View File

@ -96,11 +96,11 @@ export function formatRelativeTime(dateString: string): string {
export function formatExplicitTime(dateString: string): string {
const date = new Date(dateString);
let day = date.toLocaleDateString('en-us', {day: '2-digit'}); // eg. 01
let month = date.toLocaleString('en-us', {month: 'short'}); // eg. Jan
let year = date.getFullYear(); // eg. 2022
let hour = (date.getHours() < 10 ? '0' : '') + date.getHours(); // eg. 02
let minute = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes(); // eg. 09
const day = date.toLocaleDateString('en-us', {day: '2-digit'}); // eg. 01
const month = date.toLocaleString('en-us', {month: 'short'}); // eg. Jan
const year = date.getFullYear(); // eg. 2022
const hour = (date.getHours() < 10 ? '0' : '') + date.getHours(); // eg. 02
const minute = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes(); // eg. 09
return `${day} ${month} ${year} ${hour}:${minute}`;
}
@ -147,7 +147,7 @@ export const getScrollToPosition = (element: HTMLElement) => {
const currentParentWindow = currentWindow.parent;
for (let idx = 0; idx < currentParentWindow.frames.length; idx++) {
if (currentParentWindow.frames[idx] === currentWindow) {
for (let frameElement of currentParentWindow.document.getElementsByTagName('iframe')) {
for (const frameElement of currentParentWindow.document.getElementsByTagName('iframe')) {
if (frameElement.contentWindow === currentWindow) {
const rect = frameElement.getBoundingClientRect();
yOffset += rect.top + currentWindow.pageYOffset;

View File

@ -40,7 +40,6 @@ export function useSecondUpdate(fn: () => void, inputs: React.DependencyList) {
}
didMountRef.current += 1;
// We shouldn't listen for fn changes, so ignore exhaustive-deps
// eslint-disable-next-line react-hooks/exhaustive-deps
}, inputs);
}

View File

@ -31,15 +31,32 @@
"prepublishOnly": "yarn build"
},
"eslintConfig": {
"env": {
"browser": true,
"jest": true
},
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2022
},
"extends": [
"react-app",
"plugin:ghost/browser",
"plugin:i18next/recommended"
"plugin:i18next/recommended",
"plugin:react/recommended",
"plugin:react/jsx-runtime"
],
"plugins": [
"ghost",
"i18next"
]
],
"rules": {
"react/prop-types": "off"
},
"settings": {
"react": {
"version": "detect"
}
}
},
"browserslist": {
"production": [

View File

@ -1,9 +1,8 @@
import React from 'react';
import {render} from '@testing-library/react';
import {site} from './utils/fixtures';
import App from './App';
const setup = async (overrides) => {
const setup = async () => {
const testState = {
site,
member: null,

View File

@ -53,7 +53,7 @@ function openNotification({data}) {
};
}
function closeNotification({state}) {
function closeNotification() {
return {
showNotification: false
};

View File

@ -1,4 +1,4 @@
import React, {Component} from 'react';
import {Component} from 'react';
import {createPortal} from 'react-dom';
export default class Frame extends Component {

View File

@ -48,13 +48,13 @@ const NotificationText = ({type, status, context}) => {
/* eslint-disable i18next/no-literal-string */
return (
<p>
You've successfully subscribed to <br /><strong>{context.site.title}</strong>
You&apos;ve successfully subscribed to <br /><strong>{context.site.title}</strong>
</p>
);
} else if (type === 'signup-paid' && status === 'success') {
return (
<p>
You've successfully subscribed to <br /><strong>{context.site.title}</strong>
You&apos;ve successfully subscribed to <br /><strong>{context.site.title}</strong>
</p>
);
/* eslint-enable i18next/no-literal-string */

View File

@ -8,7 +8,7 @@ import PopupNotification from './common/PopupNotification';
import PoweredBy from './common/PoweredBy';
import {getSiteProducts, isInviteOnlySite, isCookiesDisabled, hasFreeProductPrice} from '../utils/helpers';
const StylesWrapper = ({member}) => {
const StylesWrapper = () => {
return {
modalContainer: {
zIndex: '3999999',

View File

@ -20,7 +20,7 @@ const ICON_MAPPING = {
'icon-5': ButtonIcon5
};
const Styles = ({brandColor, hasText}) => {
const Styles = ({hasText}) => {
const frame = {
...(!hasText ? {width: '105px'} : {}),
...(hasMode(['preview']) ? {opacity: 1} : {})

View File

@ -1,14 +1,14 @@
import React from 'react';
import {render} from '../utils/test-utils';
import TriggerButton from './TriggerButton';
const setup = (overrides) => {
const setup = () => {
const {mockOnActionFn, ...utils} = render(
<TriggerButton />
);
const triggerFrame = utils.getByTitle('portal-trigger');
return {
mockOnActionFn,
triggerFrame,
...utils
};

View File

@ -1,4 +1,3 @@
import React from 'react';
import {ReactComponent as LoaderIcon} from '../../images/icons/loader.svg';
import {isCookiesDisabled} from '../../utils/helpers';
@ -56,7 +55,7 @@ export const ActionButtonStyles = `
}
`;
const Styles = ({brandColor, retry, disabled, style = {}, isPrimary}) => {
const Styles = ({brandColor, disabled, style = {}, isPrimary}) => {
let backgroundColor = (brandColor || '#3eb0ef');
let opacity = '1.0';
let pointerEvents = 'auto';

View File

@ -1,8 +1,7 @@
import React from 'react';
import {render, fireEvent} from '@testing-library/react';
import ActionButton from './ActionButton';
const setup = (overrides) => {
const setup = () => {
const mockOnClickFn = jest.fn();
const props = {
label: 'Test Action Button', onClick: mockOnClickFn, disabled: false

View File

@ -1,4 +1,4 @@
import React, {useContext} from 'react';
import {useContext} from 'react';
import AppContext from '../../AppContext';
import {ReactComponent as LeftArrowIcon} from '../../images/icons/arrow-left.svg';
@ -41,7 +41,7 @@ export const BackButtonStyles = `
}
`;
function ActionButton({label = null, brandColor = '#3eb0ef', hidden = false, onClick}) {
function ActionButton({label = null, hidden = false, onClick}) {
const {t} = useContext(AppContext);
if (hidden) {

View File

@ -1,4 +1,4 @@
import React, {useEffect, useRef} from 'react';
import {useEffect, useRef} from 'react';
import {hasMode} from '../../utils/check-mode';
import {isCookiesDisabled} from '../../utils/helpers';

View File

@ -1,8 +1,7 @@
import React from 'react';
import {render, fireEvent} from '@testing-library/react';
import InputField from './InputField';
const setup = (overrides = {}) => {
const setup = () => {
const mockOnChangeFn = jest.fn();
const props = {
name: 'test-input',

View File

@ -1,4 +1,4 @@
import React, {Component} from 'react';
import {Component} from 'react';
import InputField from './InputField';
const FormInput = ({field, onChange, onBlur = () => { }, onKeyDown = () => {}}) => {

View File

@ -1,4 +1,3 @@
import React from 'react';
import {ReactComponent as UserIcon} from '../../images/icons/user.svg';
export const AvatarStyles = `

View File

@ -1,8 +1,7 @@
import React from 'react';
import {render} from '@testing-library/react';
import MemberGravatar from './MemberGravatar';
const setup = (overrides = {}) => {
const setup = () => {
const props = {
gravatar: 'https://gravatar.com/avatar/76a4c5450dbb6fde8a293a811622aa6f?s=250&d=blank'
};

View File

@ -1,7 +1,7 @@
import AppContext from '../../AppContext';
import CloseButton from '../common/CloseButton';
import BackButton from '../common/BackButton';
import React, {useContext, useState} from 'react';
import {useContext, useState} from 'react';
import Switch from '../common/Switch';
import {getSiteNewsletters, hasMemberGotEmailSuppression} from '../../utils/helpers';
import ActionButton from '../common/ActionButton';
@ -11,7 +11,7 @@ function AccountHeader() {
const {brandColor, lastPage, onAction, t} = useContext(AppContext);
return (
<header className='gh-portal-detail-header'>
<BackButton brandColor={brandColor} hidden={!lastPage} onClick={(e) => {
<BackButton brandColor={brandColor} hidden={!lastPage} onClick={() => {
onAction('back');
}} />
<h3 className='gh-portal-main-title'>{t('Email preferences')}</h3>
@ -187,7 +187,7 @@ export default function NewsletterManagement({
<div style={{width: '100%'}}>
<ActionButton
isRunning={false}
onClick={(e) => {
onClick={() => {
unsubscribeAll();
}}
disabled={isDisabled}

View File

@ -1,4 +1,3 @@
import React from 'react';
import {isCookiesDisabled} from '../../utils/helpers';
import ProductsSection, {ChangeProductSection} from './ProductsSection';

View File

@ -126,7 +126,6 @@ const NotificationText = ({message, site, t}) => {
syntax={SYNTAX_I18NEXT}
string={t('An unexpected error occured. Please try again or <a>contact support</a> if the error persists.')}
mapping={{
// eslint-disable-next-line jsx-a11y/anchor-has-content
a: <a href={supportAddressMail} onClick={() => {
supportAddressMail && window.open(supportAddressMail);
}}/>
@ -156,7 +155,7 @@ export default class PopupNotification extends React.Component {
}
}
closeNotification(e) {
closeNotification() {
this.context.onAction('clearPopupNotification');
}

View File

@ -7,7 +7,7 @@ import calculateDiscount from '../../utils/discount';
import Interpolate from '@doist/react-interpolate';
import {SYNTAX_I18NEXT} from '@doist/react-interpolate';
export const ProductsSectionStyles = ({site}) => {
export const ProductsSectionStyles = () => {
// const products = getSiteProducts({site});
// const noOfProducts = products.length;
return `
@ -824,7 +824,7 @@ function ProductCards({products, selectedInterval, handleChooseSignup, errors})
});
}
function YearlyDiscount({discount, trialDays}) {
function YearlyDiscount({discount}) {
const {site, t} = useContext(AppContext);
const {portal_plans: portalPlans} = site;
@ -847,7 +847,7 @@ function YearlyDiscount({discount, trialDays}) {
}
}
function ProductPriceSwitch({products, selectedInterval, setSelectedInterval}) {
function ProductPriceSwitch({selectedInterval, setSelectedInterval}) {
const {site, t} = useContext(AppContext);
const {portal_plans: portalPlans} = site;
if (!portalPlans.includes('monthly') || !portalPlans.includes('yearly')) {
@ -860,7 +860,7 @@ function ProductPriceSwitch({products, selectedInterval, setSelectedInterval}) {
<button
data-test-button='switch-monthly'
className={'gh-portal-btn' + (selectedInterval === 'month' ? ' active' : '')}
onClick={(e) => {
onClick={() => {
setSelectedInterval('month');
}}
>
@ -869,7 +869,7 @@ function ProductPriceSwitch({products, selectedInterval, setSelectedInterval}) {
<button
data-test-button='switch-yearly'
className={'gh-portal-btn' + (selectedInterval === 'year' ? ' active' : '')}
onClick={(e) => {
onClick={() => {
setSelectedInterval('year');
}}
>
@ -1044,7 +1044,7 @@ export function ChangeProductSection({onPlanSelect, selectedPlan, products, type
);
}
function ProductDescription({product, selectedPrice, activePrice}) {
function ProductDescription({product}) {
if (product?.description) {
return (
<div className="gh-portal-product-description" data-testid="product-description">

View File

@ -1,4 +1,4 @@
import React, {useContext, useEffect, useState} from 'react';
import {useContext, useEffect, useState} from 'react';
import AppContext from '../../AppContext';
export const SwitchStyles = `

View File

@ -1,8 +1,7 @@
import React from 'react';
import {render, fireEvent} from '@testing-library/react';
import Switch from './Switch';
const setup = (overrides = {}) => {
const setup = () => {
const mockOnToggle = jest.fn();
const props = {
onToggle: mockOnToggle,

View File

@ -1,5 +1,5 @@
import AppContext from '../../AppContext';
import React, {useContext, useEffect, useState} from 'react';
import {useContext, useEffect, useState} from 'react';
import {isPaidMember} from '../../utils/helpers';
import NewsletterManagement from '../common/NewsletterManagement';

View File

@ -1,4 +1,3 @@
import React from 'react';
import {render, fireEvent} from '../../../utils/test-utils';
import AccountHomePage from './AccountHomePage';
import {site} from '../../../utils/fixtures';

View File

@ -1,4 +1,4 @@
const AccountFooter = ({onClose, handleSignout, supportAddress = '', t}) => {
const AccountFooter = ({handleSignout, supportAddress = '', t}) => {
const supportAddressMail = `mailto:${supportAddress}`;
return (
<footer className='gh-portal-account-footer'>

View File

@ -34,7 +34,7 @@ const ContinueSubscriptionButton = () => {
<div className='gh-portal-cancelcontinue-container'>
<CancelNotice />
<ActionButton
onClick={(e) => {
onClick={() => {
onAction('continueSubscription', {
subscriptionId: subscription.id
});

View File

@ -9,7 +9,7 @@ function EmailNewsletterAction() {
const subscribed = !!newsletters?.length;
let label = subscribed ? t('Subscribed') : t('Unsubscribed');
const onToggleSubscription = (e, sub) => {
const onToggleSubscription = (e) => {
e.preventDefault();
const siteNewsletters = getSiteNewsletters({site});
const subscribedNewsletters = !member?.newsletters?.length ? siteNewsletters : [];

View File

@ -24,7 +24,7 @@ function EmailPreferencesAction() {
: <p>{t('Update your preferences')}</p>
}
</div>
<button className='gh-portal-btn gh-portal-btn-list' onClick={(e) => {
<button className='gh-portal-btn gh-portal-btn-list' onClick={() => {
onAction('switchPage', {
page,
lastPage: 'accountHome'

View File

@ -171,7 +171,7 @@ const PaidAccountActions = () => {
return null;
};
function FreeTrialLabel({subscription, priceLabel, t}) {
function FreeTrialLabel({subscription, t}) {
if (subscriptionHasFreeTrial({sub: subscription})) {
const trialEnd = getDateString(subscription.trial_end_at);
return (

View File

@ -1,6 +1,6 @@
import AppContext from '../../../../AppContext';
import MemberAvatar from '../../../common/MemberGravatar';
import React, {useContext} from 'react';
import {useContext} from 'react';
const UserHeader = () => {
const {member, brandColor, t} = useContext(AppContext);

View File

@ -50,7 +50,7 @@ function getConfirmationPageTitle({confirmationType, t}) {
}
}
const Header = ({onBack, showConfirmation, confirmationType}) => {
const Header = ({showConfirmation, confirmationType}) => {
const {member, t} = useContext(AppContext);
let title = isPaidMember({member}) ? 'Change plan' : 'Choose a plan';
if (showConfirmation) {
@ -87,7 +87,7 @@ const CancelSubscriptionButton = ({member, onCancelSubscription, action, brandCo
<div className="gh-portal-expire-container">
<ActionButton
dataTestId={'cancel-subscription'}
onClick={(e) => {
onClick={() => {
onCancelSubscription({
subscriptionId: subscription.id,
cancelAtPeriodEnd: true
@ -222,7 +222,7 @@ const ChangePlanSection = ({plans, selectedPlan, onPlanSelect, onCancelSubscript
);
};
function PlansOrProductSection({showLabel, plans, selectedPlan, onPlanSelect, onPlanCheckout, changePlan = false}) {
function PlansOrProductSection({selectedPlan, onPlanSelect, onPlanCheckout, changePlan = false}) {
const {site, member} = useContext(AppContext);
const products = getUpgradeProducts({site, member});
const isComplimentary = isComplimentaryMember({member});
@ -354,7 +354,7 @@ export default class AccountPlanPage extends React.Component {
this.context.onAction('signout');
}
onBack(e) {
onBack() {
if (this.state.showConfirmation) {
this.cancelConfirmPage();
} else {
@ -419,7 +419,7 @@ export default class AccountPlanPage extends React.Component {
}
};
onCancelSubscription({subscriptionId, cancelAtPeriodEnd}) {
onCancelSubscription({subscriptionId}) {
const {member} = this.context;
const subscription = getSubscriptionFromId({subscriptionId, member});
const subscriptionPlan = getPriceFromSubscription({subscription});

View File

@ -1,4 +1,3 @@
import React from 'react';
import {generateAccountPlanFixture, getSiteData, getProductsData} from '../../utils/fixtures-generator';
import {render, fireEvent} from '../../utils/test-utils';
import AccountPlanPage from './AccountPlanPage';

View File

@ -33,7 +33,7 @@ export default class AccountProfilePage extends React.Component {
this.context.onAction('signout');
}
onBack(e) {
onBack() {
this.context.onAction('back');
}

View File

@ -1,8 +1,7 @@
import React from 'react';
import {render, fireEvent} from '../../utils/test-utils';
import AccountProfilePage from './AccountProfilePage';
const setup = (overrides) => {
const setup = () => {
const {mockOnActionFn, context, ...utils} = render(
<AccountProfilePage />
);

View File

@ -25,7 +25,7 @@ export default function EmailReceivingPage() {
<CloseButton />
</header>
<div class="gh-longform">
<div className="gh-longform">
<h3>{t(`Help! I'm not receiving emails`)}</h3>
<p>{t(`If you're not receiving the email newsletter you've subscribed to, here are few things to check.`)}</p>

View File

@ -1,8 +1,7 @@
import React from 'react';
import {render, fireEvent} from '../../utils/test-utils';
import EmailSuppressedPage from './EmailSuppressedPage';
const setup = (overrides) => {
const setup = () => {
const {mockOnActionFn, ...utils} = render(
<EmailSuppressedPage />
);

View File

@ -18,7 +18,7 @@ export default function EmailSuppressedPage() {
<CloseButton />
</header>
<div class="gh-longform">
<div className="gh-longform">
<h3>{t('Why has my email been disabled?')}</h3>
<p>{t('Newsletters can be disabled on your account for two reasons: A previous email was marked as spam, or attempting to send an email resulted in a permanent failure (bounce).')}</p>
<h4>{t('Spam complaints')}</h4>

View File

@ -1,4 +1,4 @@
import React, {useContext, useEffect, useState} from 'react';
import {useContext, useEffect, useState} from 'react';
import AppContext from '../../AppContext';
import {ReactComponent as ThumbDownIcon} from '../../images/icons/thumbs-down.svg';
import {ReactComponent as ThumbUpIcon} from '../../images/icons/thumbs-up.svg';
@ -171,7 +171,7 @@ function ErrorPage({error}) {
return (
<div className='gh-portal-content gh-portal-feedback with-footer'>
<CloseButton />
<div class="gh-feedback-icon gh-feedback-icon-error">
<div className="gh-feedback-icon gh-feedback-icon-error">
<ThumbErrorIcon />
</div>
<h1 className="gh-portal-main-title">{t('Sorry, that didnt work.')}</h1>

View File

@ -63,7 +63,7 @@ export default class MagicLinkPage extends React.Component {
);
}
handleClose(e) {
handleClose() {
this.context.onAction('closePopup');
}

View File

@ -1,8 +1,7 @@
import React from 'react';
import {render, fireEvent} from '../../utils/test-utils';
import MagicLinkPage from './MagicLinkPage';
const setup = (overrides) => {
const setup = () => {
const {mockOnActionFn, ...utils} = render(
<MagicLinkPage />
);

View File

@ -1,5 +1,5 @@
import AppContext from '../../AppContext';
import React, {useContext, useState} from 'react';
import {useContext, useState} from 'react';
import Switch from '../common/Switch';
import {getSiteNewsletters, hasOnlyFreePlan} from '../../utils/helpers';
import ActionButton from '../common/ActionButton';
@ -16,7 +16,7 @@ function NewsletterPrefSection({newsletter, subscribedNewsletters, setSubscribed
<h3>{newsletter.name}</h3>
<p>{newsletter.description}</p>
</div>
<div class="gh-portal-lock-icon-container">
<div className="gh-portal-lock-icon-container">
<LockIcon className='gh-portal-lock-icon' alt='' title={t('Unlock access to all newsletters by becoming a paid subscriber.')} />
</div>
</section>
@ -103,7 +103,7 @@ export default function NewsletterSelectionPage({pageData, onBack}) {
isRunning={isRunning}
retry={retry}
disabled={disabled}
onClick={(e) => {
onClick={() => {
let newsletters = subscribedNewsletters.map((d) => {
return {
id: d.id

View File

@ -8,7 +8,7 @@ import {getCurrencySymbol, getProductFromId, hasMultipleProductsFeature, isSameC
import {ValidateInputForm} from '../../utils/form';
import NewsletterSelectionPage from './NewsletterSelectionPage';
export const OfferPageStyles = ({site}) => {
export const OfferPageStyles = () => {
return `
.gh-portal-offer {
padding-bottom: 0;
@ -243,7 +243,7 @@ export default class OfferPage extends React.Component {
required={true}
onChange={handleCheckboxChange}
/>
<span class="checkbox"></span>
<span className="checkbox"></span>
{termsText}
</label>
) : termsText;
@ -517,7 +517,7 @@ export default class OfferPage extends React.Component {
return '';
}
renderOfferMessage({offer, product, price, t}) {
renderOfferMessage({offer, product, t}) {
const offerMessages = {
forever: t(`{{amount}} off forever.`, {
amount: this.getOffAmount({offer})
@ -558,7 +558,7 @@ export default class OfferPage extends React.Component {
amount: offer.amount,
originalPrice: originalPrice,
interpolation: {escapeValue: false}
})} <span class="gh-portal-cancel">{t('Cancel anytime.')}</span></p>
})} <span className="gh-portal-cancel">{t('Cancel anytime.')}</span></p>
);
}
return (

View File

@ -1,8 +1,7 @@
import React from 'react';
import {render, fireEvent} from '../../utils/test-utils';
import SigninPage from './SigninPage';
const setup = (overrides) => {
const setup = () => {
const {mockOnActionFn, ...utils} = render(
<SigninPage />,
{

View File

@ -422,7 +422,7 @@ class SignupPage extends React.Component {
e && e.preventDefault();
// Hack: React checkbox gets out of sync with dom state with instant update
this.timeoutId = setTimeout(() => {
this.setState((prevState) => {
this.setState(() => {
return {
plan: priceId
};
@ -517,7 +517,7 @@ class SignupPage extends React.Component {
required={true}
onChange={handleCheckboxChange}
/>
<span class="checkbox"></span>
<span className="checkbox"></span>
{termsText}
</label>
) : termsText;

View File

@ -1,4 +1,3 @@
import React from 'react';
import SignupPage from './SignupPage';
import {getFreeProduct, getProductData, getSiteData} from '../../utils/fixtures-generator';
import {render, fireEvent} from '../../utils/test-utils';

View File

@ -1,6 +1,6 @@
import AppContext from '../../AppContext';
import ActionButton from '../common/ActionButton';
import React, {useContext, useEffect, useState} from 'react';
import {useContext, useEffect, useState} from 'react';
import {getSiteNewsletters} from '../../utils/helpers';
import setupGhostApi from '../../utils/api';
import NewsletterManagement from '../common/NewsletterManagement';
@ -98,7 +98,7 @@ export default function UnsubscribePage() {
return (
<div className='gh-portal-content gh-portal-feedback with-footer'>
<CloseButton />
<div class="gh-feedback-icon gh-feedback-icon-error">
<div className="gh-feedback-icon gh-feedback-icon-error">
<WarningIcon />
</div>
<h1 className="gh-portal-main-title">{t('That didn\'t go to plan')}</h1>

View File

@ -34,7 +34,7 @@ function handleTokenUrl() {
}
}
function setup({siteUrl}) {
function setup() {
addRootDiv();
handleTokenUrl();
}

View File

@ -1,4 +1,3 @@
import React from 'react';
import App from '../App.js';
import {fireEvent, appRender, within} from '../utils/test-utils';
import {site as FixtureSite} from '../utils/test-fixtures';

View File

@ -1,4 +1,3 @@
import React from 'react';
import App from '../App.js';
import {fireEvent, appRender, within, waitFor} from '../utils/test-utils';
import {offer as FixtureOffer, site as FixtureSite} from '../utils/test-fixtures';

View File

@ -1,4 +1,3 @@
import React from 'react';
import App from '../App.js';
import {fireEvent, appRender, within} from '../utils/test-utils';
import {offer as FixtureOffer, site as FixtureSite, member as FixtureMember} from '../utils/test-fixtures';

View File

@ -12,6 +12,8 @@ export const isOfferPreviewMode = function () {
return (path === '/portal/preview/offer');
};
/* eslint-disable no-undef */
export const isDevMode = function ({customSiteUrl = ''} = {}) {
if (customSiteUrl && process.env.NODE_ENV === 'development') {
return false;
@ -23,6 +25,8 @@ export const isTestMode = function () {
return (process.env.NODE_ENV === 'test');
};
/* eslint-enable no-undef */
const modeFns = {
preview: isPreviewMode,
offerPreview: isOfferPreviewMode,

View File

@ -453,7 +453,7 @@ export function freeHasBenefitsOrDescription({site}) {
return false;
}
export function getProductBenefits({product, site = null}) {
export function getProductBenefits({product}) {
if (product?.monthlyPrice && product?.yearlyPrice) {
const productBenefits = product?.benefits || [];
const monthlyBenefits = productBenefits;

View File

@ -1,4 +1,4 @@
export const handleAuthActions = ({qsParams, action, status}) => {
export const handleAuthActions = ({action, status}) => {
if (status && ['true', 'false'].includes(status)) {
const successStatus = JSON.parse(status);
return {
@ -57,7 +57,7 @@ export default function NotificationParser({billingOnly = false} = {}) {
let notificationData = null;
if (stripeStatus) {
return handleStripeActions({qsParams, status: stripeStatus, billingOnly});
return handleStripeActions({status: stripeStatus, billingOnly});
}
if (action && successStatus && !billingOnly) {
@ -65,4 +65,4 @@ export default function NotificationParser({billingOnly = false} = {}) {
}
return notificationData;
}
}

View File

@ -1,17 +1,18 @@
// Common test setup util - Ref: https://testing-library.com/docs/react-testing-library/setup#custom-render
import React from 'react';
import {render} from '@testing-library/react';
import AppContext from '../AppContext';
import {testSite, member} from './fixtures';
const setupProvider = (context) => {
return ({children}) => {
const Provider = ({children}) => {
return (
<AppContext.Provider value={context}>
{children}
</AppContext.Provider>
);
};
Provider.displayName = 'AppContextProvider';
return Provider;
};
const customRender = (ui, {options = {}, overrideContext = {}} = {}) => {

View File

@ -2,8 +2,8 @@
module.exports = {
root: true,
extends: [
'react-app',
'plugin:ghost/browser'
'plugin:ghost/ts',
'plugin:react/recommended'
],
plugins: [
'ghost',
@ -15,6 +15,9 @@ module.exports = {
memberSyntaxSortOrder: ['none', 'all', 'single', 'multiple']
}],
// TODO: fix + remove this
'@typescript-eslint/no-explicit-any': 'warn',
// suppress errors for missing 'import React' in JSX files, as we don't need it
'react/react-in-jsx-scope': 'off',
// ignore prop-types for now

View File

@ -82,6 +82,7 @@ const FullHeightFrame: React.FC<ResizableFrameProps> = ({children, style, title}
if (!element) {
return;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const observer = new ResizeObserver(_ => onResize(element));
observer.observe(element);

View File

@ -36,6 +36,7 @@ export default class IFrame extends Component<any> {
this.forceUpdate();
if (this.props.onResize) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(new ResizeObserver(_ => this.props.onResize(this.iframeRoot)))?.observe?.(this.iframeRoot);
}
@ -57,7 +58,7 @@ export default class IFrame extends Component<any> {
}
render() {
const {children, head, title = '', style = {}, onResize, ...rest} = this.props;
const {children, head, title = '', style = {}, ...rest} = this.props;
return (
<iframe srcDoc={`<!DOCTYPE html>`} {...rest} ref={this.setNode} frameBorder="0" style={style} title={title}>
{this.iframeHead && createPortal(head, this.iframeHead)}

View File

@ -1,8 +0,0 @@
const assert = require('assert/strict');
describe('Hello world', function () {
it('Runs a test', function () {
// TODO: Write me!
assert.ok(require('../../index'));
});
});

View File

@ -38,14 +38,29 @@
"prepublishOnly": "yarn build"
},
"eslintConfig": {
"env": {
"browser": true,
"jest": true
},
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2022
},
"extends": [
"react-app",
"react-app/jest",
"plugin:ghost/browser"
"plugin:ghost/browser",
"plugin:react/recommended"
],
"plugins": [
"ghost"
]
],
"rules": {
"react/prop-types": "off"
},
"settings": {
"react": {
"version": "detect"
}
}
},
"browserslist": {
"production": [

View File

@ -21,7 +21,6 @@ test('renders Sodo Search app component', () => {
window.location.hash = '#/search';
render(<App adminUrl="http://localhost:3000" apiKey="69010382388f9de5869ad6e558" />);
// const containerElement = screen.getElementsByClassName('gh-portal-popup-container');
// eslint-disable-next-line testing-library/no-node-access
const containerElement = document.querySelector('.gh-root-frame');
expect(containerElement).toBeInTheDocument();
});

View File

@ -1,5 +1,5 @@
// Ref: https://reactjs.org/docs/context.html
const React = require('react');
import React from 'react';
const AppContext = React.createContext({
posts: [],
@ -9,6 +9,7 @@ const AppContext = React.createContext({
lastPage: '',
page: '',
pageData: {},
// eslint-disable-next-line no-unused-vars
dispatch: (_action, _data) => {},
searchIndex: null,
indexComplete: false,

View File

@ -3,9 +3,7 @@ import AppContext from '../AppContext';
import {ReactComponent as SearchIcon} from '../icons/search.svg';
import {ReactComponent as ClearIcon} from '../icons/clear.svg';
import {ReactComponent as CircleAnimated} from '../icons/circle-anim.svg';
import {useContext, useEffect, useMemo, useRef, useState} from 'react';
const React = require('react');
import React, {useContext, useEffect, useMemo, useRef, useState} from 'react';
const DEFAULT_MAX_POSTS = 10;
const STEP_MAX_POSTS = 10;

View File

@ -123,7 +123,6 @@
"ember-truth-helpers": "3.1.1",
"ember-websockets": "10.2.1",
"eslint-plugin-babel": "5.3.1",
"eslint-plugin-react": "7.32.2",
"faker": "5.5.3",
"fs-extra": "11.1.1",
"glob": "8.1.0",

View File

@ -2,5 +2,9 @@ module.exports = {
plugins: ['ghost'],
extends: [
'plugin:ghost/ts'
]
],
rules: {
// TODO: fix + remove this
'@typescript-eslint/no-explicit-any': 'warn',
}
};

View File

@ -2,5 +2,9 @@ module.exports = {
plugins: ['ghost'],
extends: [
'plugin:ghost/ts'
]
],
rules: {
// TODO: fix + remove this
'@typescript-eslint/no-explicit-any': 'warn',
}
};

View File

@ -4,9 +4,7 @@ module.exports = {
'plugin:ghost/ts'
],
rules: {
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['error'],
'no-shadow': 'off',
'@typescript-eslint/no-shadow': ['error']
// TODO: fix + remove this
'@typescript-eslint/no-explicit-any': 'warn',
}
};

View File

@ -2,5 +2,9 @@ module.exports = {
plugins: ['ghost'],
extends: [
'plugin:ghost/ts'
]
],
rules: {
// TODO: fix + remove this
'@typescript-eslint/no-explicit-any': 'warn',
}
};

View File

@ -2,5 +2,8 @@ module.exports = {
plugins: ['ghost'],
extends: [
'plugin:ghost/ts'
]
],
rules: {
'@typescript-eslint/no-explicit-any': 'warn',
}
};

View File

@ -122,8 +122,8 @@
"devDependencies": {
"concurrently": "8.2.0",
"eslint": "8.44.0",
"eslint-config-react-app": "7.0.1",
"eslint-plugin-ghost": "3.3.0",
"eslint-plugin-react": "7.33.0",
"husky": "8.0.3",
"lint-staged": "13.2.3",
"nx": "16.5.5",

517
yarn.lock
View File

@ -734,7 +734,7 @@
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730"
integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==
"@babel/core@^7.0.0", "@babel/core@^7.1.6", "@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.12.9", "@babel/core@^7.13.10", "@babel/core@^7.13.16", "@babel/core@^7.16.0", "@babel/core@^7.16.7", "@babel/core@^7.20.12", "@babel/core@^7.20.2", "@babel/core@^7.21.3", "@babel/core@^7.22.5", "@babel/core@^7.22.9", "@babel/core@^7.3.4", "@babel/core@^7.7.5":
"@babel/core@^7.0.0", "@babel/core@^7.1.6", "@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.12.9", "@babel/core@^7.13.10", "@babel/core@^7.13.16", "@babel/core@^7.16.7", "@babel/core@^7.20.12", "@babel/core@^7.20.2", "@babel/core@^7.21.3", "@babel/core@^7.22.5", "@babel/core@^7.22.9", "@babel/core@^7.3.4", "@babel/core@^7.7.5":
version "7.22.9"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.9.tgz#bd96492c68822198f33e8a256061da3cf391f58f"
integrity sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==
@ -755,7 +755,7 @@
json5 "^2.2.2"
semver "^6.3.1"
"@babel/eslint-parser@7.22.9", "@babel/eslint-parser@^7.16.3":
"@babel/eslint-parser@7.22.9":
version "7.22.9"
resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.22.9.tgz#75f8aa978d1e76c87cc6f26c1ea16ae58804d390"
integrity sha512-xdMkt39/nviO/4vpVdrEYPwXCsYIXSSAr6mC7WQsNIlGnuxKyKE7GZjalcnbSWiC4OXGNNN3UQPeHfjSC6sTDA==
@ -799,7 +799,7 @@
lru-cache "^5.1.1"
semver "^6.3.1"
"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.22.5", "@babel/helper-create-class-features-plugin@^7.22.6", "@babel/helper-create-class-features-plugin@^7.22.9", "@babel/helper-create-class-features-plugin@^7.5.5", "@babel/helper-create-class-features-plugin@^7.8.3":
"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.22.5", "@babel/helper-create-class-features-plugin@^7.22.6", "@babel/helper-create-class-features-plugin@^7.5.5", "@babel/helper-create-class-features-plugin@^7.8.3":
version "7.22.9"
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.9.tgz#c36ea240bb3348f942f08b0fbe28d6d979fab236"
integrity sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==
@ -1005,7 +1005,7 @@
"@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
"@babel/plugin-transform-optional-chaining" "^7.22.5"
"@babel/plugin-proposal-class-properties@7.18.6", "@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.16.0", "@babel/plugin-proposal-class-properties@^7.16.5", "@babel/plugin-proposal-class-properties@^7.16.7":
"@babel/plugin-proposal-class-properties@7.18.6", "@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.16.5", "@babel/plugin-proposal-class-properties@^7.16.7":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3"
integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==
@ -1013,7 +1013,7 @@
"@babel/helper-create-class-features-plugin" "^7.18.6"
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-proposal-decorators@7.22.7", "@babel/plugin-proposal-decorators@^7.13.5", "@babel/plugin-proposal-decorators@^7.16.4", "@babel/plugin-proposal-decorators@^7.16.7":
"@babel/plugin-proposal-decorators@7.22.7", "@babel/plugin-proposal-decorators@^7.13.5", "@babel/plugin-proposal-decorators@^7.16.7":
version "7.22.7"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.22.7.tgz#9b5b73c2e404f0869ef8a8a53765f8203c5467a7"
integrity sha512-omXqPF7Onq4Bb7wHxXjM3jSMSJvUUbvDvmmds7KI5n9Cq6Ln5I05I1W2nRlRof1rGdiUxJrxwe285WF96XlBXQ==
@ -1032,7 +1032,7 @@
"@babel/helper-plugin-utils" "^7.18.9"
"@babel/plugin-syntax-export-namespace-from" "^7.8.3"
"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.4.4":
"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.4.4":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1"
integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==
@ -1040,15 +1040,7 @@
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
"@babel/plugin-proposal-numeric-separator@^7.16.0":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75"
integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-syntax-numeric-separator" "^7.10.4"
"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.16.0", "@babel/plugin-proposal-optional-chaining@^7.6.0":
"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.6.0":
version "7.21.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea"
integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==
@ -1057,7 +1049,7 @@
"@babel/helper-skip-transparent-expression-wrappers" "^7.20.0"
"@babel/plugin-syntax-optional-chaining" "^7.8.3"
"@babel/plugin-proposal-private-methods@^7.16.0", "@babel/plugin-proposal-private-methods@^7.16.5":
"@babel/plugin-proposal-private-methods@^7.16.5":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea"
integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==
@ -1144,13 +1136,6 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-syntax-flow@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.22.5.tgz#163b820b9e7696ce134df3ee716d9c0c98035859"
integrity sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-import-assertions@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz#07d252e2aa0bc6125567f742cd58619cb14dce98"
@ -1186,13 +1171,6 @@
dependencies:
"@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-syntax-jsx@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918"
integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
@ -1256,13 +1234,6 @@
dependencies:
"@babel/helper-plugin-utils" "^7.19.0"
"@babel/plugin-syntax-typescript@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz#aac8d383b062c5072c647a31ef990c1d0af90272"
integrity sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-unicode-sets-regex@^7.18.6":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357"
@ -1397,14 +1368,6 @@
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-export-namespace-from" "^7.8.3"
"@babel/plugin-transform-flow-strip-types@^7.16.0":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.22.5.tgz#0bb17110c7bf5b35a60754b2f00c58302381dee2"
integrity sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-flow" "^7.22.5"
"@babel/plugin-transform-flow-strip-types@^7.21.0":
version "7.21.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.21.0.tgz#6aeca0adcb81dc627c8986e770bfaa4d9812aff5"
@ -1600,20 +1563,6 @@
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz#3c4326f9fce31c7968d6cb9debcaf32d9e279a2b"
integrity sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-transform-react-jsx-development@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz#e716b6edbef972a92165cd69d92f1255f7e73e87"
integrity sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==
dependencies:
"@babel/plugin-transform-react-jsx" "^7.22.5"
"@babel/plugin-transform-react-jsx-self@^7.18.6", "@babel/plugin-transform-react-jsx-self@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz#ca2fdc11bc20d4d46de01137318b13d04e481d8e"
@ -1628,25 +1577,6 @@
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-transform-react-jsx@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz#932c291eb6dd1153359e2a90cb5e557dcf068416"
integrity sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==
dependencies:
"@babel/helper-annotate-as-pure" "^7.22.5"
"@babel/helper-module-imports" "^7.22.5"
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-jsx" "^7.22.5"
"@babel/types" "^7.22.5"
"@babel/plugin-transform-react-pure-annotations@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz#1f58363eef6626d6fa517b95ac66fe94685e32c0"
integrity sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==
dependencies:
"@babel/helper-annotate-as-pure" "^7.22.5"
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-transform-regenerator@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.5.tgz#cd8a68b228a5f75fa01420e8cc2fc400f0fc32aa"
@ -1674,18 +1604,6 @@
babel-plugin-polyfill-regenerator "^0.4.1"
semver "^6.3.0"
"@babel/plugin-transform-runtime@^7.16.4":
version "7.22.9"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.9.tgz#a87b11e170cbbfb018e6a2bf91f5c6e533b9e027"
integrity sha512-9KjBH61AGJetCPYp/IEyLEp47SyybZb0nDRpBvmtEkm+rUIwxdlKpyNHI1TmsGkeuLclJdleQHRZ8XLBnnh8CQ==
dependencies:
"@babel/helper-module-imports" "^7.22.5"
"@babel/helper-plugin-utils" "^7.22.5"
babel-plugin-polyfill-corejs2 "^0.4.4"
babel-plugin-polyfill-corejs3 "^0.8.2"
babel-plugin-polyfill-regenerator "^0.5.1"
semver "^6.3.1"
"@babel/plugin-transform-shorthand-properties@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz#6e277654be82b5559fc4b9f58088507c24f0c624"
@ -1732,16 +1650,6 @@
"@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-syntax-typescript" "^7.20.0"
"@babel/plugin-transform-typescript@^7.22.5":
version "7.22.9"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.9.tgz#91e08ad1eb1028ecc62662a842e93ecfbf3c7234"
integrity sha512-BnVR1CpKiuD0iobHPaM1iLvcwPYN2uVFAqoLVSpEDKWuOikoCv5HbKLxclhKYUXlWkX86DoZGtqI4XhbOsyrMg==
dependencies:
"@babel/helper-annotate-as-pure" "^7.22.5"
"@babel/helper-create-class-features-plugin" "^7.22.9"
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/plugin-syntax-typescript" "^7.22.5"
"@babel/plugin-transform-typescript@~7.4.0":
version "7.4.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.4.5.tgz#ab3351ba35307b79981993536c93ff8be050ba28"
@ -1807,7 +1715,7 @@
core-js "^2.6.5"
regenerator-runtime "^0.13.4"
"@babel/preset-env@^7.10.2", "@babel/preset-env@^7.16.4", "@babel/preset-env@^7.16.5", "@babel/preset-env@^7.16.7", "@babel/preset-env@^7.22.9":
"@babel/preset-env@^7.10.2", "@babel/preset-env@^7.16.5", "@babel/preset-env@^7.16.7", "@babel/preset-env@^7.22.9":
version "7.22.9"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.22.9.tgz#57f17108eb5dfd4c5c25a44c1977eba1df310ac7"
integrity sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==
@ -1913,18 +1821,6 @@
"@babel/types" "^7.4.4"
esutils "^2.0.2"
"@babel/preset-react@^7.16.0":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.22.5.tgz#c4d6058fbf80bccad02dd8c313a9aaa67e3c3dd6"
integrity sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/helper-validator-option" "^7.22.5"
"@babel/plugin-transform-react-display-name" "^7.22.5"
"@babel/plugin-transform-react-jsx" "^7.22.5"
"@babel/plugin-transform-react-jsx-development" "^7.22.5"
"@babel/plugin-transform-react-pure-annotations" "^7.22.5"
"@babel/preset-typescript@^7.13.0":
version "7.21.5"
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.21.5.tgz#68292c884b0e26070b4d66b202072d391358395f"
@ -1936,17 +1832,6 @@
"@babel/plugin-transform-modules-commonjs" "^7.21.5"
"@babel/plugin-transform-typescript" "^7.21.3"
"@babel/preset-typescript@^7.16.0":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.22.5.tgz#16367d8b01d640e9a507577ed4ee54e0101e51c8"
integrity sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
"@babel/helper-validator-option" "^7.22.5"
"@babel/plugin-syntax-jsx" "^7.22.5"
"@babel/plugin-transform-modules-commonjs" "^7.22.5"
"@babel/plugin-transform-typescript" "^7.22.5"
"@babel/register@^7.13.16":
version "7.21.0"
resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.21.0.tgz#c97bf56c2472e063774f31d344c592ebdcefa132"
@ -1977,13 +1862,6 @@
dependencies:
regenerator-runtime "^0.13.11"
"@babel/runtime@^7.16.3", "@babel/runtime@^7.20.7":
version "7.22.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438"
integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==
dependencies:
regenerator-runtime "^0.13.11"
"@babel/template@^7.20.7", "@babel/template@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
@ -3868,11 +3746,6 @@
estree-walker "^2.0.2"
picomatch "^2.3.1"
"@rushstack/eslint-patch@^1.1.0":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz#31b9c510d8cada9683549e1dbb4284cca5001faf"
integrity sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==
"@segment/loosely-validate-event@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz#87dfc979e5b4e7b82c5f1d8b722dfd5d77644681"
@ -7103,11 +6976,6 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
"@types/json5@^0.0.29":
version "0.0.29"
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
"@types/jsonwebtoken@9.0.2", "@types/jsonwebtoken@^9", "@types/jsonwebtoken@^9.0.0":
version "9.0.2"
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#9eeb56c76dd555039be2a3972218de5bd3b8d83e"
@ -7318,7 +7186,7 @@
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
"@types/semver@^7.3.12", "@types/semver@^7.3.4", "@types/semver@^7.5.0":
"@types/semver@^7.3.4", "@types/semver@^7.5.0":
version "7.5.0"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a"
integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==
@ -7412,29 +7280,6 @@
semver "^7.5.4"
ts-api-utils "^1.0.1"
"@typescript-eslint/eslint-plugin@^5.5.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db"
integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==
dependencies:
"@eslint-community/regexpp" "^4.4.0"
"@typescript-eslint/scope-manager" "5.62.0"
"@typescript-eslint/type-utils" "5.62.0"
"@typescript-eslint/utils" "5.62.0"
debug "^4.3.4"
graphemer "^1.4.0"
ignore "^5.2.0"
natural-compare-lite "^1.4.0"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/experimental-utils@^5.0.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz#14559bf73383a308026b427a4a6129bae2146741"
integrity sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==
dependencies:
"@typescript-eslint/utils" "5.62.0"
"@typescript-eslint/parser@6.1.0":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.1.0.tgz#3135bf65dca5340d8650703eb8cb83113e156ee5"
@ -7446,24 +7291,6 @@
"@typescript-eslint/visitor-keys" "6.1.0"
debug "^4.3.4"
"@typescript-eslint/parser@^5.5.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7"
integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==
dependencies:
"@typescript-eslint/scope-manager" "5.62.0"
"@typescript-eslint/types" "5.62.0"
"@typescript-eslint/typescript-estree" "5.62.0"
debug "^4.3.4"
"@typescript-eslint/scope-manager@5.62.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c"
integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==
dependencies:
"@typescript-eslint/types" "5.62.0"
"@typescript-eslint/visitor-keys" "5.62.0"
"@typescript-eslint/scope-manager@6.1.0":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz#a6cdbe11630614f8c04867858a42dd56590796ed"
@ -7472,16 +7299,6 @@
"@typescript-eslint/types" "6.1.0"
"@typescript-eslint/visitor-keys" "6.1.0"
"@typescript-eslint/type-utils@5.62.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a"
integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==
dependencies:
"@typescript-eslint/typescript-estree" "5.62.0"
"@typescript-eslint/utils" "5.62.0"
debug "^4.3.4"
tsutils "^3.21.0"
"@typescript-eslint/type-utils@6.1.0":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.1.0.tgz#21cc6c3bc1980b03f9eb4e64580d0c5be6f08215"
@ -7492,29 +7309,11 @@
debug "^4.3.4"
ts-api-utils "^1.0.1"
"@typescript-eslint/types@5.62.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f"
integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==
"@typescript-eslint/types@6.1.0":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.1.0.tgz#2d607c62827bb416ada5c96ebfa2ef84e45a8dfa"
integrity sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==
"@typescript-eslint/typescript-estree@5.62.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b"
integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==
dependencies:
"@typescript-eslint/types" "5.62.0"
"@typescript-eslint/visitor-keys" "5.62.0"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/typescript-estree@6.1.0":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz#ea382f6482ba698d7e993a88ce5391ea7a66c33d"
@ -7528,20 +7327,6 @@
semver "^7.5.4"
ts-api-utils "^1.0.1"
"@typescript-eslint/utils@5.62.0", "@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.58.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86"
integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==
dependencies:
"@eslint-community/eslint-utils" "^4.2.0"
"@types/json-schema" "^7.0.9"
"@types/semver" "^7.3.12"
"@typescript-eslint/scope-manager" "5.62.0"
"@typescript-eslint/types" "5.62.0"
"@typescript-eslint/typescript-estree" "5.62.0"
eslint-scope "^5.1.1"
semver "^7.3.7"
"@typescript-eslint/utils@6.1.0":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.1.0.tgz#1641843792b4e3451cc692e2c73055df8b26f453"
@ -7555,14 +7340,6 @@
"@typescript-eslint/typescript-estree" "6.1.0"
semver "^7.5.4"
"@typescript-eslint/visitor-keys@5.62.0":
version "5.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e"
integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==
dependencies:
"@typescript-eslint/types" "5.62.0"
eslint-visitor-keys "^3.3.0"
"@typescript-eslint/visitor-keys@6.1.0":
version "6.1.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz#d2b84dff6b58944d3257ea03687e269a788c73be"
@ -8459,13 +8236,6 @@ aria-query@5.1.3, aria-query@^5.0.0, aria-query@^5.0.2:
dependencies:
deep-equal "^2.0.5"
aria-query@^5.1.3:
version "5.3.0"
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e"
integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==
dependencies:
dequal "^2.0.3"
arr-diff@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
@ -8542,16 +8312,6 @@ array-unique@^0.3.2:
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==
array.prototype.flat@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2"
integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.4"
es-abstract "^1.20.4"
es-shim-unscopables "^1.0.0"
array.prototype.flatmap@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183"
@ -8660,11 +8420,6 @@ assign-symbols@^1.0.0:
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==
ast-types-flow@^0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==
ast-types@0.13.3:
version "0.13.3"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.3.tgz#50da3f28d17bdbc7969a3a2d83a0e4a72ae755a7"
@ -8822,11 +8577,6 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
axe-core@^4.6.2:
version "4.7.2"
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0"
integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==
axios-retry@3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.2.0.tgz#eb48e72f90b177fde62329b2896aa8476cfb90ba"
@ -8851,13 +8601,6 @@ axios@^1.0.0, axios@^1.3.3:
form-data "^4.0.0"
proxy-from-env "^1.1.0"
axobject-query@^3.1.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a"
integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==
dependencies:
dequal "^2.0.3"
babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
@ -9510,11 +9253,6 @@ babel-plugin-transform-react-jsx@6.24.1:
babel-plugin-syntax-jsx "^6.8.0"
babel-runtime "^6.22.0"
babel-plugin-transform-react-remove-prop-types@^0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a"
integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==
babel-plugin-transform-regenerator@^6.22.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
@ -9593,28 +9331,6 @@ babel-preset-env@^1.7.0:
invariant "^2.2.2"
semver "^5.3.0"
babel-preset-react-app@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz#ed6005a20a24f2c88521809fa9aea99903751584"
integrity sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==
dependencies:
"@babel/core" "^7.16.0"
"@babel/plugin-proposal-class-properties" "^7.16.0"
"@babel/plugin-proposal-decorators" "^7.16.4"
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.0"
"@babel/plugin-proposal-numeric-separator" "^7.16.0"
"@babel/plugin-proposal-optional-chaining" "^7.16.0"
"@babel/plugin-proposal-private-methods" "^7.16.0"
"@babel/plugin-transform-flow-strip-types" "^7.16.0"
"@babel/plugin-transform-react-display-name" "^7.16.0"
"@babel/plugin-transform-runtime" "^7.16.4"
"@babel/preset-env" "^7.16.4"
"@babel/preset-react" "^7.16.0"
"@babel/preset-typescript" "^7.16.0"
"@babel/runtime" "^7.16.3"
babel-plugin-macros "^3.1.0"
babel-plugin-transform-react-remove-prop-types "^0.4.24"
babel-register@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
@ -12023,11 +11739,6 @@ configstore@^5.0.1:
write-file-atomic "^3.0.0"
xdg-basedir "^4.0.0"
confusing-browser-globals@^1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81"
integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==
connect-slashes@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/connect-slashes/-/connect-slashes-1.4.0.tgz#fe884e9d130e9bd0a40d8ee502c1dfa269f94373"
@ -12741,11 +12452,6 @@ dag-map@^2.0.2:
resolved "https://registry.yarnpkg.com/dag-map/-/dag-map-2.0.2.tgz#9714b472de82a1843de2fba9b6876938cab44c68"
integrity sha512-xnsprIzYuDeiyu5zSKwilV/ajRHxnoMlAhEREfyfTgTSViMVY2fGP1ZcHJbtwup26oCkofySU/m6oKJ3HrkW7w==
damerau-levenshtein@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
dash-get@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/dash-get/-/dash-get-1.0.2.tgz#4c9e9ad5ef04c4bf9d3c9a451f6f7997298dcc7c"
@ -13058,7 +12764,7 @@ dependency-graph@^0.11.0:
resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27"
integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==
dequal@^2.0.2, dequal@^2.0.3:
dequal@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
@ -15337,47 +15043,11 @@ escodegen@^2.0.0:
optionalDependencies:
source-map "~0.6.1"
eslint-config-react-app@7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz#73ba3929978001c5c86274c017ea57eb5fa644b4"
integrity sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==
dependencies:
"@babel/core" "^7.16.0"
"@babel/eslint-parser" "^7.16.3"
"@rushstack/eslint-patch" "^1.1.0"
"@typescript-eslint/eslint-plugin" "^5.5.0"
"@typescript-eslint/parser" "^5.5.0"
babel-preset-react-app "^10.0.1"
confusing-browser-globals "^1.0.11"
eslint-plugin-flowtype "^8.0.3"
eslint-plugin-import "^2.25.3"
eslint-plugin-jest "^25.3.0"
eslint-plugin-jsx-a11y "^6.5.1"
eslint-plugin-react "^7.27.1"
eslint-plugin-react-hooks "^4.3.0"
eslint-plugin-testing-library "^5.0.1"
eslint-formatter-kakoune@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/eslint-formatter-kakoune/-/eslint-formatter-kakoune-1.0.0.tgz#a95cc4fe1fbc06b84e0f2397e83f5f0b68340125"
integrity sha512-Uk/TVLt6Nf6Xoz7C1iYuZjOSdJxe5aaauGRke8JhKeJwD66Y61/pY2FjtLP04Ooq9PwV34bzrkKkU2UZ5FtDRA==
eslint-import-resolver-node@^0.3.7:
version "0.3.7"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7"
integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==
dependencies:
debug "^3.2.7"
is-core-module "^2.11.0"
resolve "^1.22.1"
eslint-module-utils@^2.7.4:
version "2.8.0"
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49"
integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==
dependencies:
debug "^3.2.7"
eslint-plugin-babel@5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.3.1.tgz#75a2413ffbf17e7be57458301c60291f2cfbf560"
@ -15421,14 +15091,6 @@ eslint-plugin-filenames@allouis/eslint-plugin-filenames#15dc354f4e3d155fc2d6ae08
lodash.snakecase "4.1.1"
lodash.upperfirst "4.3.1"
eslint-plugin-flowtype@^8.0.3:
version "8.0.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz#e1557e37118f24734aa3122e7536a038d34a4912"
integrity sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==
dependencies:
lodash "^4.17.21"
string-natural-compare "^3.0.1"
eslint-plugin-ghost@3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-ghost/-/eslint-plugin-ghost-3.3.0.tgz#576fcbb308e94b5e601ce8806ec63d354c5c114d"
@ -15453,63 +15115,6 @@ eslint-plugin-i18next@6.0.3:
lodash "^4.17.21"
requireindex "~1.1.0"
eslint-plugin-import@^2.25.3:
version "2.27.5"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65"
integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==
dependencies:
array-includes "^3.1.6"
array.prototype.flat "^1.3.1"
array.prototype.flatmap "^1.3.1"
debug "^3.2.7"
doctrine "^2.1.0"
eslint-import-resolver-node "^0.3.7"
eslint-module-utils "^2.7.4"
has "^1.0.3"
is-core-module "^2.11.0"
is-glob "^4.0.3"
minimatch "^3.1.2"
object.values "^1.1.6"
resolve "^1.22.1"
semver "^6.3.0"
tsconfig-paths "^3.14.1"
eslint-plugin-jest@27.2.3:
version "27.2.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz#6f8a4bb2ca82c0c5d481d1b3be256ab001f5a3ec"
integrity sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==
dependencies:
"@typescript-eslint/utils" "^5.10.0"
eslint-plugin-jest@^25.3.0:
version "25.7.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz#ff4ac97520b53a96187bad9c9814e7d00de09a6a"
integrity sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==
dependencies:
"@typescript-eslint/experimental-utils" "^5.0.0"
eslint-plugin-jsx-a11y@^6.5.1:
version "6.7.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz#fca5e02d115f48c9a597a6894d5bcec2f7a76976"
integrity sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==
dependencies:
"@babel/runtime" "^7.20.7"
aria-query "^5.1.3"
array-includes "^3.1.6"
array.prototype.flatmap "^1.3.1"
ast-types-flow "^0.0.7"
axe-core "^4.6.2"
axobject-query "^3.1.1"
damerau-levenshtein "^1.0.8"
emoji-regex "^9.2.2"
has "^1.0.3"
jsx-ast-utils "^3.3.3"
language-tags "=1.0.5"
minimatch "^3.1.2"
object.entries "^1.1.6"
object.fromentries "^2.0.6"
semver "^6.3.0"
eslint-plugin-mocha@7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-7.0.1.tgz#b2e9e8ebef7836f999a83f8bab25d0e0c05f0d28"
@ -15532,7 +15137,7 @@ eslint-plugin-n@16.0.1:
resolve "^1.22.2"
semver "^7.5.3"
eslint-plugin-react-hooks@4.6.0, eslint-plugin-react-hooks@^4.3.0:
eslint-plugin-react-hooks@4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
@ -15542,28 +15147,7 @@ eslint-plugin-react-refresh@0.4.3:
resolved "https://registry.yarnpkg.com/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.3.tgz#59dae8c00a119f06ea16b1d3e6891df3775947c7"
integrity sha512-Hh0wv8bUNY877+sI0BlCUlsS0TYYQqvzEwJsJJPM2WF4RnTStSnSR3zdJYa2nPOJgg3UghXi54lVyMSmpCalzA==
eslint-plugin-react@7.32.2:
version "7.32.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz#e71f21c7c265ebce01bcbc9d0955170c55571f10"
integrity sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==
dependencies:
array-includes "^3.1.6"
array.prototype.flatmap "^1.3.1"
array.prototype.tosorted "^1.1.1"
doctrine "^2.1.0"
estraverse "^5.3.0"
jsx-ast-utils "^2.4.1 || ^3.0.0"
minimatch "^3.1.2"
object.entries "^1.1.6"
object.fromentries "^2.0.6"
object.hasown "^1.1.2"
object.values "^1.1.6"
prop-types "^15.8.1"
resolve "^2.0.0-next.4"
semver "^6.3.0"
string.prototype.matchall "^4.0.8"
eslint-plugin-react@7.33.0, eslint-plugin-react@^7.27.1:
eslint-plugin-react@7.33.0:
version "7.33.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.0.tgz#6c356fb0862fec2cd1b04426c669ea746e9b6eb3"
integrity sha512-qewL/8P34WkY8jAqdQxsiL82pDUeT7nhs8IsuXgfgnsEloKCT4miAV9N9kGtx7/KM9NH/NCGUE7Edt9iGxLXFw==
@ -15597,13 +15181,6 @@ eslint-plugin-tailwindcss@3.13.0:
fast-glob "^3.2.5"
postcss "^8.4.4"
eslint-plugin-testing-library@^5.0.1:
version "5.11.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.0.tgz#0bad7668e216e20dd12f8c3652ca353009163121"
integrity sha512-ELY7Gefo+61OfXKlQeXNIDVVLPcvKTeiQOoMZG9TeuWa7Ln4dUNRv8JdRWBQI9Mbb427XGlVB1aa1QPZxBJM8Q==
dependencies:
"@typescript-eslint/utils" "^5.58.0"
eslint-plugin-unicorn@42.0.0:
version "42.0.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-42.0.0.tgz#47d60c00c263ad743403b052db689e39acbacff1"
@ -18736,13 +18313,6 @@ is-color-stop@^1.0.0:
rgb-regex "^1.0.1"
rgba-regex "^1.0.0"
is-core-module@^2.11.0, is-core-module@^2.12.1:
version "2.12.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd"
integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==
dependencies:
has "^1.0.3"
is-core-module@^2.12.0, is-core-module@^2.5.0, is-core-module@^2.9.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4"
@ -18750,6 +18320,13 @@ is-core-module@^2.12.0, is-core-module@^2.5.0, is-core-module@^2.9.0:
dependencies:
has "^1.0.3"
is-core-module@^2.12.1:
version "2.12.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd"
integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==
dependencies:
has "^1.0.3"
is-data-descriptor@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@ -19907,7 +19484,7 @@ json5@^0.5.1:
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==
json5@^1.0.1, json5@^1.0.2:
json5@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==
@ -20014,16 +19591,6 @@ jsprim@^1.2.2:
array-includes "^3.1.5"
object.assign "^4.1.3"
jsx-ast-utils@^3.3.3:
version "3.3.4"
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.4.tgz#b896535fed5b867650acce5a9bd4135ffc7b3bf9"
integrity sha512-fX2TVdCViod6HwKEtSWGHs57oFhVfCMwieb9PuRDgjDPh5XeqJiHFFFJCHxU5cnTc3Bu/GRL+kPiFmw8XWOfKw==
dependencies:
array-includes "^3.1.6"
array.prototype.flat "^1.3.1"
object.assign "^4.1.4"
object.values "^1.1.6"
juice@9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/juice/-/juice-9.1.0.tgz#3ef8a12392d44c1cd996022aa977581049a65050"
@ -20225,18 +19792,11 @@ known-css-properties@^0.27.0:
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.27.0.tgz#82a9358dda5fe7f7bd12b5e7142c0a205393c0c5"
integrity sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==
language-subtag-registry@^0.3.20, language-subtag-registry@~0.3.2:
language-subtag-registry@^0.3.20:
version "0.3.22"
resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d"
integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==
language-tags@=1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a"
integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==
dependencies:
language-subtag-registry "~0.3.2"
language-tags@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.8.tgz#042b4bdb0d4e771a9f8cc2fdc9bb26a52a367312"
@ -26261,15 +25821,6 @@ resolve@1.22.3, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
resolve@^1.22.1:
version "1.22.2"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
dependencies:
is-core-module "^2.11.0"
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
resolve@^2.0.0-next.4:
version "2.0.0-next.4"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660"
@ -27641,11 +27192,6 @@ string-length@^1.0.1:
dependencies:
strip-ansi "^3.0.0"
string-natural-compare@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
string-range@~1.2, string-range@~1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/string-range/-/string-range-1.2.2.tgz#a893ed347e72299bc83befbbf2a692a8d239d5dd"
@ -28831,16 +28377,6 @@ ts-node@10.9.1:
v8-compile-cache-lib "^3.0.1"
yn "3.1.1"
tsconfig-paths@^3.14.1:
version "3.14.2"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088"
integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==
dependencies:
"@types/json5" "^0.0.29"
json5 "^1.0.2"
minimist "^1.2.6"
strip-bom "^3.0.0"
tsconfig-paths@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.1.2.tgz#4819f861eef82e6da52fb4af1e8c930a39ed979a"
@ -28855,7 +28391,7 @@ tslib@2.1.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
tslib@^1.11.1, tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0:
tslib@^1.11.1, tslib@^1.13.0, tslib@^1.9.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
@ -28870,13 +28406,6 @@ tsscmp@1.0.6:
resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb"
integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==
tsutils@^3.21.0:
version "3.21.0"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
dependencies:
tslib "^1.8.1"
tty-browserify@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"