mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-04-22 13:29:27 +00:00
Correct use selector (#515)
This commit is contained in:
parent
971421925a
commit
a41d3d1515
20 changed files with 74 additions and 205 deletions
package.jsonyarn.lock
src/components
common
editor/app-bar
history-page
intro-page/cover-buttons
landing-layout
footer
navigation
login-page
markdown-renderer
profile-page
register-page
|
@ -8,7 +8,6 @@
|
|||
"@testing-library/react": "10.4.9",
|
||||
"@testing-library/user-event": "12.1.3",
|
||||
"@types/codemirror": "0.0.97",
|
||||
"@types/deep-equal": "1.0.1",
|
||||
"@types/emoji-mart": "3.0.2",
|
||||
"@types/highlight.js": "9.12.4",
|
||||
"@types/jest": "26.0.10",
|
||||
|
@ -31,7 +30,6 @@
|
|||
"@typescript-eslint/parser": "3.10.1",
|
||||
"bootstrap": "4.5.2",
|
||||
"codemirror": "5.57.0",
|
||||
"deep-equal": "2.0.3",
|
||||
"emoji-mart": "3.0.0",
|
||||
"eslint-config-react-app": "5.2.1",
|
||||
"eslint-config-standard": "14.1.1",
|
||||
|
@ -41,6 +39,7 @@
|
|||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "4.2.1",
|
||||
"eslint-plugin-standard": "4.0.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"flowchart.js": "1.14.0",
|
||||
"fork-awesome": "1.1.7",
|
||||
"github-markdown-css": "4.0.0",
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
|
||||
import equal from 'fast-deep-equal'
|
||||
import React from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { ApplicationState } from '../../../redux'
|
||||
|
@ -9,7 +11,7 @@ export interface BrandingProps {
|
|||
}
|
||||
|
||||
export const Branding: React.FC<BrandingProps> = ({ inline = false }) => {
|
||||
const branding = useSelector((state: ApplicationState) => state.config.branding)
|
||||
const branding = useSelector((state: ApplicationState) => state.config.branding, equal)
|
||||
const showBranding = !!branding.name || !!branding.logo
|
||||
|
||||
return (
|
||||
|
|
|
@ -7,11 +7,11 @@ export interface DocumentTitleProps {
|
|||
}
|
||||
|
||||
export const DocumentTitle: React.FC<DocumentTitleProps> = ({ title }) => {
|
||||
const branding = useSelector((state: ApplicationState) => state.config.branding)
|
||||
const brandingName = useSelector((state: ApplicationState) => state.config.branding.name)
|
||||
|
||||
useEffect(() => {
|
||||
document.title = `${title ? title + ' - ' : ''}CodiMD ${branding.name ? ` @ ${branding.name}` : ''}`
|
||||
}, [branding, title])
|
||||
document.title = `${title ? title + ' - ' : ''}CodiMD ${brandingName ? ` @ ${brandingName}` : ''}`
|
||||
}, [brandingName, title])
|
||||
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import equal from 'fast-deep-equal'
|
||||
import React from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
@ -8,7 +9,7 @@ import { ForkAwesomeIcon } from '../fork-awesome/fork-awesome-icon'
|
|||
import { ShowIf } from '../show-if/show-if'
|
||||
|
||||
export const MotdBanner: React.FC = () => {
|
||||
const bannerState = useSelector((state: ApplicationState) => state.banner)
|
||||
const bannerState = useSelector((state: ApplicationState) => state.banner, equal)
|
||||
|
||||
const dismissBanner = () => {
|
||||
setBanner({ ...bannerState, show: false })
|
||||
|
|
|
@ -19,7 +19,7 @@ import { NavbarBranding } from './navbar-branding'
|
|||
export const AppBar: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const { id } = useParams<EditorPathParams>()
|
||||
const user = useSelector((state: ApplicationState) => state.user)
|
||||
const userExists = useSelector((state: ApplicationState) => !!state.user)
|
||||
|
||||
return (
|
||||
<Navbar bg={'light'}>
|
||||
|
@ -39,10 +39,10 @@ export const AppBar: React.FC = () => {
|
|||
<Button className="mx-2" size="sm" variant="primary">
|
||||
<ForkAwesomeIcon icon="plus"/> <Trans i18nKey="editor.documentBar.new"/>
|
||||
</Button>
|
||||
<ShowIf condition={!user}>
|
||||
<ShowIf condition={!userExists}>
|
||||
<SignInButton size={'sm'} />
|
||||
</ShowIf>
|
||||
<ShowIf condition={!!user}>
|
||||
<ShowIf condition={userExists}>
|
||||
<UserDropdown />
|
||||
</ShowIf>
|
||||
</Nav>
|
||||
|
|
|
@ -14,12 +14,12 @@ export enum EditorMode {
|
|||
|
||||
export const EditorViewMode: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const editorConfig = useSelector((state: ApplicationState) => state.editorConfig)
|
||||
const editorMode = useSelector((state: ApplicationState) => state.editorConfig.editorMode)
|
||||
return (
|
||||
<ToggleButtonGroup
|
||||
type="radio"
|
||||
name="options"
|
||||
value={editorConfig.editorMode}
|
||||
value={editorMode}
|
||||
onChange={(value: EditorMode) => {
|
||||
setEditorMode(value)
|
||||
}}>
|
||||
|
|
|
@ -5,6 +5,7 @@ import { useSelector } from 'react-redux'
|
|||
import { deleteHistory, deleteHistoryEntry, getHistory, setHistory, updateHistoryEntry } from '../../api/history'
|
||||
import { deleteNote } from '../../api/notes'
|
||||
import { ApplicationState } from '../../redux'
|
||||
|
||||
import {
|
||||
collectEntries,
|
||||
downloadHistory,
|
||||
|
@ -46,7 +47,7 @@ export const HistoryPage: React.FC = () => {
|
|||
const [localHistoryEntries, setLocalHistoryEntries] = useState<HistoryEntry[]>(loadHistoryFromLocalStore)
|
||||
const [remoteHistoryEntries, setRemoteHistoryEntries] = useState<HistoryEntry[]>([])
|
||||
const [toolbarState, setToolbarState] = useState<HistoryToolbarState>(toolbarInitState)
|
||||
const user = useSelector((state: ApplicationState) => state.user)
|
||||
const userExists = useSelector((state: ApplicationState) => !!state.user)
|
||||
const [error, setError] = useState('')
|
||||
|
||||
const historyWrite = useCallback((entries: HistoryEntry[]) => {
|
||||
|
@ -61,24 +62,24 @@ export const HistoryPage: React.FC = () => {
|
|||
}, [historyWrite, localHistoryEntries])
|
||||
|
||||
const importHistory = useCallback((entries: HistoryEntry[]): void => {
|
||||
if (user) {
|
||||
if (userExists) {
|
||||
setHistory(entries)
|
||||
.then(() => setRemoteHistoryEntries(entries))
|
||||
.catch(() => setError('setHistory'))
|
||||
} else {
|
||||
setLocalHistoryEntries(entries)
|
||||
}
|
||||
}, [user])
|
||||
}, [userExists])
|
||||
|
||||
const refreshHistory = useCallback(() => {
|
||||
const localHistory = loadHistoryFromLocalStore()
|
||||
setLocalHistoryEntries(localHistory)
|
||||
if (user) {
|
||||
if (userExists) {
|
||||
getHistory()
|
||||
.then((remoteHistory) => setRemoteHistoryEntries(remoteHistory))
|
||||
.catch(() => setError('getHistory'))
|
||||
}
|
||||
}, [user])
|
||||
}, [userExists])
|
||||
|
||||
useEffect(() => {
|
||||
refreshHistory()
|
||||
|
@ -94,17 +95,17 @@ export const HistoryPage: React.FC = () => {
|
|||
|
||||
const clearHistory = useCallback(() => {
|
||||
setLocalHistoryEntries([])
|
||||
if (user) {
|
||||
if (userExists) {
|
||||
deleteHistory()
|
||||
.then(() => setRemoteHistoryEntries([]))
|
||||
.catch(() => setError('deleteHistory'))
|
||||
}
|
||||
historyWrite([])
|
||||
}, [historyWrite, user])
|
||||
}, [historyWrite, userExists])
|
||||
|
||||
const uploadAll = useCallback((): void => {
|
||||
const newHistory = mergeEntryArrays(localHistoryEntries, remoteHistoryEntries)
|
||||
if (user) {
|
||||
if (userExists) {
|
||||
setHistory(newHistory)
|
||||
.then(() => {
|
||||
setRemoteHistoryEntries(newHistory)
|
||||
|
@ -113,7 +114,7 @@ export const HistoryPage: React.FC = () => {
|
|||
})
|
||||
.catch(() => setError('setHistory'))
|
||||
}
|
||||
}, [historyWrite, localHistoryEntries, remoteHistoryEntries, user])
|
||||
}, [historyWrite, localHistoryEntries, remoteHistoryEntries, userExists])
|
||||
|
||||
const removeFromHistoryClick = useCallback((entryId: string, location: HistoryEntryOrigin): void => {
|
||||
if (location === HistoryEntryOrigin.LOCAL) {
|
||||
|
@ -126,14 +127,14 @@ export const HistoryPage: React.FC = () => {
|
|||
}, [])
|
||||
|
||||
const deleteNoteClick = useCallback((entryId: string, location: HistoryEntryOrigin): void => {
|
||||
if (user) {
|
||||
if (userExists) {
|
||||
deleteNote(entryId)
|
||||
.then(() => {
|
||||
removeFromHistoryClick(entryId, location)
|
||||
})
|
||||
.catch(() => setError('deleteNote'))
|
||||
}
|
||||
}, [user, removeFromHistoryClick])
|
||||
}, [userExists, removeFromHistoryClick])
|
||||
|
||||
const pinClick = useCallback((entryId: string, location: HistoryEntryOrigin): void => {
|
||||
if (location === HistoryEntryOrigin.LOCAL) {
|
||||
|
|
|
@ -49,7 +49,7 @@ export const initState: HistoryToolbarState = {
|
|||
export const HistoryToolbar: React.FC<HistoryToolbarProps> = ({ onSettingsChange, tags, onClearHistory, onRefreshHistory, onExportHistory, onImportHistory, onUploadAll }) => {
|
||||
const [t] = useTranslation()
|
||||
const [state, setState] = useState<HistoryToolbarState>(initState)
|
||||
const user = useSelector((state: ApplicationState) => state.user)
|
||||
const userExists = useSelector((state: ApplicationState) => !!state.user)
|
||||
|
||||
const titleSortChanged = (direction: SortModeEnum) => {
|
||||
setState(prevState => ({
|
||||
|
@ -118,7 +118,7 @@ export const HistoryToolbar: React.FC<HistoryToolbarProps> = ({ onSettingsChange
|
|||
<ForkAwesomeIcon icon='refresh'/>
|
||||
</Button>
|
||||
</InputGroup>
|
||||
<ShowIf condition={!!user}>
|
||||
<ShowIf condition={userExists}>
|
||||
<InputGroup className={'mr-1 mb-1'}>
|
||||
<Button variant={'light'} title={t('landing.history.toolbar.uploadAll')} onClick={onUploadAll}>
|
||||
<ForkAwesomeIcon icon='cloud-upload'/>
|
||||
|
|
|
@ -10,10 +10,10 @@ import { SignInButton } from '../../landing-layout/navigation/sign-in-button'
|
|||
|
||||
export const CoverButtons: React.FC = () => {
|
||||
useTranslation()
|
||||
const user = useSelector((state: ApplicationState) => state.user)
|
||||
const authProviders = useSelector((state: ApplicationState) => state.config.authProviders)
|
||||
const userExists = useSelector((state: ApplicationState) => !!state.user)
|
||||
const anyAuthProviderActivated = useSelector((state: ApplicationState) => Object.values(state.config.authProviders).includes(true))
|
||||
|
||||
if (user) {
|
||||
if (userExists) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ export const CoverButtons: React.FC = () => {
|
|||
variant="success"
|
||||
size="lg"
|
||||
/>
|
||||
<ShowIf condition={Object.values(authProviders).includes(true)}>
|
||||
<ShowIf condition={anyAuthProviderActivated}>
|
||||
<span className="m-2">
|
||||
<Trans i18nKey="common.or"/>
|
||||
</span>
|
||||
|
|
|
@ -10,7 +10,7 @@ import { VersionInfo } from './version-info'
|
|||
export const PoweredByLinks: React.FC = () => {
|
||||
useTranslation()
|
||||
|
||||
const config = useSelector((state: ApplicationState) => state.config)
|
||||
const specialLinks = useSelector((state: ApplicationState) => Object.entries(state.config.specialLinks) as [string, string][])
|
||||
|
||||
return (
|
||||
<p>
|
||||
|
@ -20,7 +20,7 @@ export const PoweredByLinks: React.FC = () => {
|
|||
|
|
||||
<TranslatedInternalLink href='/n/release-notes' i18nKey='landing.footer.releases'/>
|
||||
{
|
||||
Object.entries({ ...config.specialLinks }).map(([i18nKey, href]) =>
|
||||
specialLinks.map(([i18nKey, href]) =>
|
||||
<Fragment key={i18nKey}>
|
||||
|
|
||||
<TranslatedExternalLink href={href} i18nKey={'landing.footer.' + i18nKey}/>
|
||||
|
|
|
@ -8,6 +8,7 @@ import frontendVersion from '../../../version.json'
|
|||
import { TranslatedExternalLink } from '../../common/links/translated-external-link'
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import { CopyableField } from '../../common/copyable-field/copyable-field'
|
||||
import equal from 'fast-deep-equal'
|
||||
|
||||
export const VersionInfo: React.FC = () => {
|
||||
const [show, setShow] = useState(false)
|
||||
|
@ -17,7 +18,7 @@ export const VersionInfo: React.FC = () => {
|
|||
|
||||
const { t } = useTranslation()
|
||||
|
||||
const serverVersion = useSelector((state: ApplicationState) => state.config.version)
|
||||
const serverVersion = useSelector((state: ApplicationState) => state.config.version, equal)
|
||||
|
||||
const column = (title: string, version: string, sourceCodeLink: string, issueTrackerLink: string) => (
|
||||
<Col md={6} className={'flex-column'}>
|
||||
|
|
|
@ -12,7 +12,7 @@ import './header-bar.scss'
|
|||
|
||||
const HeaderBar: React.FC = () => {
|
||||
useTranslation()
|
||||
const user = useSelector((state: ApplicationState) => state.user)
|
||||
const userExists = useSelector((state: ApplicationState) => !!state.user)
|
||||
|
||||
return (
|
||||
<Navbar className="justify-content-between">
|
||||
|
@ -25,7 +25,7 @@ const HeaderBar: React.FC = () => {
|
|||
</HeaderNavLink>
|
||||
</div>
|
||||
<div className="d-inline-flex">
|
||||
{!user
|
||||
{!userExists
|
||||
? <Fragment>
|
||||
<span className={'mx-1 d-flex'}>
|
||||
<NewGuestNoteButton/>
|
||||
|
|
|
@ -13,9 +13,9 @@ type SignInButtonProps = {
|
|||
|
||||
export const SignInButton: React.FC<SignInButtonProps> = ({ variant, ...props }) => {
|
||||
const { t } = useTranslation()
|
||||
const authProviders = useSelector((state: ApplicationState) => state.config.authProviders)
|
||||
const anyAuthProviderActive = useSelector((state: ApplicationState) => Object.values(state.config.authProviders).includes(true))
|
||||
return (
|
||||
<ShowIf condition={Object.values(authProviders).includes(true)}>
|
||||
<ShowIf condition={anyAuthProviderActive}>
|
||||
<LinkContainer to="/login" title={t('login.signIn')}>
|
||||
<Button
|
||||
variant={variant || 'success'}
|
||||
|
|
|
@ -7,10 +7,11 @@ import { ApplicationState } from '../../../redux'
|
|||
import { clearUser } from '../../../redux/user/methods'
|
||||
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
|
||||
import { UserAvatar } from '../../common/user-avatar/user-avatar'
|
||||
import equal from 'fast-deep-equal'
|
||||
|
||||
export const UserDropdown: React.FC = () => {
|
||||
useTranslation()
|
||||
const user = useSelector((state: ApplicationState) => state.user)
|
||||
const user = useSelector((state: ApplicationState) => state.user, equal)
|
||||
|
||||
if (!user) {
|
||||
return null
|
||||
|
|
|
@ -9,12 +9,13 @@ import { ViaInternal } from './auth/via-internal'
|
|||
import { ViaLdap } from './auth/via-ldap'
|
||||
import { OneClickType, ViaOneClick } from './auth/via-one-click'
|
||||
import { ViaOpenId } from './auth/via-openid'
|
||||
|
||||
import equal from 'fast-deep-equal'
|
||||
export const LoginPage: React.FC = () => {
|
||||
useTranslation()
|
||||
const authProviders = useSelector((state: ApplicationState) => state.config.authProviders)
|
||||
const customAuthNames = useSelector((state: ApplicationState) => state.config.customAuthNames)
|
||||
const userLoginState = useSelector((state: ApplicationState) => state.user)
|
||||
const authProviders = useSelector((state: ApplicationState) => state.config.authProviders, equal)
|
||||
const customSamlAuthName = useSelector((state: ApplicationState) => state.config.customAuthNames.saml)
|
||||
const customOauthAuthName = useSelector((state: ApplicationState) => state.config.customAuthNames.oauth2)
|
||||
const userLoggedIn = useSelector((state: ApplicationState) => !!state.user)
|
||||
|
||||
const oneClickProviders = [authProviders.dropbox, authProviders.facebook, authProviders.github, authProviders.gitlab,
|
||||
authProviders.google, authProviders.oauth2, authProviders.saml, authProviders.twitter]
|
||||
|
@ -22,15 +23,15 @@ export const LoginPage: React.FC = () => {
|
|||
const oneClickCustomName: (type: OneClickType) => string | undefined = (type) => {
|
||||
switch (type) {
|
||||
case OneClickType.SAML:
|
||||
return customAuthNames.saml
|
||||
return customSamlAuthName
|
||||
case OneClickType.OAUTH2:
|
||||
return customAuthNames.oauth2
|
||||
return customOauthAuthName
|
||||
default:
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
if (userLoginState) {
|
||||
if (userLoggedIn) {
|
||||
// TODO Redirect to previous page?
|
||||
return (
|
||||
<Redirect to='/history'/>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import equal from 'deep-equal'
|
||||
import equal from 'fast-deep-equal'
|
||||
import { DomElement } from 'domhandler'
|
||||
import emojiData from 'emoji-mart/data/twitter.json'
|
||||
import { Data } from 'emoji-mart/dist-es/utils/data'
|
||||
|
|
|
@ -10,9 +10,9 @@ import { ProfileChangePassword } from './settings/profile-change-password'
|
|||
import { ProfileDisplayName } from './settings/profile-display-name'
|
||||
|
||||
export const ProfilePage: React.FC = () => {
|
||||
const user = useSelector((state: ApplicationState) => state.user)
|
||||
const userProvider = useSelector((state: ApplicationState) => state.user?.provider)
|
||||
|
||||
if (!user) {
|
||||
if (!userProvider) {
|
||||
return (
|
||||
<Redirect to={'/login'}/>
|
||||
)
|
||||
|
@ -23,7 +23,7 @@ export const ProfilePage: React.FC = () => {
|
|||
<Row className="h-100 flex justify-content-center">
|
||||
<Col lg={6}>
|
||||
<ProfileDisplayName/>
|
||||
<ShowIf condition={user.provider === LoginProvider.INTERNAL}>
|
||||
<ShowIf condition={userProvider === LoginProvider.INTERNAL}>
|
||||
<ProfileChangePassword/>
|
||||
</ShowIf>
|
||||
<ProfileAccountManagement/>
|
||||
|
|
|
@ -9,18 +9,18 @@ import { getAndSetUser } from '../../login-page/auth/utils'
|
|||
export const ProfileDisplayName: React.FC = () => {
|
||||
const regexInvalidDisplayName = /^\s*$/
|
||||
const { t } = useTranslation()
|
||||
const user = useSelector((state: ApplicationState) => state.user)
|
||||
const userName = useSelector((state: ApplicationState) => state.user?.name)
|
||||
const [submittable, setSubmittable] = useState(false)
|
||||
const [error, setError] = useState(false)
|
||||
const [displayName, setDisplayName] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
setDisplayName(user.name)
|
||||
if (userName !== undefined) {
|
||||
setDisplayName(userName)
|
||||
}
|
||||
}, [user])
|
||||
}, [userName])
|
||||
|
||||
if (!user) {
|
||||
if (!userName) {
|
||||
return <Alert variant={'danger'}>User not logged in</Alert>
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,9 @@ export enum RegisterError {
|
|||
|
||||
export const RegisterPage: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const config = useSelector((state: ApplicationState) => state.config)
|
||||
const user = useSelector((state: ApplicationState) => state.user)
|
||||
const allowRegister = useSelector((state: ApplicationState) => state.config.allowRegister)
|
||||
const specialLinks = useSelector((state: ApplicationState) => state.config.specialLinks)
|
||||
const userExists = useSelector((state: ApplicationState) => !!state.user)
|
||||
|
||||
const [username, setUsername] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
|
@ -40,13 +41,13 @@ export const RegisterPage: React.FC = () => {
|
|||
setReady(username !== '' && password !== '' && password.length >= 8 && password === passwordAgain)
|
||||
}, [username, password, passwordAgain])
|
||||
|
||||
if (!config.allowRegister) {
|
||||
if (!allowRegister) {
|
||||
return (
|
||||
<Redirect to={'/login'}/>
|
||||
)
|
||||
}
|
||||
|
||||
if (user) {
|
||||
if (userExists) {
|
||||
return (
|
||||
<Redirect to={'/intro'}/>
|
||||
)
|
||||
|
@ -105,17 +106,17 @@ export const RegisterPage: React.FC = () => {
|
|||
required
|
||||
/>
|
||||
</Form.Group>
|
||||
<ShowIf condition={!!config.specialLinks?.termsOfUse || !!config.specialLinks?.privacy}>
|
||||
<ShowIf condition={!!specialLinks?.termsOfUse || !!specialLinks?.privacy}>
|
||||
<Trans i18nKey='login.register.infoTermsPrivacy'/>
|
||||
<ul>
|
||||
<ShowIf condition={!!config.specialLinks?.termsOfUse}>
|
||||
<ShowIf condition={!!specialLinks?.termsOfUse}>
|
||||
<li>
|
||||
<TranslatedExternalLink i18nKey='landing.footer.termsOfUse' href={config.specialLinks.termsOfUse}/>
|
||||
<TranslatedExternalLink i18nKey='landing.footer.termsOfUse' href={specialLinks.termsOfUse}/>
|
||||
</li>
|
||||
</ShowIf>
|
||||
<ShowIf condition={!!config.specialLinks?.privacy}>
|
||||
<ShowIf condition={!!specialLinks?.privacy}>
|
||||
<li>
|
||||
<TranslatedExternalLink i18nKey='landing.footer.privacy' href={config.specialLinks.privacy}/>
|
||||
<TranslatedExternalLink i18nKey='landing.footer.privacy' href={specialLinks.privacy}/>
|
||||
</li>
|
||||
</ShowIf>
|
||||
</ul>
|
||||
|
|
148
yarn.lock
148
yarn.lock
|
@ -1681,11 +1681,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
|
||||
integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
|
||||
|
||||
"@types/deep-equal@1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.1.tgz#71cfabb247c22bcc16d536111f50c0ed12476b03"
|
||||
integrity sha512-mMUu4nWHLBlHtxXY17Fg6+ucS/MnndyOWyOe7MmwkoMYxvfQU2ajtRaEvqSUv+aVkMqH/C0NCI8UoVfRNQ10yg==
|
||||
|
||||
"@types/domhandler@*":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/domhandler/-/domhandler-2.4.1.tgz#7b3b347f7762180fbcb1ece1ce3dd0ebbb8c64cf"
|
||||
|
@ -2558,11 +2553,6 @@ array-equal@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
|
||||
integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
|
||||
|
||||
array-filter@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83"
|
||||
integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=
|
||||
|
||||
array-find-index@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
|
||||
|
@ -2729,13 +2719,6 @@ autoprefixer@^9.6.1:
|
|||
postcss "^7.0.32"
|
||||
postcss-value-parser "^4.1.0"
|
||||
|
||||
available-typed-arrays@^1.0.0, available-typed-arrays@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5"
|
||||
integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==
|
||||
dependencies:
|
||||
array-filter "^1.0.0"
|
||||
|
||||
aws-sign2@~0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
|
||||
|
@ -4350,26 +4333,6 @@ decode-uri-component@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
|
||||
|
||||
deep-equal@2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.3.tgz#cad1c15277ad78a5c01c49c2dee0f54de8a6a7b0"
|
||||
integrity sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA==
|
||||
dependencies:
|
||||
es-abstract "^1.17.5"
|
||||
es-get-iterator "^1.1.0"
|
||||
is-arguments "^1.0.4"
|
||||
is-date-object "^1.0.2"
|
||||
is-regex "^1.0.5"
|
||||
isarray "^2.0.5"
|
||||
object-is "^1.1.2"
|
||||
object-keys "^1.1.1"
|
||||
object.assign "^4.1.0"
|
||||
regexp.prototype.flags "^1.3.0"
|
||||
side-channel "^1.0.2"
|
||||
which-boxed-primitive "^1.0.1"
|
||||
which-collection "^1.0.1"
|
||||
which-typed-array "^1.1.2"
|
||||
|
||||
deep-equal@^1.0.1, deep-equal@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a"
|
||||
|
@ -4796,7 +4759,7 @@ error-stack-parser@^2.0.6:
|
|||
dependencies:
|
||||
stackframe "^1.1.1"
|
||||
|
||||
es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5:
|
||||
es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5:
|
||||
version "1.17.6"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a"
|
||||
integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==
|
||||
|
@ -4831,19 +4794,6 @@ es-abstract@^1.18.0-next.0:
|
|||
string.prototype.trimend "^1.0.1"
|
||||
string.prototype.trimstart "^1.0.1"
|
||||
|
||||
es-get-iterator@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.0.tgz#bb98ad9d6d63b31aacdc8f89d5d0ee57bcb5b4c8"
|
||||
integrity sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==
|
||||
dependencies:
|
||||
es-abstract "^1.17.4"
|
||||
has-symbols "^1.0.1"
|
||||
is-arguments "^1.0.4"
|
||||
is-map "^2.0.1"
|
||||
is-set "^2.0.1"
|
||||
is-string "^1.0.5"
|
||||
isarray "^2.0.5"
|
||||
|
||||
es-to-primitive@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
|
||||
|
@ -5701,11 +5651,6 @@ for-own@^0.1.3:
|
|||
dependencies:
|
||||
for-in "^1.0.1"
|
||||
|
||||
foreach@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
|
||||
integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k=
|
||||
|
||||
forever-agent@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||
|
@ -6702,11 +6647,6 @@ is-arrayish@^0.3.1:
|
|||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
|
||||
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
|
||||
|
||||
is-bigint@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.0.tgz#73da8c33208d00f130e9b5e15d23eac9215601c4"
|
||||
integrity sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g==
|
||||
|
||||
is-binary-path@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
|
||||
|
@ -6721,11 +6661,6 @@ is-binary-path@~2.1.0:
|
|||
dependencies:
|
||||
binary-extensions "^2.0.0"
|
||||
|
||||
is-boolean-object@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e"
|
||||
integrity sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==
|
||||
|
||||
is-buffer@^1.0.2, is-buffer@^1.1.5:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||
|
@ -6769,7 +6704,7 @@ is-data-descriptor@^1.0.0:
|
|||
dependencies:
|
||||
kind-of "^6.0.0"
|
||||
|
||||
is-date-object@^1.0.1, is-date-object@^1.0.2:
|
||||
is-date-object@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
|
||||
integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
|
||||
|
@ -6868,21 +6803,11 @@ is-installed-globally@^0.3.2:
|
|||
global-dirs "^2.0.1"
|
||||
is-path-inside "^3.0.1"
|
||||
|
||||
is-map@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1"
|
||||
integrity sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==
|
||||
|
||||
is-negative-zero@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461"
|
||||
integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=
|
||||
|
||||
is-number-object@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197"
|
||||
integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==
|
||||
|
||||
is-number@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
|
||||
|
@ -6953,7 +6878,7 @@ is-promise@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
|
||||
integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
|
||||
|
||||
is-regex@^1.0.4, is-regex@^1.0.5, is-regex@^1.1.0, is-regex@^1.1.1:
|
||||
is-regex@^1.0.4, is-regex@^1.1.0, is-regex@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9"
|
||||
integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==
|
||||
|
@ -6975,11 +6900,6 @@ is-root@2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c"
|
||||
integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==
|
||||
|
||||
is-set@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.1.tgz#d1604afdab1724986d30091575f54945da7e5f43"
|
||||
integrity sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==
|
||||
|
||||
is-stream@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||
|
@ -6990,7 +6910,7 @@ is-stream@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
|
||||
integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
|
||||
|
||||
is-string@^1.0.4, is-string@^1.0.5:
|
||||
is-string@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6"
|
||||
integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==
|
||||
|
@ -7009,16 +6929,6 @@ is-symbol@^1.0.2:
|
|||
dependencies:
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
is-typed-array@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.3.tgz#a4ff5a5e672e1a55f99c7f54e59597af5c1df04d"
|
||||
integrity sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==
|
||||
dependencies:
|
||||
available-typed-arrays "^1.0.0"
|
||||
es-abstract "^1.17.4"
|
||||
foreach "^2.0.5"
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
is-typedarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
||||
|
@ -7029,16 +6939,6 @@ is-utf8@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
|
||||
integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
|
||||
|
||||
is-weakmap@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2"
|
||||
integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==
|
||||
|
||||
is-weakset@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.1.tgz#e9a0af88dbd751589f5e50d80f4c98b780884f83"
|
||||
integrity sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==
|
||||
|
||||
is-windows@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
|
||||
|
@ -7066,11 +6966,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
isarray@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
|
||||
integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
|
@ -8874,7 +8769,7 @@ object-inspect@^1.7.0, object-inspect@^1.8.0:
|
|||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
|
||||
integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==
|
||||
|
||||
object-is@^1.0.1, object-is@^1.1.2:
|
||||
object-is@^1.0.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6"
|
||||
integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==
|
||||
|
@ -13026,44 +12921,11 @@ whatwg-url@^7.0.0:
|
|||
tr46 "^1.0.1"
|
||||
webidl-conversions "^4.0.2"
|
||||
|
||||
which-boxed-primitive@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz#cbe8f838ebe91ba2471bb69e9edbda67ab5a5ec1"
|
||||
integrity sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==
|
||||
dependencies:
|
||||
is-bigint "^1.0.0"
|
||||
is-boolean-object "^1.0.0"
|
||||
is-number-object "^1.0.3"
|
||||
is-string "^1.0.4"
|
||||
is-symbol "^1.0.2"
|
||||
|
||||
which-collection@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906"
|
||||
integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==
|
||||
dependencies:
|
||||
is-map "^2.0.1"
|
||||
is-set "^2.0.1"
|
||||
is-weakmap "^2.0.1"
|
||||
is-weakset "^2.0.1"
|
||||
|
||||
which-module@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
|
||||
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
|
||||
|
||||
which-typed-array@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.2.tgz#e5f98e56bda93e3dac196b01d47c1156679c00b2"
|
||||
integrity sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==
|
||||
dependencies:
|
||||
available-typed-arrays "^1.0.2"
|
||||
es-abstract "^1.17.5"
|
||||
foreach "^2.0.5"
|
||||
function-bind "^1.1.1"
|
||||
has-symbols "^1.0.1"
|
||||
is-typed-array "^1.1.3"
|
||||
|
||||
which@1, which@^1.2.9, which@^1.3.0, which@^1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||
|
|
Loading…
Add table
Reference in a new issue