mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
Merge branch 'feature/async-tree' into develop
This commit is contained in:
commit
357394d3a2
28 changed files with 1059 additions and 628 deletions
3
.babelrc
3
.babelrc
|
|
@ -11,7 +11,8 @@
|
|||
"modules": false,
|
||||
"targets": {
|
||||
"esmodules": true
|
||||
}
|
||||
},
|
||||
"exclude": ["babel-plugin-transform-async-to-generator"]
|
||||
}
|
||||
],
|
||||
"@babel/preset-typescript",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@ describe(`in GitHub homepage`, () => {
|
|||
beforeAll(() => page.goto('https://github.com'))
|
||||
|
||||
it('should not render Gitako', async () => {
|
||||
expectToNotFind('.gitako-side-bar .gitako-position-wrapper')
|
||||
await expectToNotFind('.gitako-side-bar .gitako-position-wrapper')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,9 +1,27 @@
|
|||
import { expectToFind } from '../utils'
|
||||
import { expectToFind, expectToNotFind, scroll } from '../utils'
|
||||
|
||||
describe(`in Gitako project page`, () => {
|
||||
beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako'))
|
||||
|
||||
it('should render Gitako', async () => {
|
||||
expectToFind('.gitako-side-bar .gitako-position-wrapper')
|
||||
await expectToFind('.gitako-side-bar .gitako-position-wrapper')
|
||||
})
|
||||
|
||||
it('should render file list', async () => {
|
||||
await expectToFind('.gitako-side-bar .files .node-item')
|
||||
})
|
||||
|
||||
it('should render while scroll', async () => {
|
||||
const filesEle = await page.waitForSelector('.gitako-side-bar .files')
|
||||
// node of tsconfig.json should NOT be rendered before scroll down
|
||||
await expectToNotFind('.gitako-side-bar .files a[title="tsconfig.json"]')
|
||||
const box = await filesEle.boundingBox()
|
||||
if (box) {
|
||||
await page.mouse.move(box.x + 40, box.y + 40)
|
||||
await scroll({ totalDistance: 100, duration: 5000 })
|
||||
|
||||
// node of tsconfig.json should be rendered now
|
||||
await expectToFind('.gitako-side-bar .files a[title="tsconfig.json"]')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
|||
13
__tests__/cases/pull-request-page.gitako.ts
Normal file
13
__tests__/cases/pull-request-page.gitako.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { expectToFind } from '../utils'
|
||||
|
||||
describe(`in Gitako project page`, () => {
|
||||
beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako/pull/71'))
|
||||
|
||||
it('should render Gitako', async () => {
|
||||
await expectToFind('.gitako-side-bar .gitako-position-wrapper')
|
||||
})
|
||||
|
||||
it('should render file list', async () => {
|
||||
await expectToFind('.gitako-side-bar .files .node-item')
|
||||
})
|
||||
})
|
||||
|
|
@ -1,7 +1,27 @@
|
|||
export async function expectToFind(selector: string) {
|
||||
await expect(await page.waitForSelector(selector)).not.toBeNull()
|
||||
await expect(page.waitForSelector(selector)).resolves.not.toBeNull()
|
||||
}
|
||||
|
||||
export async function expectToNotFind(selector: string) {
|
||||
await expect(page.waitForSelector(selector, { timeout: 1000 })).rejects.toThrow()
|
||||
}
|
||||
|
||||
export function sleep(timeout: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, timeout))
|
||||
}
|
||||
|
||||
export async function scroll({
|
||||
totalDistance,
|
||||
step = 1,
|
||||
duration = 500,
|
||||
}: {
|
||||
totalDistance: number
|
||||
step?: number
|
||||
duration?: number
|
||||
}) {
|
||||
let distance = 0
|
||||
while ((distance += step) < totalDistance) {
|
||||
await (page.mouse as any).wheel({ deltaY: step })
|
||||
await sleep((duration * step) / totalDistance)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
27
package.json
27
package.json
|
|
@ -17,32 +17,28 @@
|
|||
"test": "NODE_ENV=test jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@primer/components": "^19.1.1",
|
||||
"@primer/components": "^20.0.0",
|
||||
"@primer/css": "^14.4.0",
|
||||
"@primer/octicons-react": "^10.0.0",
|
||||
"@sentry/browser": "^5.12.1",
|
||||
"@types/firefox-webext-browser": "^70.0.1",
|
||||
"@types/history": "^4.7.5",
|
||||
"@types/ini": "^1.3.30",
|
||||
"@types/jest": "^24.0.25",
|
||||
"@types/js-base64": "^2.3.1",
|
||||
"@types/node": "^11.10.4",
|
||||
"@types/nprogress": "^0.0.29",
|
||||
"@types/puppeteer": "^2.0.0",
|
||||
"@types/react": "^16.8.24",
|
||||
"@types/react-dom": "^16.8.5",
|
||||
"@types/react-window": "^1.8.1",
|
||||
"@types/styled-components": "^5.0.1",
|
||||
"@types/styled-system__css": "^5.0.11",
|
||||
"@types/styled-components": "^5.1.3",
|
||||
"@types/styled-system__css": "^5.0.14",
|
||||
"ini": "^1.3.5",
|
||||
"js-base64": "^2.5.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pjax-api": "^3.31.2",
|
||||
"react": "^16.13.0",
|
||||
"react-dom": "^16.13.0",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-use": "^13.8.0",
|
||||
"react-window": "^1.8.5",
|
||||
"styled-components": "^5.0.1",
|
||||
"styled-components": "^5.2.0",
|
||||
"webext-domain-permission-toggle": "^1.0.0",
|
||||
"webext-dynamic-content-scripts": "^6.0.3",
|
||||
"webextension-polyfill": "^0.5.0"
|
||||
|
|
@ -57,6 +53,10 @@
|
|||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/preset-typescript": "^7.3.3",
|
||||
"@sentry/cli": "^1.51.0",
|
||||
"@types/firefox-webext-browser": "^70.0.1",
|
||||
"@types/jest": "^24.0.25",
|
||||
"@types/node": "^11.10.4",
|
||||
"@types/puppeteer": "^3.0.2",
|
||||
"babel-loader": "^8.0.5",
|
||||
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
|
||||
"copy-webpack-plugin": "^5.0.0",
|
||||
|
|
@ -68,11 +68,11 @@
|
|||
"jest-puppeteer": "^4.4.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"puppeteer": "^2.0.0",
|
||||
"puppeteer": "^5.4.1",
|
||||
"raw-loader": "^4.0.0",
|
||||
"sass": "^1.26.2",
|
||||
"sass-loader": "^8.0.2",
|
||||
"typescript": "^3.7.2",
|
||||
"typescript": "^4.0.3",
|
||||
"uglifyjs-webpack-plugin": "^2.1.2",
|
||||
"url-loader": "^1.1.2",
|
||||
"web-ext": "^4.2.0",
|
||||
|
|
@ -86,5 +86,8 @@
|
|||
"semi": false,
|
||||
"trailingComma": "all",
|
||||
"arrowParens": "avoid"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/styled-components": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export function AccessDeniedDescription({ hasToken }: { hasToken: boolean }) {
|
|||
>
|
||||
here
|
||||
</a>{' '}
|
||||
if you setup Gitako with OAuth.
|
||||
if you setup Gitako with OAuth. Or try clear and set token again.
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ import { FileExplorerCore } from 'driver/core'
|
|||
import { ConnectorState, Props } from 'driver/core/FileExplorer'
|
||||
import { platform } from 'platforms'
|
||||
import * as React from 'react'
|
||||
import { useEvent, usePrevious } from 'react-use'
|
||||
import { useEvent } from 'react-use'
|
||||
import { FixedSizeList, ListChildComponentProps } from 'react-window'
|
||||
import { cx } from 'utils/cx'
|
||||
import { focusFileExplorer } from 'utils/DOMHelper'
|
||||
import { isValidRegexpSource } from 'utils/general'
|
||||
import { useOnLocationChange } from 'utils/hooks/useOnLocationChange'
|
||||
import { VisibleNodes } from 'utils/VisibleNodesGenerator'
|
||||
|
|
@ -29,66 +30,38 @@ const RawFileExplorer: React.FC<Props & ConnectorState> = function RawFileExplor
|
|||
expandTo,
|
||||
setUpTree,
|
||||
treeRoot,
|
||||
defer,
|
||||
} = props
|
||||
const {
|
||||
val: { compressSingletonFolder },
|
||||
} = useConfigs()
|
||||
const { val: config } = useConfigs()
|
||||
|
||||
React.useEffect(() => {
|
||||
const { setUpTree, treeRoot, metaData } = props
|
||||
setUpTree({ treeRoot, metaData, compressSingletonFolder })
|
||||
}, [setUpTree, treeRoot, compressSingletonFolder])
|
||||
setUpTree({ treeRoot, metaData, config })
|
||||
}, [setUpTree, treeRoot, config.compressSingletonFolder, config.access_token])
|
||||
|
||||
React.useEffect(() => {
|
||||
const { execAfterRender } = props
|
||||
execAfterRender()
|
||||
if (visibleNodes?.focusedNode) focusFileExplorer()
|
||||
})
|
||||
|
||||
function renderFiles(visibleNodes: VisibleNodes) {
|
||||
const inSearch = searchKey !== ''
|
||||
const { nodes, focusedNode } = visibleNodes
|
||||
if (inSearch && nodes.length === 0) {
|
||||
return (
|
||||
<Text marginTop={6} textAlign="center" color="text.gray">
|
||||
No results found.
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<SizeObserver className={'files'}>
|
||||
{({ width = 0, height = 0 }) => (
|
||||
<ListView
|
||||
focusedNode={focusedNode}
|
||||
nodes={nodes}
|
||||
height={height}
|
||||
width={width}
|
||||
searchKey={searchKey}
|
||||
onNodeClick={onNodeClick}
|
||||
renderActions={
|
||||
searchKey
|
||||
? node => (
|
||||
<button
|
||||
title={'Reveal in file tree'}
|
||||
className={'go-to-button'}
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
goTo(node.path.split('/'))
|
||||
}}
|
||||
>
|
||||
<Icon type="go-to" />
|
||||
</button>
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
visibleNodes={visibleNodes}
|
||||
expandTo={expandTo}
|
||||
metaData={metaData}
|
||||
/>
|
||||
)}
|
||||
</SizeObserver>
|
||||
)
|
||||
}
|
||||
const renderActions: ((node: TreeNode) => React.ReactNode) | undefined = React.useMemo(
|
||||
() =>
|
||||
visibleNodes?.lastMatch?.match.searchKey
|
||||
? node => (
|
||||
<button
|
||||
title={'Reveal in file tree'}
|
||||
className={'go-to-button'}
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
goTo(node.path.split('/'))
|
||||
}}
|
||||
>
|
||||
<Icon type="go-to" />
|
||||
</button>
|
||||
)
|
||||
: undefined,
|
||||
[visibleNodes, goTo],
|
||||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -114,7 +87,31 @@ const RawFileExplorer: React.FC<Props & ConnectorState> = function RawFileExplor
|
|||
onSearch={props.search}
|
||||
onFocus={props.onFocusSearchBar}
|
||||
/>
|
||||
{renderFiles(visibleNodes)}
|
||||
{visibleNodes.lastMatch?.match.searchKey !== '' && visibleNodes.nodes.length === 0 && (
|
||||
<>
|
||||
<Text marginTop={6} textAlign="center" color="text.gray">
|
||||
No results found.
|
||||
</Text>
|
||||
{defer && (
|
||||
<Text textAlign="center" color="gray.4" fontSize="12px">
|
||||
Lazy mode is ON. Search results are limited to loaded folders.
|
||||
</Text>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<SizeObserver className={'files'}>
|
||||
{({ width = 0, height = 0 }) => (
|
||||
<ListView
|
||||
height={height}
|
||||
width={width}
|
||||
onNodeClick={onNodeClick}
|
||||
renderActions={renderActions}
|
||||
visibleNodes={visibleNodes}
|
||||
expandTo={expandTo}
|
||||
metaData={metaData}
|
||||
/>
|
||||
)}
|
||||
</SizeObserver>
|
||||
</>
|
||||
)
|
||||
)}
|
||||
|
|
@ -136,76 +133,90 @@ const VirtualNode = React.memo(function VirtualNode({
|
|||
style,
|
||||
data,
|
||||
}: ListChildComponentProps) {
|
||||
const { searchKey, onNodeClick, renderActions, visibleNodes } = data
|
||||
const regex =
|
||||
searchKey && isValidRegexpSource(searchKey) ? new RegExp(searchKey, 'gi') : undefined
|
||||
const { onNodeClick, renderActions, visibleNodes } = data
|
||||
if (!visibleNodes) return null
|
||||
|
||||
const { nodes, depths, focusedNode, expandedNodes } = visibleNodes
|
||||
const {
|
||||
lastMatch,
|
||||
nodes,
|
||||
focusedNode,
|
||||
expandedNodes,
|
||||
loading,
|
||||
depths,
|
||||
} = visibleNodes as VisibleNodes
|
||||
const node = nodes[index]
|
||||
const searchKey = lastMatch?.match.searchKey
|
||||
return (
|
||||
<Node
|
||||
style={style}
|
||||
key={node.path}
|
||||
node={node}
|
||||
depth={depths.get(node) || 0}
|
||||
focused={focusedNode === node}
|
||||
focused={focusedNode?.path === node.path}
|
||||
loading={loading.has(node.path)}
|
||||
expanded={expandedNodes.has(node.path)}
|
||||
onClick={onNodeClick}
|
||||
renderActions={renderActions}
|
||||
regex={regex}
|
||||
regex={searchKey && isValidRegexpSource(searchKey) ? new RegExp(searchKey, 'gi') : undefined}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
function ListView({
|
||||
nodes,
|
||||
width,
|
||||
height,
|
||||
focusedNode,
|
||||
metaData,
|
||||
expandTo,
|
||||
searchKey,
|
||||
onNodeClick,
|
||||
renderActions,
|
||||
visibleNodes,
|
||||
}: {
|
||||
nodes: TreeNode[]
|
||||
type ListViewProps = {
|
||||
height: number
|
||||
width: number
|
||||
focusedNode: TreeNode | null
|
||||
searchKey: string
|
||||
onNodeClick(event: React.MouseEvent<HTMLElement, MouseEvent>, node: TreeNode): void
|
||||
renderActions?(node: TreeNode): React.ReactNode
|
||||
visibleNodes: VisibleNodes
|
||||
} & Pick<Props, 'metaData'> &
|
||||
Pick<ConnectorState, 'expandTo'>) {
|
||||
const listRef = React.useRef<FixedSizeList>(null)
|
||||
React.useEffect(() => {
|
||||
if (focusedNode && listRef.current) {
|
||||
listRef.current.scrollToItem(nodes.indexOf(focusedNode), 'smart')
|
||||
}
|
||||
}, [listRef.current, focusedNode])
|
||||
}
|
||||
|
||||
const lastNodeLength = usePrevious(nodes.length)
|
||||
function ListView({
|
||||
width,
|
||||
height,
|
||||
metaData,
|
||||
expandTo,
|
||||
onNodeClick,
|
||||
renderActions,
|
||||
visibleNodes,
|
||||
}: ListViewProps & Pick<Props, 'metaData'> & Pick<ConnectorState, 'expandTo'>) {
|
||||
const listRef = React.useRef<FixedSizeList>(null)
|
||||
// the change of depths indicates switch into/from search state
|
||||
React.useEffect(() => {
|
||||
if (listRef.current && !focusedNode && lastNodeLength !== nodes.length) {
|
||||
listRef.current.scrollTo(0)
|
||||
const { focusedNode, nodes } = visibleNodes
|
||||
if (listRef.current && focusedNode?.path) {
|
||||
const index = nodes.findIndex(node => node.path === focusedNode.path)
|
||||
if (index !== -1) {
|
||||
listRef.current.scrollToItem(index, 'smart')
|
||||
}
|
||||
}
|
||||
}, [listRef.current, focusedNode, nodes.length])
|
||||
}, [visibleNodes])
|
||||
// For some reason, removing the deps array above results in bug:
|
||||
// If scroll fast and far, then clicking on items would result in redirect
|
||||
// Not know the reason :(
|
||||
|
||||
const goToCurrentItem = React.useCallback(() => {
|
||||
const targetPath = platform.getCurrentPath(metaData.branchName)
|
||||
if (targetPath) expandTo(targetPath)
|
||||
}, [metaData.branchName])
|
||||
|
||||
useOnLocationChange(goToCurrentItem)
|
||||
useEvent('pjax:ready', goToCurrentItem, document)
|
||||
|
||||
const itemData = React.useMemo(
|
||||
() => ({
|
||||
onNodeClick,
|
||||
renderActions,
|
||||
visibleNodes,
|
||||
}),
|
||||
[onNodeClick, renderActions, visibleNodes],
|
||||
)
|
||||
|
||||
return (
|
||||
<FixedSizeList
|
||||
ref={listRef}
|
||||
itemKey={(index, { nodes = [] }) => nodes[index]?.path}
|
||||
itemData={{ nodes, searchKey, onNodeClick, renderActions, visibleNodes }}
|
||||
itemCount={nodes.length}
|
||||
itemKey={(index, { visibleNodes }) => visibleNodes?.nodes[index]?.path}
|
||||
itemData={itemData}
|
||||
itemCount={visibleNodes.nodes.length}
|
||||
itemSize={36}
|
||||
height={height}
|
||||
width={width}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
ChevronDownIcon as ChevronDown,
|
||||
ChevronRightIcon as ChevronRight,
|
||||
ClockIcon as Clock,
|
||||
FileCodeIcon as FileCode,
|
||||
FileIcon as File,
|
||||
FileMediaIcon as FileMedia,
|
||||
|
|
@ -26,6 +27,11 @@ function getSVGIconComponent(
|
|||
name: string
|
||||
} {
|
||||
switch (type) {
|
||||
case 'loading':
|
||||
return {
|
||||
IconComponent: Clock,
|
||||
name: 'Clock',
|
||||
}
|
||||
case 'hourglass':
|
||||
return {
|
||||
IconComponent: Hourglass,
|
||||
|
|
@ -131,7 +137,12 @@ type Props = {
|
|||
onClick?: (event: React.MouseEvent<HTMLElement>) => void
|
||||
} & IconProps
|
||||
|
||||
export function Icon({ type, className = undefined, placeholder, ...otherProps }: Props) {
|
||||
export const Icon = React.memo(function Icon({
|
||||
type,
|
||||
className = undefined,
|
||||
placeholder,
|
||||
...otherProps
|
||||
}: Props) {
|
||||
let children: React.ReactNode = null
|
||||
if (!placeholder) {
|
||||
const { name, IconComponent } = getSVGIconComponent(type)
|
||||
|
|
@ -142,4 +153,4 @@ export function Icon({ type, className = undefined, placeholder, ...otherProps }
|
|||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ type Props = {
|
|||
depth: number
|
||||
expanded: boolean
|
||||
focused: boolean
|
||||
loading: boolean
|
||||
renderActions?(node: TreeNode): React.ReactNode
|
||||
style?: React.CSSProperties
|
||||
regex?: RegExp
|
||||
|
|
@ -32,6 +33,7 @@ export function Node({
|
|||
depth,
|
||||
expanded,
|
||||
focused,
|
||||
loading,
|
||||
renderActions,
|
||||
style,
|
||||
onClick,
|
||||
|
|
@ -57,7 +59,7 @@ export function Node({
|
|||
title={path}
|
||||
>
|
||||
<div className={'node-item-label'}>
|
||||
<NodeItemIcon node={node} open={expanded} />
|
||||
<NodeItemIcon node={node} open={expanded} loading={loading} />
|
||||
{name.includes('/') ? (
|
||||
name.split('/').map((chunk, index) => (
|
||||
<React.Fragment key={chunk}>
|
||||
|
|
@ -77,9 +79,11 @@ export function Node({
|
|||
const NodeItemIcon = React.memo(function NodeItemIcon({
|
||||
node,
|
||||
open = false,
|
||||
loading,
|
||||
}: {
|
||||
node: TreeNode
|
||||
open?: boolean
|
||||
loading?: boolean
|
||||
}) {
|
||||
const {
|
||||
val: { icons },
|
||||
|
|
@ -96,7 +100,7 @@ const NodeItemIcon = React.memo(function NodeItemIcon({
|
|||
<Icon
|
||||
className={'node-item-type-icon'}
|
||||
placeholder={node.type !== 'tree'}
|
||||
type={getIconType(node)}
|
||||
type={loading ? 'loading' : getIconType(node)}
|
||||
/>
|
||||
{node.type === 'commit' ? (
|
||||
<Icon type={getIconType(node)} />
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ const RawGitako: React.FC<Props & ConnectorState> = function RawGitako(props) {
|
|||
errorDueToAuth,
|
||||
metaData,
|
||||
treeData: treeRoot,
|
||||
defer,
|
||||
error,
|
||||
shouldShow,
|
||||
showSettings,
|
||||
|
|
@ -119,7 +120,6 @@ const RawGitako: React.FC<Props & ConnectorState> = function RawGitako(props) {
|
|||
<div className={'gitako-side-bar-content'}>
|
||||
<div className={'header'}>
|
||||
{metaData ? <MetaBar metaData={metaData} /> : <div />}
|
||||
|
||||
<div className={'close-side-bar-button-position'}>
|
||||
<button className={'close-side-bar-button'} onClick={toggleShowSideBar}>
|
||||
<Icon className={'action-icon'} type={'x'} />
|
||||
|
|
@ -138,11 +138,16 @@ const RawGitako: React.FC<Props & ConnectorState> = function RawGitako(props) {
|
|||
accessToken={accessToken}
|
||||
loadWithPJAX={loadWithPJAX}
|
||||
config={configContext.val}
|
||||
defer={defer}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
<SettingsBar toggleShowSettings={toggleShowSettings} activated={showSettings} />
|
||||
<SettingsBar
|
||||
defer={defer}
|
||||
toggleShowSettings={toggleShowSettings}
|
||||
activated={showSettings}
|
||||
/>
|
||||
</div>
|
||||
</Resizable>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Link } from '@primer/components'
|
||||
import { Label, Link } from '@primer/components'
|
||||
import { Icon } from 'components/Icon'
|
||||
import { VERSION } from 'env'
|
||||
import { platform } from 'platforms'
|
||||
|
|
@ -21,6 +21,7 @@ export const wikiLinks = {
|
|||
}
|
||||
|
||||
type Props = {
|
||||
defer?: boolean
|
||||
activated: boolean
|
||||
toggleShowSettings: () => void
|
||||
}
|
||||
|
|
@ -79,7 +80,7 @@ function SettingsBarContent() {
|
|||
}
|
||||
|
||||
export function SettingsBar(props: Props) {
|
||||
const { toggleShowSettings, activated } = props
|
||||
const { defer, toggleShowSettings, activated } = props
|
||||
return (
|
||||
<div className={'gitako-settings-bar'}>
|
||||
{activated && <SettingsBarContent />}
|
||||
|
|
@ -93,13 +94,24 @@ export function SettingsBar(props: Props) {
|
|||
>
|
||||
{VERSION}
|
||||
</Link>
|
||||
<button className={'settings-button'} onClick={toggleShowSettings}>
|
||||
{activated ? (
|
||||
<Icon type={'chevron-down'} className={'hide-settings-icon'} />
|
||||
) : (
|
||||
<Icon type={'gear'} className={'show-settings-icon'} />
|
||||
<div className={'header-right'}>
|
||||
{defer && (
|
||||
<Label
|
||||
title="File tree data is loaded on demand. And search results are limited."
|
||||
bg="yellow.5"
|
||||
color="gray.6"
|
||||
>
|
||||
Lazy Mode
|
||||
</Label>
|
||||
)}
|
||||
</button>
|
||||
<button className={'settings-button'} onClick={toggleShowSettings}>
|
||||
{activated ? (
|
||||
<Icon type={'chevron-down'} className={'hide-settings-icon'} />
|
||||
) : (
|
||||
<Icon type={'gear'} className={'show-settings-icon'} />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -612,6 +612,13 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
padding: 2px 6px 2px 10px;
|
||||
border-top: 1px solid $border-gray-light;
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
cursor: help; // Will this make user hover for more time to see the tooltip?
|
||||
}
|
||||
|
||||
.settings-button {
|
||||
@include icon-button();
|
||||
@include button-color();
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ function run<M extends Method>([method, args]: [M, Parameters<M>]) {
|
|||
}
|
||||
|
||||
export type DispatchState<Props, State> = React.Component<Props, State>['setState']
|
||||
export type GetState<Props, State> = () => [State, Props]
|
||||
export type GetState<Props, State> = () => { state: State; props: Props }
|
||||
export type TriggerOtherMethod<Props, State> = <Args extends any[]>(
|
||||
methodCreator: MethodCreator<Props, State, Args>,
|
||||
...args: Parameters<ReturnType<MethodCreator<Props, State, Args>>>
|
||||
|
|
@ -75,7 +75,7 @@ function link<P, S>(instance: React.Component<P, S>, sources: Sources<P, S>): Wr
|
|||
const dispatchState: DispatchState<P, S> = (updater, callback) => {
|
||||
instance.setState(updater, callback)
|
||||
}
|
||||
const prepareState: GetState<P, S> = () => [instance.state, instance.props]
|
||||
const prepareState: GetState<P, S> = () => ({ state: instance.state, props: instance.props })
|
||||
const dispatch: Dispatch<P, S> = {
|
||||
call: dispatchCall,
|
||||
get: prepareState,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { GetCreatedMethod, MethodCreator } from 'driver/connect'
|
|||
import { platform } from 'platforms'
|
||||
import { Config } from 'utils/configHelper'
|
||||
import * as DOMHelper from 'utils/DOMHelper'
|
||||
import { searchKeyToRegexps } from 'utils/general'
|
||||
import { VisibleNodes, VisibleNodesGenerator } from 'utils/VisibleNodesGenerator'
|
||||
|
||||
export type Props = {
|
||||
|
|
@ -13,6 +12,7 @@ export type Props = {
|
|||
toggleShowSettings: React.MouseEventHandler
|
||||
config: Config
|
||||
loadWithPJAX(url: string): void
|
||||
defer?: boolean
|
||||
}
|
||||
|
||||
export type ConnectorState = {
|
||||
|
|
@ -21,7 +21,6 @@ export type ConnectorState = {
|
|||
searchKey: string
|
||||
searched: boolean // derived state from searchKey, = !!searchKey
|
||||
|
||||
execAfterRender: GetCreatedMethod<typeof execAfterRender>
|
||||
handleKeyDown: GetCreatedMethod<typeof handleKeyDown>
|
||||
search: GetCreatedMethod<typeof search>
|
||||
onNodeClick: GetCreatedMethod<typeof onNodeClick>
|
||||
|
|
@ -31,75 +30,69 @@ export type ConnectorState = {
|
|||
expandTo: GetCreatedMethod<typeof expandTo>
|
||||
}
|
||||
|
||||
function getVisibleParentNode(
|
||||
nodes: TreeNode[],
|
||||
focusedNode: TreeNode,
|
||||
depths: Map<TreeNode, number>,
|
||||
) {
|
||||
const focusedNodeIndex = nodes.indexOf(focusedNode)
|
||||
const focusedNodeDepth = depths.get(focusedNode)
|
||||
let indexOfParentNode = focusedNodeIndex - 1
|
||||
let depth: number | undefined
|
||||
while (indexOfParentNode !== -1) {
|
||||
depth = depths.get(nodes[indexOfParentNode])
|
||||
if (depth === undefined || focusedNodeDepth === undefined || !(depth >= focusedNodeDepth)) {
|
||||
break
|
||||
function getVisibleParentNode(nodes: TreeNode[], focusedNode: TreeNode) {
|
||||
let index = nodes.findIndex(node => node.path === focusedNode.path) - 1
|
||||
while (index >= 0) {
|
||||
if (nodes[index].contents?.includes(focusedNode)) {
|
||||
return nodes[index]
|
||||
}
|
||||
--indexOfParentNode
|
||||
--index
|
||||
}
|
||||
const parentNode = nodes[indexOfParentNode]
|
||||
return parentNode
|
||||
}
|
||||
|
||||
type Task = () => void
|
||||
const tasksAfterRender: Task[] = []
|
||||
let visibleNodesGenerator: VisibleNodesGenerator
|
||||
|
||||
type BoundMethodCreator<Args extends any[] = []> = MethodCreator<Props, ConnectorState, Args>
|
||||
|
||||
export const setUpTree: BoundMethodCreator<[
|
||||
Pick<Props, 'treeRoot' | 'metaData'> & Pick<Config, 'compressSingletonFolder'>,
|
||||
]> = dispatch => async ({ treeRoot, metaData, compressSingletonFolder }) => {
|
||||
Pick<Props, 'treeRoot' | 'metaData'> & { config: Config },
|
||||
]> = dispatch => async ({ treeRoot, metaData, config }) => {
|
||||
if (!treeRoot) return
|
||||
dispatch.set({ state: 'rendering' })
|
||||
|
||||
visibleNodesGenerator = new VisibleNodesGenerator(treeRoot, {
|
||||
const { compressSingletonFolder } = config
|
||||
|
||||
visibleNodesGenerator = new VisibleNodesGenerator({
|
||||
root: treeRoot,
|
||||
compress: compressSingletonFolder,
|
||||
async getTreeData(path) {
|
||||
const { root } = await platform.getTreeData(metaData, path, false, config.access_token)
|
||||
return root
|
||||
},
|
||||
})
|
||||
|
||||
visibleNodesGenerator.init()
|
||||
tasksAfterRender.push(DOMHelper.focusSearchInput)
|
||||
dispatch.set({ state: 'done' })
|
||||
|
||||
visibleNodesGenerator.onUpdate(visibleNodes => dispatch.set({ visibleNodes }))
|
||||
if (platform.shouldExpandAll?.()) {
|
||||
visibleNodesGenerator.visibleNodes.nodes.forEach(node =>
|
||||
dispatch.call(toggleNodeExpansion, node, { skipScrollToNode: true, recursive: true }),
|
||||
)
|
||||
dispatch.call(updateVisibleNodes)
|
||||
const unsubscribe = visibleNodesGenerator.onUpdate(visibleNodes => {
|
||||
unsubscribe()
|
||||
visibleNodes.nodes.forEach(node =>
|
||||
dispatch.call(toggleNodeExpansion, node, { recursive: true }),
|
||||
)
|
||||
})
|
||||
dispatch.call(search, '')
|
||||
} else {
|
||||
const targetPath = platform.getCurrentPath(metaData.branchName)
|
||||
if (targetPath) dispatch.call(goTo, targetPath)
|
||||
else dispatch.call(search, '')
|
||||
}
|
||||
}
|
||||
|
||||
export const execAfterRender: BoundMethodCreator = dispatch => () => {
|
||||
for (const task of tasksAfterRender) {
|
||||
task()
|
||||
}
|
||||
tasksAfterRender.length = 0
|
||||
dispatch.set({ state: 'done' })
|
||||
}
|
||||
|
||||
export const handleKeyDown: BoundMethodCreator<[React.KeyboardEvent]> = dispatch => event => {
|
||||
const [{ searched, visibleNodes }, { loadWithPJAX }] = dispatch.get()
|
||||
const {
|
||||
state: { searched, visibleNodes },
|
||||
props: { loadWithPJAX },
|
||||
} = dispatch.get()
|
||||
if (!visibleNodes) return
|
||||
const { nodes, focusedNode, expandedNodes, depths } = visibleNodes
|
||||
const { nodes, focusedNode, expandedNodes } = visibleNodes
|
||||
function handleVerticalMove(index: number) {
|
||||
if (0 <= index && index < nodes.length) {
|
||||
DOMHelper.focusFileExplorer()
|
||||
dispatch.call(focusNode, nodes[index], false)
|
||||
dispatch.call(focusNode, nodes[index])
|
||||
} else {
|
||||
DOMHelper.focusSearchInput()
|
||||
dispatch.call(focusNode, null, false)
|
||||
dispatch.call(focusNode, null)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +100,7 @@ export const handleKeyDown: BoundMethodCreator<[React.KeyboardEvent]> = dispatch
|
|||
// prevent document body scrolling if the keypress results in Gitako action
|
||||
let muteEvent = true
|
||||
if (focusedNode) {
|
||||
const focusedNodeIndex = nodes.indexOf(focusedNode)
|
||||
const focusedNodeIndex = nodes.findIndex(node => node.path === focusedNode.path)
|
||||
switch (key) {
|
||||
case 'ArrowUp':
|
||||
// focus on previous node
|
||||
|
|
@ -124,9 +117,9 @@ export const handleKeyDown: BoundMethodCreator<[React.KeyboardEvent]> = dispatch
|
|||
dispatch.call(setExpand, focusedNode, false)
|
||||
} else {
|
||||
// go forward to the start of the list, find the closest node with lower depth
|
||||
const parentNode = getVisibleParentNode(nodes, focusedNode, depths)
|
||||
const parentNode = getVisibleParentNode(nodes, focusedNode)
|
||||
if (parentNode) {
|
||||
dispatch.call(focusNode, parentNode, false)
|
||||
dispatch.call(focusNode, parentNode)
|
||||
}
|
||||
}
|
||||
break
|
||||
|
|
@ -137,10 +130,8 @@ export const handleKeyDown: BoundMethodCreator<[React.KeyboardEvent]> = dispatch
|
|||
if (focusedNode.type === 'tree') {
|
||||
if (expandedNodes.has(focusedNode.path)) {
|
||||
const nextNode = nodes[focusedNodeIndex + 1]
|
||||
const d1 = depths.get(nextNode)
|
||||
const d2 = depths.get(focusedNode)
|
||||
if (d1 !== undefined && d2 !== undefined && d1 > d2) {
|
||||
dispatch.call(focusNode, nextNode, false)
|
||||
if (focusedNode.contents?.includes(nextNode)) {
|
||||
dispatch.call(focusNode, nextNode)
|
||||
}
|
||||
} else {
|
||||
dispatch.call(setExpand, focusedNode, true)
|
||||
|
|
@ -153,17 +144,16 @@ export const handleKeyDown: BoundMethodCreator<[React.KeyboardEvent]> = dispatch
|
|||
break
|
||||
case 'Enter':
|
||||
// expand node or redirect to file page
|
||||
if (focusedNode.type === 'tree') {
|
||||
if (searched) {
|
||||
dispatch.call(goTo, focusedNode.path.split('/'))
|
||||
} else {
|
||||
dispatch.call(setExpand, focusedNode, true)
|
||||
if (searched) {
|
||||
dispatch.call(goTo, focusedNode.path.split('/'))
|
||||
} else {
|
||||
if (focusedNode.type === 'tree') {
|
||||
dispatch.call(toggleNodeExpansion, focusedNode, { recursive: event.altKey })
|
||||
} else if (focusedNode.type === 'blob') {
|
||||
if (focusedNode.url) loadWithPJAX(focusedNode.url)
|
||||
} else if (focusedNode.type === 'commit') {
|
||||
window.open(focusedNode.url)
|
||||
}
|
||||
} else if (focusedNode.type === 'blob') {
|
||||
if (searched) dispatch.call(goTo, focusedNode.path.split('/'))
|
||||
else if (focusedNode.url) loadWithPJAX(focusedNode.url)
|
||||
} else if (focusedNode.type === 'commit') {
|
||||
window.open(focusedNode.url)
|
||||
}
|
||||
break
|
||||
default:
|
||||
|
|
@ -178,11 +168,11 @@ export const handleKeyDown: BoundMethodCreator<[React.KeyboardEvent]> = dispatch
|
|||
switch (key) {
|
||||
case 'ArrowDown':
|
||||
DOMHelper.focusFileExplorer()
|
||||
dispatch.call(focusNode, nodes[0], false)
|
||||
dispatch.call(focusNode, nodes[0])
|
||||
break
|
||||
case 'ArrowUp':
|
||||
DOMHelper.focusFileExplorer()
|
||||
dispatch.call(focusNode, nodes[nodes.length - 1], false)
|
||||
dispatch.call(focusNode, nodes[nodes.length - 1])
|
||||
break
|
||||
default:
|
||||
muteEvent = false
|
||||
|
|
@ -194,52 +184,41 @@ export const handleKeyDown: BoundMethodCreator<[React.KeyboardEvent]> = dispatch
|
|||
}
|
||||
}
|
||||
|
||||
export const onFocusSearchBar: BoundMethodCreator = dispatch => () =>
|
||||
dispatch.call(focusNode, null, false)
|
||||
export const onFocusSearchBar: BoundMethodCreator = dispatch => () => dispatch.call(focusNode, null)
|
||||
|
||||
export const search: BoundMethodCreator<[string]> = dispatch => searchKey => {
|
||||
dispatch.set({ searchKey, searched: searchKey !== '' })
|
||||
const regexps = searchKeyToRegexps(searchKey)
|
||||
visibleNodesGenerator.search(regexps)
|
||||
dispatch.call(updateVisibleNodes)
|
||||
visibleNodesGenerator.search({ searchKey })
|
||||
}
|
||||
|
||||
export const goTo: BoundMethodCreator<[string[]]> = dispatch => async currentPath => {
|
||||
export const goTo: BoundMethodCreator<[string[]]> = dispatch => currentPath => {
|
||||
dispatch.set({ searchKey: '', searched: false })
|
||||
visibleNodesGenerator.search(null)
|
||||
dispatch.call(updateVisibleNodes)
|
||||
tasksAfterRender.push(() => {
|
||||
dispatch.call(expandTo, currentPath)
|
||||
})
|
||||
dispatch.call(expandTo, currentPath)
|
||||
}
|
||||
|
||||
export const setExpand: BoundMethodCreator<[TreeNode, boolean]> = dispatch => (
|
||||
export const setExpand: BoundMethodCreator<[TreeNode, boolean]> = dispatch => async (
|
||||
node,
|
||||
expand = false,
|
||||
) => {
|
||||
visibleNodesGenerator.setExpand(node, expand)
|
||||
dispatch.call(focusNode, node, false)
|
||||
await visibleNodesGenerator.setExpand(node, expand)
|
||||
dispatch.call(focusNode, node)
|
||||
}
|
||||
|
||||
export const toggleNodeExpansion: BoundMethodCreator<[
|
||||
TreeNode,
|
||||
{
|
||||
skipScrollToNode?: boolean
|
||||
recursive?: boolean
|
||||
},
|
||||
]> = dispatch => (node, { skipScrollToNode = false, recursive = false }) => {
|
||||
visibleNodesGenerator.toggleExpand(node, recursive)
|
||||
dispatch.call(focusNode, node, skipScrollToNode)
|
||||
tasksAfterRender.push(DOMHelper.focusFileExplorer)
|
||||
]> = dispatch => async (node, { recursive = false }) => {
|
||||
visibleNodesGenerator.focusNode(node)
|
||||
await visibleNodesGenerator.toggleExpand(node, recursive)
|
||||
}
|
||||
|
||||
export const focusNode: BoundMethodCreator<[TreeNode | null, boolean]> = dispatch => (
|
||||
export const focusNode: BoundMethodCreator<[TreeNode | null]> = dispatch => (
|
||||
node: TreeNode | null,
|
||||
) => {
|
||||
const [{ visibleNodes }] = dispatch.get()
|
||||
if (!visibleNodes) return
|
||||
visibleNodesGenerator.focusNode(node)
|
||||
dispatch.call(updateVisibleNodes)
|
||||
}
|
||||
|
||||
export const onNodeClick: BoundMethodCreator<[
|
||||
|
|
@ -250,22 +229,20 @@ export const onNodeClick: BoundMethodCreator<[
|
|||
if (preventDefault) event.preventDefault()
|
||||
|
||||
if (node.type === 'tree') {
|
||||
const [
|
||||
,
|
||||
{
|
||||
const {
|
||||
props: {
|
||||
config: { recursiveToggleFolder },
|
||||
},
|
||||
] = dispatch.get()
|
||||
} = dispatch.get()
|
||||
const recursive =
|
||||
(recursiveToggleFolder === 'shift' && event.shiftKey) ||
|
||||
(recursiveToggleFolder === 'alt' && event.altKey)
|
||||
dispatch.call(toggleNodeExpansion, node, {
|
||||
skipScrollToNode: true,
|
||||
recursive,
|
||||
})
|
||||
dispatch.call(toggleNodeExpansion, node, { recursive })
|
||||
} else if (node.type === 'blob') {
|
||||
const [, { loadWithPJAX }] = dispatch.get()
|
||||
dispatch.call(focusNode, node, true)
|
||||
const {
|
||||
props: { loadWithPJAX },
|
||||
} = dispatch.get()
|
||||
dispatch.call(focusNode, node)
|
||||
if (node.url && !node.url.includes('#')) {
|
||||
loadWithPJAX(node.url)
|
||||
}
|
||||
|
|
@ -276,15 +253,9 @@ export const onNodeClick: BoundMethodCreator<[
|
|||
}
|
||||
}
|
||||
|
||||
export const expandTo: BoundMethodCreator<[string[]]> = dispatch => currentPath => {
|
||||
const nodeExpandedTo = visibleNodesGenerator.expandTo(currentPath.join('/'))
|
||||
export const expandTo: BoundMethodCreator<[string[]]> = dispatch => async currentPath => {
|
||||
const nodeExpandedTo = await visibleNodesGenerator.expandTo(currentPath.join('/'))
|
||||
if (nodeExpandedTo) {
|
||||
visibleNodesGenerator.focusNode(nodeExpandedTo)
|
||||
}
|
||||
dispatch.call(updateVisibleNodes)
|
||||
}
|
||||
|
||||
export const updateVisibleNodes: BoundMethodCreator = dispatch => () => {
|
||||
const { visibleNodes } = visibleNodesGenerator
|
||||
dispatch.set({ visibleNodes })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export type ConnectorState = {
|
|||
// file tree data
|
||||
treeData?: TreeNode
|
||||
logoContainerElement: Element | null
|
||||
defer?: boolean
|
||||
disabled: boolean
|
||||
initializingPromise: Promise<void> | null
|
||||
} & {
|
||||
|
|
@ -34,7 +35,9 @@ export type ConnectorState = {
|
|||
type BoundMethodCreator<Args extends any[] = []> = MethodCreator<Props, ConnectorState, Args>
|
||||
|
||||
export const init: BoundMethodCreator = dispatch => async () => {
|
||||
const [{ initializingPromise }] = dispatch.get()
|
||||
const {
|
||||
state: { initializingPromise },
|
||||
} = dispatch.get()
|
||||
if (initializingPromise) await initializingPromise
|
||||
|
||||
let done: any = null // cannot use type `(() => void) | null` here
|
||||
|
|
@ -58,7 +61,9 @@ export const init: BoundMethodCreator = dispatch => async () => {
|
|||
})
|
||||
dispatch.call(setMetaData, metaData)
|
||||
|
||||
const [, { configContext }] = dispatch.get()
|
||||
const {
|
||||
props: { configContext },
|
||||
} = dispatch.get()
|
||||
const { access_token: accessToken } = configContext.val
|
||||
|
||||
if (!metaData.userName || !metaData.repoName) return
|
||||
|
|
@ -69,6 +74,8 @@ export const init: BoundMethodCreator = dispatch => async () => {
|
|||
userName: metaData.userName,
|
||||
repoName: metaData.repoName,
|
||||
},
|
||||
'/',
|
||||
true,
|
||||
accessToken,
|
||||
)
|
||||
const caughtAggressiveError = getTreeDataAggressively?.catch(error => {
|
||||
|
|
@ -103,6 +110,8 @@ export const init: BoundMethodCreator = dispatch => async () => {
|
|||
userName: metaData.userName,
|
||||
repoName: metaData.repoName,
|
||||
},
|
||||
'/',
|
||||
true,
|
||||
accessToken,
|
||||
)
|
||||
} else {
|
||||
|
|
@ -114,9 +123,9 @@ export const init: BoundMethodCreator = dispatch => async () => {
|
|||
})
|
||||
}
|
||||
getTreeData
|
||||
.then(async treeData => {
|
||||
.then(async ({ root: treeData, defer }) => {
|
||||
if (treeData) {
|
||||
dispatch.set({ treeData })
|
||||
dispatch.set({ treeData, defer })
|
||||
}
|
||||
})
|
||||
.catch(err => dispatch.call(handleError, err))
|
||||
|
|
@ -141,7 +150,7 @@ export const handleError: BoundMethodCreator<[Error]> = dispatch => async err =>
|
|||
) {
|
||||
dispatch.set({ errorDueToAuth: true })
|
||||
} else if (err.message === errors.CONNECTION_BLOCKED) {
|
||||
const [, props] = dispatch.get()
|
||||
const { props } = dispatch.get()
|
||||
if (props.configContext.val.access_token) {
|
||||
dispatch.call(setError, `Cannot connect to ${platformName}.`)
|
||||
} else {
|
||||
|
|
@ -157,7 +166,10 @@ export const handleError: BoundMethodCreator<[Error]> = dispatch => async err =>
|
|||
}
|
||||
|
||||
export const toggleShowSideBar: BoundMethodCreator = dispatch => () => {
|
||||
const [{ shouldShow }, { configContext }] = dispatch.get()
|
||||
const {
|
||||
state: { shouldShow },
|
||||
props: { configContext },
|
||||
} = dispatch.get()
|
||||
dispatch.call(setShouldShow, !shouldShow)
|
||||
|
||||
const {
|
||||
|
|
|
|||
5
src/global.d.ts
vendored
5
src/global.d.ts
vendored
|
|
@ -23,5 +23,8 @@ type IO<T> = {
|
|||
onChange(value: T): void
|
||||
}
|
||||
|
||||
// do not use with generics
|
||||
type Override<Original, Incoming> = Omit<Original, keyof Incoming> & Incoming
|
||||
|
||||
type VoidFN<T> = (payload: T) => void
|
||||
|
||||
type Async<T> = T | Promise<T>
|
||||
|
|
|
|||
|
|
@ -74,9 +74,13 @@ export async function getTreeData(
|
|||
userName: string,
|
||||
repoName: string,
|
||||
branchName: string,
|
||||
recursive?: boolean,
|
||||
accessToken?: string,
|
||||
): Promise<GitHubAPI.TreeData> {
|
||||
const url = `https://${API_ENDPOINT}/repos/${userName}/${repoName}/git/trees/${branchName}?recursive=1`
|
||||
const search = new URLSearchParams()
|
||||
if (recursive) search.set('recursive', '1')
|
||||
const url =
|
||||
`https://${API_ENDPOINT}/repos/${userName}/${repoName}/git/trees/${branchName}?` + search
|
||||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,15 @@ function processTree(tree: TreeNode[]): TreeNode {
|
|||
const item = pathToItem.get(path)
|
||||
if (item) {
|
||||
itemsToCreateTreeNode.push(item)
|
||||
} else {
|
||||
const $item: TreeNode = {
|
||||
name: path.split('/').pop() || '',
|
||||
path,
|
||||
type: 'tree',
|
||||
contents: [],
|
||||
}
|
||||
pathToItem.set(path, $item)
|
||||
itemsToCreateTreeNode.push($item)
|
||||
}
|
||||
// 'a/b' -> 'a'
|
||||
// 'a' -> ''
|
||||
|
|
@ -66,6 +75,8 @@ export function isEnterprise() {
|
|||
return !window.location.host.endsWith('github.com')
|
||||
}
|
||||
|
||||
const pathSHAMap = new Map<string, string>()
|
||||
|
||||
export const GitHub: Platform = {
|
||||
isEnterprise,
|
||||
resolveMeta() {
|
||||
|
|
@ -97,7 +108,7 @@ export const GitHub: Platform = {
|
|||
defaultBranchName: data.default_branch,
|
||||
}
|
||||
},
|
||||
async getTreeData(metaData, accessToken) {
|
||||
async getTreeData(metaData, path = '/', recursive, accessToken) {
|
||||
const { userName, repoName, branchName } = metaData
|
||||
|
||||
const pullId = URLHelper.isInPullPage()
|
||||
|
|
@ -140,28 +151,39 @@ export const GitHub: Platform = {
|
|||
url: `https://${window.location.host}/${metaData.userName}/${
|
||||
metaData.repoName
|
||||
}/pull/${pullId}/files${window.location.search}#${id || ''}`,
|
||||
contents: undefined,
|
||||
sha: item.sha,
|
||||
}
|
||||
})
|
||||
|
||||
const missingFolders = findMissingFolders(nodes)
|
||||
nodes.push(
|
||||
...missingFolders.map(
|
||||
folder =>
|
||||
({
|
||||
name: folder.replace(/^.*\//, ''),
|
||||
path: folder,
|
||||
type: 'tree',
|
||||
} as TreeNode),
|
||||
),
|
||||
)
|
||||
|
||||
const tree = processTree(nodes)
|
||||
return tree
|
||||
const root = processTree(nodes)
|
||||
return { root }
|
||||
}
|
||||
|
||||
const sha = path === '/' ? branchName : pathSHAMap.get(path)
|
||||
if (!sha) throw new Error(`No sha for path "${path}"`)
|
||||
const treeData = await API.getTreeData(userName, repoName, sha, recursive, accessToken)
|
||||
|
||||
// remove deep items
|
||||
if (treeData.truncated) {
|
||||
if (treeData.tree.some(item => item.path.includes('/')))
|
||||
treeData.tree = treeData.tree.filter(item => !item.path.includes('/'))
|
||||
}
|
||||
|
||||
// update map
|
||||
if (path !== '/' || treeData.truncated) {
|
||||
if (path !== '/') {
|
||||
function sanitizePath(path: string) {
|
||||
return path.replace(/\/\/+/g, '/').replace(/^\/|\/$/g, '') || '/'
|
||||
}
|
||||
treeData.tree.forEach(item => {
|
||||
item.path = sanitizePath(`${path}/${item.path}`)
|
||||
})
|
||||
}
|
||||
treeData.tree.forEach(item => {
|
||||
pathSHAMap.set(item.path, item.sha)
|
||||
})
|
||||
}
|
||||
|
||||
const treeData = await API.getTreeData(userName, repoName, branchName, accessToken)
|
||||
const root = processTree(
|
||||
treeData.tree.map(item => ({
|
||||
path: item.path || '',
|
||||
|
|
@ -193,12 +215,12 @@ export const GitHub: Platform = {
|
|||
)
|
||||
|
||||
if (blobData && blobData.encoding === 'base64' && blobData.content) {
|
||||
resolveGitModules(root, Base64.decode(blobData.content))
|
||||
await resolveGitModules(root, Base64.decode(blobData.content))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return root
|
||||
return { root, defer: treeData.truncated }
|
||||
},
|
||||
shouldShow() {
|
||||
return Boolean(DOMHelper.isInCodePage() || URLHelper.isInPullPage())
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ export const Gitee: Platform = {
|
|||
defaultBranchName: data.default_branch,
|
||||
}
|
||||
},
|
||||
async getTreeData(metaData, accessToken) {
|
||||
async getTreeData(metaData, path, recursive, accessToken) {
|
||||
const { userName, repoName, branchName } = metaData
|
||||
const treeData = await API.getTreeData(userName, repoName, branchName)
|
||||
const root = parseTreeData(treeData, metaData)
|
||||
|
|
@ -124,12 +124,12 @@ export const Gitee: Platform = {
|
|||
)
|
||||
|
||||
if (blobData && blobData.encoding === 'base64' && blobData.content) {
|
||||
resolveGitModules(root, Base64.decode(blobData.content))
|
||||
await resolveGitModules(root, Base64.decode(blobData.content))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return root
|
||||
return { root }
|
||||
},
|
||||
shouldShow() {
|
||||
return DOMHelper.isInCodePage()
|
||||
|
|
|
|||
7
src/platforms/platform.d.ts
vendored
7
src/platforms/platform.d.ts
vendored
|
|
@ -5,7 +5,12 @@ type Platform = {
|
|||
metaData: Pick<MetaData, 'userName' | 'repoName'>,
|
||||
accessToken?: string,
|
||||
): Promise<Pick<MetaData, 'userUrl' | 'repoUrl' | 'defaultBranchName'>>
|
||||
getTreeData(metaData: MetaData, accessToken?: string): Promise<TreeNode>
|
||||
getTreeData(
|
||||
metaData: MetaData,
|
||||
path?: string,
|
||||
recursive?: boolean,
|
||||
accessToken?: string,
|
||||
): Promise<{ root: TreeNode; defer?: boolean }>
|
||||
shouldShow(): boolean
|
||||
shouldExpandAll?(): boolean
|
||||
getCurrentPath(branchName: string): string[] | null
|
||||
|
|
|
|||
54
src/utils/EventHub.ts
Normal file
54
src/utils/EventHub.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
export class EventSubscription<Data, Listener extends VoidFN<Data> = VoidFN<Data>> {
|
||||
listeners: Listener[] = []
|
||||
|
||||
emit(data: Data) {
|
||||
for (const listener of this.listeners) listener(data)
|
||||
}
|
||||
|
||||
addEventListener(listener: Listener) {
|
||||
this.listeners.push(listener)
|
||||
return () => this.removeEventListener(listener)
|
||||
}
|
||||
|
||||
removeEventListener(listener: Listener) {
|
||||
const index = this.listeners.indexOf(listener)
|
||||
if (index !== -1) this.listeners.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
export class EventHub<
|
||||
Shape extends {
|
||||
[event: string]: any
|
||||
}
|
||||
> {
|
||||
ports: {
|
||||
[key in keyof Shape]: EventSubscription<Shape[key]>
|
||||
} = {} as EventHub<Shape>['ports']
|
||||
|
||||
getPort<Event extends keyof Shape>(event: Event) {
|
||||
if (!this.ports[event]) this.ports[event] = new EventSubscription<Shape[typeof event]>()
|
||||
|
||||
return this.ports[event]
|
||||
}
|
||||
|
||||
emit<Event extends keyof Shape>(event: Event, data: Shape[Event]) {
|
||||
const port = this.getPort(event)
|
||||
return port.emit(data)
|
||||
}
|
||||
|
||||
addEventListener<Event extends keyof Shape>(
|
||||
event: Event,
|
||||
listener: (data: Shape[Event]) => void,
|
||||
) {
|
||||
const port = this.getPort(event)
|
||||
return port.addEventListener(listener)
|
||||
}
|
||||
|
||||
removeEventListener<Event extends keyof Shape>(
|
||||
event: Event,
|
||||
listener: (data: Shape[Event]) => void,
|
||||
) {
|
||||
const port = this.getPort(event)
|
||||
return port.removeEventListener(listener)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +1,28 @@
|
|||
import { findNode } from './general'
|
||||
|
||||
/**
|
||||
* This is the stack for generating an array of nodes for rendering
|
||||
*
|
||||
* when lower layer changes, higher layers would reset
|
||||
* when higher layer changes, lower layers would not notice
|
||||
*
|
||||
* render stack | when will change | on change callback
|
||||
*
|
||||
* ^ changes frequently
|
||||
* |
|
||||
* |4 focus | when hover/focus move | onFocusChange
|
||||
* | | | expandedNodes + focusNode -> visibleNodes
|
||||
* |3 expansion | when fold/unfold | onExpansionChange
|
||||
* | | | searchedNodes + toggleNode -> expandedNodes
|
||||
* |2 search key | when search | onSearch
|
||||
* | | | treeNodes + searchKey -> searchedNodes
|
||||
* |1 tree: { root <-> nodes } | when tree init | treeHelper.parse
|
||||
* | | tree data from api -> { root, nodes }
|
||||
* v stable
|
||||
*/
|
||||
import { EventHub } from './EventHub'
|
||||
import { findNode, searchKeyToRegexp, traverse, withEffect } from './general'
|
||||
|
||||
function search(
|
||||
root: TreeNode,
|
||||
regexp: RegExp,
|
||||
match: (node: TreeNode) => boolean,
|
||||
onChildMatch: (node: TreeNode) => void,
|
||||
): TreeNode | null {
|
||||
// go traverse no matter root matches or not to make sure find all nodes matches
|
||||
// go traverse no matter root matches or not to make sure find all nodes
|
||||
const contents = []
|
||||
|
||||
if (root.type === 'tree' && root.contents) {
|
||||
let childMatch = false
|
||||
for (const item of root.contents) {
|
||||
if (isNodeMatch(item, regexp)) {
|
||||
for (const node of root.contents) {
|
||||
if (match(node)) {
|
||||
childMatch = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of root.contents) {
|
||||
const $item = search(item, regexp, onChildMatch)
|
||||
if ($item) {
|
||||
if ($item !== item) childMatch = true
|
||||
contents.push($item)
|
||||
for (const node of root.contents) {
|
||||
const $node = search(node, match, onChildMatch)
|
||||
if ($node) {
|
||||
if ($node !== node) childMatch = true
|
||||
contents.push($node)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,16 +38,12 @@ function search(
|
|||
}
|
||||
}
|
||||
|
||||
if (isNodeMatch(root, regexp)) {
|
||||
if (match(root)) {
|
||||
return root
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function isNodeMatch(root: TreeNode, regexp: RegExp): boolean {
|
||||
return regexp.test(root.name)
|
||||
}
|
||||
|
||||
function compressTree(root: TreeNode, prefix: string[] = []): TreeNode {
|
||||
if (root.contents) {
|
||||
if (root.contents.length === 1) {
|
||||
|
|
@ -78,10 +55,10 @@ function compressTree(root: TreeNode, prefix: string[] = []): TreeNode {
|
|||
|
||||
let compressed = false
|
||||
const contents = []
|
||||
for (const item of root.contents) {
|
||||
const $item = compressTree(item)
|
||||
if ($item !== item) compressed = true
|
||||
contents.push($item)
|
||||
for (const node of root.contents) {
|
||||
const $node = compressTree(node)
|
||||
if ($node !== node) compressed = true
|
||||
contents.push($node)
|
||||
}
|
||||
if (compressed)
|
||||
return {
|
||||
|
|
@ -98,180 +75,294 @@ function compressTree(root: TreeNode, prefix: string[] = []): TreeNode {
|
|||
: root
|
||||
}
|
||||
|
||||
class L1 {
|
||||
root: TreeNode
|
||||
|
||||
constructor(root: TreeNode) {
|
||||
this.root = root
|
||||
function mergeNodes(target: TreeNode, source: TreeNode) {
|
||||
for (const node of source.contents || []) {
|
||||
const dup = target.contents?.find($node => $node.path === node.path)
|
||||
if (dup) {
|
||||
mergeNodes(dup, node)
|
||||
} else {
|
||||
if (!target.contents) target.contents = []
|
||||
target.contents.push(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class L2 {
|
||||
l1: L1
|
||||
compress: boolean
|
||||
root: TreeNode | null = null
|
||||
class BaseLayer {
|
||||
baseRoot: TreeNode
|
||||
getTreeData: (path: string) => Async<TreeNode>
|
||||
loading: Set<TreeNode['path']> = new Set()
|
||||
|
||||
constructor(l1: L1, options: Options) {
|
||||
this.l1 = l1
|
||||
baseHub = new EventHub<{
|
||||
emit: BaseLayer['baseRoot']
|
||||
loadingChange: BaseLayer['loading']
|
||||
}>()
|
||||
|
||||
constructor({ root, getTreeData }: Options) {
|
||||
this.baseRoot = root
|
||||
this.getTreeData = getTreeData
|
||||
}
|
||||
|
||||
loadTreeData = async (path: string) => {
|
||||
const node = await findNode(this.baseRoot, path)
|
||||
if (node && node.type !== 'tree') return node
|
||||
if (node?.contents?.length) return node // check in memory
|
||||
if (this.loading.has(path)) return
|
||||
|
||||
this.loading.add(path)
|
||||
this.baseHub.emit('loadingChange', this.loading)
|
||||
mergeNodes(this.baseRoot, await this.getTreeData(path))
|
||||
this.loading.delete(path)
|
||||
this.baseHub.emit('loadingChange', this.loading)
|
||||
this.baseHub.emit('emit', this.baseRoot)
|
||||
|
||||
return await findNode(this.baseRoot, path)
|
||||
}
|
||||
}
|
||||
|
||||
class ShakeLayer extends BaseLayer {
|
||||
shackedRoot: TreeNode | null = null
|
||||
lastMatch: Parameters<ShakeLayer['shake']>[0] = undefined
|
||||
shakeHub = new EventHub<{ emit: TreeNode | null }>()
|
||||
|
||||
constructor(options: Options) {
|
||||
super(options)
|
||||
|
||||
this.baseHub.addEventListener('emit', () => this.shake(this.lastMatch))
|
||||
}
|
||||
|
||||
shake = withEffect(
|
||||
(p?: {
|
||||
match: {
|
||||
// shape in object for better extensibility
|
||||
searchKey: string
|
||||
}
|
||||
onChildMatch: (node: TreeNode) => void
|
||||
}) => {
|
||||
this.lastMatch = p
|
||||
if (p) {
|
||||
const {
|
||||
match: { searchKey },
|
||||
onChildMatch,
|
||||
} = p
|
||||
|
||||
const regexp = searchKeyToRegexp(searchKey)
|
||||
if (regexp) {
|
||||
this.shackedRoot = search(this.baseRoot, node => regexp.test(node.name), onChildMatch)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.shackedRoot = this.baseRoot
|
||||
},
|
||||
() => this.shakeHub.emit('emit', this.shackedRoot),
|
||||
)
|
||||
}
|
||||
|
||||
class CompressLayer extends ShakeLayer {
|
||||
private compress: boolean
|
||||
depths = new Map<TreeNode, number>()
|
||||
compressedRoot: TreeNode | null = null
|
||||
compressHub = new EventHub<{ emit: TreeNode | null }>()
|
||||
|
||||
constructor(options: Options) {
|
||||
super(options)
|
||||
this.compress = Boolean(options.compress)
|
||||
|
||||
this.shakeHub.addEventListener('emit', () => this.compressTree())
|
||||
}
|
||||
|
||||
search = (regexp: RegExp | null, onChildMatch: (node: TreeNode) => void) => {
|
||||
const rootNode = regexp ? search(this.l1.root, regexp, onChildMatch) : this.l1.root
|
||||
private compressTree = withEffect(
|
||||
() => {
|
||||
this.compressedRoot =
|
||||
this.shackedRoot && this.compress
|
||||
? {
|
||||
...this.shackedRoot,
|
||||
contents: this.shackedRoot.contents?.map(node => compressTree(node)),
|
||||
}
|
||||
: this.shackedRoot
|
||||
|
||||
this.root =
|
||||
rootNode && this.compress
|
||||
? { ...rootNode, contents: rootNode.contents?.map(node => compressTree(node)) }
|
||||
: rootNode
|
||||
}
|
||||
if (this.compressedRoot) {
|
||||
const depths = new Map<TreeNode, number>()
|
||||
const recordDepth = (node: TreeNode, depth = 0) => {
|
||||
depths.set(node, depth)
|
||||
for (const $node of node.contents || []) {
|
||||
recordDepth($node, depth + 1)
|
||||
}
|
||||
}
|
||||
recordDepth(this.compressedRoot, -1)
|
||||
this.depths = depths
|
||||
}
|
||||
},
|
||||
() => this.compressHub.emit('emit', this.compressedRoot),
|
||||
)
|
||||
}
|
||||
|
||||
class L3 {
|
||||
l1: L1
|
||||
l2: L2
|
||||
|
||||
class FlattenLayer extends CompressLayer {
|
||||
focusedNode: TreeNode | null = null
|
||||
nodes: TreeNode[] = []
|
||||
expandedNodes: Set<TreeNode['path']> = new Set()
|
||||
depths: Map<TreeNode, number> = new Map()
|
||||
flattenHub = new EventHub<{ emit: null }>()
|
||||
|
||||
constructor(l1: L1, l2: L2) {
|
||||
this.l1 = l1
|
||||
this.l2 = l2
|
||||
constructor(options: Options) {
|
||||
super(options)
|
||||
|
||||
this.compressHub.addEventListener('emit', () => this.generateVisibleNodes())
|
||||
}
|
||||
|
||||
toggleExpand = (node: TreeNode, recursive?: boolean) => {
|
||||
const expand = !this.expandedNodes.has(node.path)
|
||||
if (recursive) {
|
||||
const recursiveSetExpand = (node: TreeNode, expand: boolean) => {
|
||||
this.barelySetExpand(node, expand)
|
||||
node.contents?.forEach($node => recursiveSetExpand($node, expand))
|
||||
generateVisibleNodes = withEffect(
|
||||
async () => {
|
||||
const nodes: TreeNode[] = []
|
||||
const focusedNode = this.focusedNode
|
||||
|
||||
if (
|
||||
focusedNode &&
|
||||
this.compressedRoot &&
|
||||
!(await findNode(this.compressedRoot, focusedNode.path))
|
||||
) {
|
||||
// rescue the focus after expanding async singleton folder
|
||||
await traverse(
|
||||
this.compressedRoot.contents,
|
||||
node => {
|
||||
if (node.type === 'tree' && node.path.startsWith(focusedNode.path)) {
|
||||
this.focusNode(node)
|
||||
}
|
||||
|
||||
return node.type === 'tree' && this.expandedNodes.has(node.path)
|
||||
},
|
||||
node => node.contents || [],
|
||||
)
|
||||
}
|
||||
recursiveSetExpand(node, expand)
|
||||
this.generateVisibleNodes()
|
||||
} else {
|
||||
this.setExpand(node, expand)
|
||||
|
||||
await traverse(
|
||||
this.compressedRoot?.contents,
|
||||
node => {
|
||||
nodes.push(node)
|
||||
return node.type === 'tree' && this.expandedNodes.has(node.path)
|
||||
},
|
||||
node => node.contents || [],
|
||||
)
|
||||
this.nodes = nodes
|
||||
},
|
||||
() => this.flattenHub.emit('emit', null),
|
||||
)
|
||||
|
||||
focusNode = (node: TreeNode | null) => {
|
||||
if (this.focusedNode !== node) {
|
||||
this.focusedNode = node
|
||||
this.flattenHub.emit('emit', null)
|
||||
}
|
||||
}
|
||||
|
||||
barelySetExpand = (node: TreeNode, expand: boolean) => {
|
||||
if (expand && node.contents) {
|
||||
// only node with contents is expandable
|
||||
if (expand) {
|
||||
this.expandedNodes.add(node.path)
|
||||
} else {
|
||||
this.expandedNodes.delete(node.path)
|
||||
}
|
||||
}
|
||||
|
||||
setExpand = (node: TreeNode, expand: boolean) => {
|
||||
$setExpand = (node: TreeNode, expand: boolean) => {
|
||||
this.barelySetExpand(node, expand)
|
||||
this.generateVisibleNodes()
|
||||
if (expand && node.type === 'tree') return this.loadTreeData(node.path)
|
||||
}
|
||||
setExpand = withEffect(this.$setExpand, this.generateVisibleNodes)
|
||||
|
||||
expandTo = (path: string, expandAlongTheWay?: boolean) => {
|
||||
const rootNode = this.l2.root
|
||||
if (expandAlongTheWay && path.includes('/')) {
|
||||
this.expandTo(path.slice(0, path.lastIndexOf('/')), true)
|
||||
}
|
||||
const node = rootNode && findNode(rootNode, path.split('/'), node => this.setExpand(node, true))
|
||||
if (node) this.setExpand(node, true)
|
||||
return node
|
||||
}
|
||||
toggleExpand = withEffect(async (node: TreeNode, recursive = false) => {
|
||||
const expand = !this.expandedNodes.has(node.path)
|
||||
await traverse(
|
||||
[node],
|
||||
async node => {
|
||||
await this.$setExpand(node, expand)
|
||||
return recursive
|
||||
},
|
||||
node => node.contents || [],
|
||||
)
|
||||
}, this.generateVisibleNodes)
|
||||
|
||||
search = (regexp: RegExp | null) => {
|
||||
this.expandedNodes.clear()
|
||||
this.l2.search(regexp, node => this.expandedNodes.add(node.path))
|
||||
this.generateVisibleNodes()
|
||||
}
|
||||
|
||||
generateVisibleNodes = () => {
|
||||
this.depths.clear()
|
||||
const nodes: TreeNode[] = []
|
||||
if (this.l2.root?.contents) {
|
||||
const traverse = (root: TreeNode, depth = 0) => {
|
||||
nodes.push(root)
|
||||
this.depths.set(root, depth)
|
||||
if (this.expandedNodes.has(root.path) && root.type === 'tree' && root.contents?.length) {
|
||||
for (const item of root.contents) {
|
||||
traverse(item, depth + 1)
|
||||
expandTo = withEffect(async (path: string) => {
|
||||
const rootNode = this.compressedRoot
|
||||
if (rootNode) {
|
||||
await traverse(
|
||||
[rootNode],
|
||||
async node => {
|
||||
const overflowChar = node.path[path.length + 1]
|
||||
const match = path.startsWith(node.path) && (overflowChar === '/' || !overflowChar)
|
||||
if (node.path) {
|
||||
// rootNode.path === ''
|
||||
if (match) {
|
||||
if (node.path === path) {
|
||||
// do not wait for expansion for the exact node as that will block "jumping from search"
|
||||
this.$setExpand(node, true)
|
||||
} else await this.$setExpand(node, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const item of this.l2.root.contents) {
|
||||
traverse(item)
|
||||
}
|
||||
return match
|
||||
},
|
||||
node => node?.contents || [],
|
||||
)
|
||||
|
||||
const node = await findNode(rootNode, path)
|
||||
return node
|
||||
}
|
||||
this.nodes = nodes
|
||||
}
|
||||
}
|
||||
}, this.generateVisibleNodes)
|
||||
|
||||
export type VisibleNodes = {
|
||||
nodes: L3['nodes']
|
||||
depths: L3['depths']
|
||||
expandedNodes: L3['expandedNodes']
|
||||
focusedNode: L4['focusedNode']
|
||||
}
|
||||
|
||||
class L4 {
|
||||
l1: L1
|
||||
l2: L2
|
||||
l3: L3
|
||||
|
||||
focusedNode: TreeNode | null
|
||||
|
||||
constructor(l1: L1, l2: L2, l3: L3) {
|
||||
this.l1 = l1
|
||||
this.l2 = l2
|
||||
this.l3 = l3
|
||||
this.focusedNode = null
|
||||
}
|
||||
|
||||
focusNode = (node: TreeNode | null) => {
|
||||
this.focusedNode = node
|
||||
search = (
|
||||
match: {
|
||||
searchKey: string
|
||||
} | null,
|
||||
) => {
|
||||
this.shake(
|
||||
match
|
||||
? {
|
||||
match,
|
||||
onChildMatch: node => this.$setExpand(node, true),
|
||||
}
|
||||
: undefined,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type Options = {
|
||||
compress?: boolean
|
||||
root: BaseLayer['baseRoot']
|
||||
getTreeData: BaseLayer['getTreeData']
|
||||
compress: CompressLayer['compress']
|
||||
}
|
||||
|
||||
export class VisibleNodesGenerator {
|
||||
l1: L1
|
||||
l2: L2
|
||||
l3: L3
|
||||
l4: L4
|
||||
export type VisibleNodes = {
|
||||
loading: BaseLayer['loading']
|
||||
lastMatch: ShakeLayer['lastMatch']
|
||||
depths: CompressLayer['depths']
|
||||
nodes: FlattenLayer['nodes']
|
||||
expandedNodes: FlattenLayer['expandedNodes']
|
||||
focusedNode: FlattenLayer['focusedNode']
|
||||
}
|
||||
|
||||
search: L3['search']
|
||||
setExpand: L3['setExpand']
|
||||
toggleExpand: L3['toggleExpand']
|
||||
expandTo: L3['expandTo']
|
||||
focusNode: L4['focusNode']
|
||||
export class VisibleNodesGenerator extends FlattenLayer {
|
||||
hub = new EventHub<{
|
||||
emit: VisibleNodes
|
||||
}>()
|
||||
constructor(options: Options) {
|
||||
super(options)
|
||||
|
||||
constructor(root: TreeNode, options: Options) {
|
||||
this.l1 = new L1(root)
|
||||
this.l2 = new L2(this.l1, options)
|
||||
this.l3 = new L3(this.l1, this.l2)
|
||||
this.l4 = new L4(this.l1, this.l2, this.l3)
|
||||
|
||||
this.search = regexps => {
|
||||
this.l3.search(regexps)
|
||||
this.l4.focusNode(null)
|
||||
}
|
||||
this.setExpand = (...args) => this.l3.setExpand(...args)
|
||||
this.toggleExpand = (...args) => this.l3.toggleExpand(...args)
|
||||
this.expandTo = (...args) => this.l3.expandTo(...args)
|
||||
this.focusNode = (...args) => this.l4.focusNode(...args)
|
||||
this.flattenHub.addEventListener('emit', () => this.update())
|
||||
this.baseHub.addEventListener('loadingChange', () => this.update())
|
||||
}
|
||||
|
||||
init() {
|
||||
this.search(null)
|
||||
onUpdate(callback: (visibleNodes: VisibleNodes) => void) {
|
||||
return this.hub.addEventListener('emit', callback)
|
||||
}
|
||||
|
||||
get visibleNodes() {
|
||||
update() {
|
||||
this.hub.emit('emit', this.visibleNodes)
|
||||
}
|
||||
|
||||
get visibleNodes(): VisibleNodes {
|
||||
return {
|
||||
nodes: this.l3.nodes,
|
||||
depths: this.l3.depths,
|
||||
expandedNodes: this.l3.expandedNodes,
|
||||
focusedNode: this.l4.focusedNode,
|
||||
nodes: this.nodes,
|
||||
lastMatch: this.lastMatch,
|
||||
depths: this.depths,
|
||||
expandedNodes: this.expandedNodes,
|
||||
focusedNode: this.focusedNode,
|
||||
loading: this.loading,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,38 +47,49 @@ export function friendlyFormatShortcut(shortcut?: string) {
|
|||
}
|
||||
|
||||
/**
|
||||
* if item's name matches path, return self-depth of the item
|
||||
* if item's name matches path, return the depth of the item
|
||||
* else return 0
|
||||
*/
|
||||
function measureDistance(item: TreeNode, path: TreeNode['name'][]): number {
|
||||
const pathString = path.join('/')
|
||||
if (item.name.indexOf(pathString + '/') === 0) {
|
||||
if (item.name.startsWith(pathString + '/')) {
|
||||
// If accessing a leading item of compressed node, path will be shorter than item.name
|
||||
return path.length
|
||||
} else if (pathString === item.name || pathString.indexOf(item.name + '/') === 0) {
|
||||
} else if (pathString === item.name || pathString.startsWith(item.name + '/')) {
|
||||
return item.name.split('/').length
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
export async function traverse<T>(
|
||||
range: T[] = [],
|
||||
conditionAndEffect: (node: T) => Async<boolean>,
|
||||
getChildren: (node: T) => T[],
|
||||
) {
|
||||
for (const item of range) {
|
||||
if (await conditionAndEffect(item)) {
|
||||
await traverse(getChildren(item), conditionAndEffect, getChildren)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* look for the first item matches given path under root.content
|
||||
*/
|
||||
export function findNode(
|
||||
root: TreeNode,
|
||||
path: TreeNode['name'][],
|
||||
callback?: (node: TreeNode) => void,
|
||||
): TreeNode | undefined {
|
||||
if (Array.isArray(root.contents)) {
|
||||
for (const item of root.contents) {
|
||||
const distance = measureDistance(item, path)
|
||||
if (distance > 0) {
|
||||
if (callback) callback(item)
|
||||
if (path.length === distance) return item
|
||||
return findNode(item, path.slice(distance), callback)
|
||||
export async function findNode(root: TreeNode, path: TreeNode['path']) {
|
||||
let node: TreeNode | undefined
|
||||
await traverse(
|
||||
[root],
|
||||
$node => {
|
||||
if (path === $node.path) {
|
||||
node = $node
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return path.startsWith($node.path)
|
||||
},
|
||||
node => node.contents || [],
|
||||
)
|
||||
return node
|
||||
}
|
||||
|
||||
export function createStyleSheet(content: string) {
|
||||
|
|
@ -130,7 +141,7 @@ export async function JSONRequest(url: string, data: any, extra: RequestInit = {
|
|||
).json()
|
||||
}
|
||||
|
||||
export function searchKeyToRegexps(searchKey: string) {
|
||||
export function searchKeyToRegexp(searchKey: string) {
|
||||
if (!searchKey) return null
|
||||
|
||||
try {
|
||||
|
|
@ -159,3 +170,14 @@ export function isValidRegexpSource(source: string) {
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export function withEffect<Method extends (...args: any[]) => any>(
|
||||
method: Method,
|
||||
effect: (payload: ReturnType<Method>) => void,
|
||||
): (...args: Parameters<Method>) => ReturnType<Method> {
|
||||
return (...args) => {
|
||||
const returnValue = method.apply(null, args)
|
||||
Promise.resolve(returnValue).then(effect)
|
||||
return returnValue
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,13 +38,14 @@ type ParsedModule = {
|
|||
[key: string]: string | undefined
|
||||
}
|
||||
|
||||
function handleParsed(root: TreeNode, parsed: ParsedINI) {
|
||||
Object.values(parsed).forEach(value => {
|
||||
// TODO: merge into getTreeData callback
|
||||
async function handleParsed(root: TreeNode, parsed: ParsedINI) {
|
||||
for (const value of Object.values(parsed)) {
|
||||
if (typeof value === 'string') return
|
||||
const url = value?.url
|
||||
const path = value?.path
|
||||
if (typeof url === 'string' && typeof path === 'string') {
|
||||
const node = findNode(root, path.split('/'))
|
||||
const node = await findNode(root, path)
|
||||
if (node) {
|
||||
if (subModuleURLRegex.HTTPGit.test(url)) {
|
||||
node.url = transformModuleHTTPDotGitURL(node, url)
|
||||
|
|
@ -61,16 +62,16 @@ function handleParsed(root: TreeNode, parsed: ParsedINI) {
|
|||
// raiseError(new Error(`Submodule node not found`), { path })
|
||||
}
|
||||
} else {
|
||||
handleParsed(root, value as ParsedINI)
|
||||
await handleParsed(root, value as ParsedINI)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveGitModules(root: TreeNode, content: string) {
|
||||
export async function resolveGitModules(root: TreeNode, content: string) {
|
||||
try {
|
||||
if (Array.isArray(root.contents)) {
|
||||
const parsed: ParsedINI = ini.parse(content)
|
||||
handleParsed(root, parsed)
|
||||
await handleParsed(root, parsed)
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(`Error resolving git modules`)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ const config: Config = {
|
|||
return path
|
||||
},
|
||||
},
|
||||
fallback(target, reason) {
|
||||
// prevent unexpected reload
|
||||
},
|
||||
}
|
||||
|
||||
export function usePJAX() {
|
||||
|
|
|
|||
35
src/utils/hooks/useUpdateReason.tsx
Normal file
35
src/utils/hooks/useUpdateReason.tsx
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import { IN_PRODUCTION_MODE } from 'env'
|
||||
import * as React from 'react'
|
||||
|
||||
export function useUpdateReason<P /* extends {
|
||||
[key: string]: any
|
||||
} */>(props: P) {
|
||||
const lastPropsRef = React.useRef<P>(props)
|
||||
React.useEffect(() => {
|
||||
if (IN_PRODUCTION_MODE) return
|
||||
let output: unknown[][] = []
|
||||
for (const key of Object.keys(props)) {
|
||||
if (key === 'children') continue
|
||||
const $key = key as keyof P
|
||||
if (!(key in lastPropsRef.current)) output.push([`[Added]`, key, props[$key]])
|
||||
if (lastPropsRef.current[$key] !== props[$key])
|
||||
output.push([`[Updated]`, key, lastPropsRef.current[$key], props[$key]])
|
||||
}
|
||||
|
||||
for (const key of Object.keys(lastPropsRef.current)) {
|
||||
if (key === 'children') continue
|
||||
const $key = key as keyof P
|
||||
if (!(key in props)) output.push([`[Removed]`, key, props[$key]])
|
||||
}
|
||||
|
||||
if (output.length) {
|
||||
console.log(`[Updated Reasons]`)
|
||||
for (const record of output) {
|
||||
console.log(...record.map(r => (typeof r === 'function' ? '[fn]' : r)))
|
||||
}
|
||||
console.log(`;;`)
|
||||
}
|
||||
|
||||
lastPropsRef.current = props
|
||||
})
|
||||
}
|
||||
463
yarn.lock
463
yarn.lock
|
|
@ -33,6 +33,13 @@
|
|||
dependencies:
|
||||
"@babel/highlight" "^7.10.3"
|
||||
|
||||
"@babel/code-frame@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
|
||||
integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.10.4"
|
||||
|
||||
"@babel/code-frame@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e"
|
||||
|
|
@ -92,6 +99,15 @@
|
|||
lodash "^4.17.13"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/generator@^7.11.5":
|
||||
version "7.11.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620"
|
||||
integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==
|
||||
dependencies:
|
||||
"@babel/types" "^7.11.5"
|
||||
jsesc "^2.5.1"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/generator@^7.6.0":
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.0.tgz#e2c21efbfd3293ad819a2359b448f002bfdfda56"
|
||||
|
|
@ -103,16 +119,6 @@
|
|||
source-map "^0.5.0"
|
||||
trim-right "^1.0.1"
|
||||
|
||||
"@babel/generator@^7.8.6":
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.7.tgz#870b3cf7984f5297998152af625c4f3e341400f7"
|
||||
integrity sha512-DQwjiKJqH4C3qGiyQCAExJHoZssn49JTMJgZ8SANGgVFdkupcUhLOdkAeoC6kmHZCPfoDG5M0b6cFlSN5wW7Ew==
|
||||
dependencies:
|
||||
"@babel/types" "^7.8.7"
|
||||
jsesc "^2.5.1"
|
||||
lodash "^4.17.13"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32"
|
||||
|
|
@ -192,14 +198,14 @@
|
|||
"@babel/template" "^7.10.3"
|
||||
"@babel/types" "^7.10.3"
|
||||
|
||||
"@babel/helper-function-name@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca"
|
||||
integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==
|
||||
"@babel/helper-function-name@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a"
|
||||
integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==
|
||||
dependencies:
|
||||
"@babel/helper-get-function-arity" "^7.8.3"
|
||||
"@babel/template" "^7.8.3"
|
||||
"@babel/types" "^7.8.3"
|
||||
"@babel/helper-get-function-arity" "^7.10.4"
|
||||
"@babel/template" "^7.10.4"
|
||||
"@babel/types" "^7.10.4"
|
||||
|
||||
"@babel/helper-get-function-arity@^7.0.0":
|
||||
version "7.0.0"
|
||||
|
|
@ -215,12 +221,12 @@
|
|||
dependencies:
|
||||
"@babel/types" "^7.10.3"
|
||||
|
||||
"@babel/helper-get-function-arity@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5"
|
||||
integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==
|
||||
"@babel/helper-get-function-arity@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2"
|
||||
integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==
|
||||
dependencies:
|
||||
"@babel/types" "^7.8.3"
|
||||
"@babel/types" "^7.10.4"
|
||||
|
||||
"@babel/helper-hoist-variables@^7.4.4":
|
||||
version "7.4.4"
|
||||
|
|
@ -367,6 +373,13 @@
|
|||
dependencies:
|
||||
"@babel/types" "^7.10.1"
|
||||
|
||||
"@babel/helper-split-export-declaration@^7.11.0":
|
||||
version "7.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f"
|
||||
integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==
|
||||
dependencies:
|
||||
"@babel/types" "^7.11.0"
|
||||
|
||||
"@babel/helper-split-export-declaration@^7.4.4":
|
||||
version "7.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677"
|
||||
|
|
@ -374,18 +387,16 @@
|
|||
dependencies:
|
||||
"@babel/types" "^7.4.4"
|
||||
|
||||
"@babel/helper-split-export-declaration@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9"
|
||||
integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==
|
||||
dependencies:
|
||||
"@babel/types" "^7.8.3"
|
||||
|
||||
"@babel/helper-validator-identifier@^7.10.3":
|
||||
version "7.10.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz#60d9847f98c4cea1b279e005fdb7c28be5412d15"
|
||||
integrity sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
|
||||
integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==
|
||||
|
||||
"@babel/helper-wrap-function@^7.1.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa"
|
||||
|
|
@ -441,6 +452,15 @@
|
|||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/highlight@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143"
|
||||
integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.10.4"
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/highlight@^7.8.3":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797"
|
||||
|
|
@ -455,6 +475,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.3.tgz#7e71d892b0d6e7d04a1af4c3c79d72c1f10f5315"
|
||||
integrity sha512-oJtNJCMFdIMwXGmx+KxuaD7i3b8uS7TTFYW/FNG2BT8m+fmGHoiPYoH0Pe3gya07WuFmM5FCDIr1x0irkD/hyA==
|
||||
|
||||
"@babel/parser@^7.10.4", "@babel/parser@^7.11.5":
|
||||
version "7.11.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037"
|
||||
integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==
|
||||
|
||||
"@babel/parser@^7.6.0":
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.0.tgz#3e05d0647432a8326cb28d0de03895ae5a57f39b"
|
||||
|
|
@ -1040,6 +1065,15 @@
|
|||
"@babel/parser" "^7.10.3"
|
||||
"@babel/types" "^7.10.3"
|
||||
|
||||
"@babel/template@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278"
|
||||
integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.10.4"
|
||||
"@babel/parser" "^7.10.4"
|
||||
"@babel/types" "^7.10.4"
|
||||
|
||||
"@babel/template@^7.8.3":
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
|
||||
|
|
@ -1080,19 +1114,19 @@
|
|||
lodash "^4.17.13"
|
||||
|
||||
"@babel/traverse@^7.4.5":
|
||||
version "7.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.6.tgz#acfe0c64e1cd991b3e32eae813a6eb564954b5ff"
|
||||
integrity sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A==
|
||||
version "7.11.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3"
|
||||
integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.8.3"
|
||||
"@babel/generator" "^7.8.6"
|
||||
"@babel/helper-function-name" "^7.8.3"
|
||||
"@babel/helper-split-export-declaration" "^7.8.3"
|
||||
"@babel/parser" "^7.8.6"
|
||||
"@babel/types" "^7.8.6"
|
||||
"@babel/code-frame" "^7.10.4"
|
||||
"@babel/generator" "^7.11.5"
|
||||
"@babel/helper-function-name" "^7.10.4"
|
||||
"@babel/helper-split-export-declaration" "^7.11.0"
|
||||
"@babel/parser" "^7.11.5"
|
||||
"@babel/types" "^7.11.5"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
lodash "^4.17.13"
|
||||
lodash "^4.17.19"
|
||||
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0":
|
||||
version "7.6.1"
|
||||
|
|
@ -1112,7 +1146,16 @@
|
|||
lodash "^4.17.13"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.8.7":
|
||||
"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.11.5":
|
||||
version "7.11.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d"
|
||||
integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.10.4"
|
||||
lodash "^4.17.19"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.8.6":
|
||||
version "7.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.7.tgz#1fc9729e1acbb2337d5b6977a63979b4819f5d1d"
|
||||
integrity sha512-k2TreEHxFA4CjGkL+GYjRyx35W0Mr7DP5+9q6WMkyKXB+904bYmG40syjMFV0oLlhhFCwWl0vA0DyzTDkwAiJw==
|
||||
|
|
@ -1145,7 +1188,7 @@
|
|||
exec-sh "^0.3.2"
|
||||
minimist "^1.2.0"
|
||||
|
||||
"@emotion/is-prop-valid@^0.8.3":
|
||||
"@emotion/is-prop-valid@^0.8.8":
|
||||
version "0.8.8"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
|
||||
integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
|
||||
|
|
@ -1357,14 +1400,14 @@
|
|||
"@types/yargs" "^15.0.0"
|
||||
chalk "^3.0.0"
|
||||
|
||||
"@primer/components@^19.1.1":
|
||||
version "19.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@primer/components/-/components-19.1.1.tgz#5980a57a92e632210844e778f79f5f181b8c6d2e"
|
||||
integrity sha512-SOgUqqaKVIcs5ItniKtrpF+uEDaguCA+2LEOxCOYSiKmPk8wlJBAtTSTTBc3X7TPEk6jU7JVaqY0eXIXmpVswQ==
|
||||
"@primer/components@^20.0.0":
|
||||
version "20.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@primer/components/-/components-20.0.0.tgz#643bd7d719af28d6cdf446909255ee04e9f47014"
|
||||
integrity sha512-OpnBJDB+7Rw8NK7p/UlJx3B6uGjRSVKtbEUAE+BjTYAD5wrjSnWKTgBqnorTzPcmstDAxC6GNtmsukyyk3lMHA==
|
||||
dependencies:
|
||||
"@babel/helpers" "7.9.2"
|
||||
"@babel/runtime" "7.9.2"
|
||||
"@primer/octicons-react" "^9.6.0"
|
||||
"@primer/octicons-react" "^10.0.0"
|
||||
"@primer/primitives" "3.0.0"
|
||||
"@reach/dialog" "0.3.0"
|
||||
"@styled-system/css" "5.1.5"
|
||||
|
|
@ -1396,13 +1439,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@primer/octicons-react/-/octicons-react-10.0.0.tgz#82f0d64b4276778fb51468afac00aa0c420ad230"
|
||||
integrity sha512-I+m7Srg/Ivo5VuXoKwKCJ6YJya+lr6EVzp/WGnDlwBSpy0m4WfYAmZigt3A0i4JMqgLRFDlK+8AgqT66E9bOOw==
|
||||
|
||||
"@primer/octicons-react@^9.6.0":
|
||||
version "9.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@primer/octicons-react/-/octicons-react-9.6.0.tgz#996f621cb063757a4985cd6b45e59ed00e3444bf"
|
||||
integrity sha512-FR0fiU1UY1ds5ZMCUY+iVkkm1Eh4yDHf2ui+cxB3VvYX23DAdUAohPGit+qaMFy2caDd7uWYGRZduKS7dW1FZQ==
|
||||
dependencies:
|
||||
prop-types "^15.6.1"
|
||||
|
||||
"@primer/octicons@^9.1.1":
|
||||
version "9.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@primer/octicons/-/octicons-9.5.0.tgz#36e9422a6f790afde6b49a7d2d6daf1402076afd"
|
||||
|
|
@ -1807,10 +1843,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.2.tgz#0e58ae66773d7fd7c372a493aff740878ec9ceaa"
|
||||
integrity sha512-f8JzJNWVhKtc9dg/dyDNfliTKNOJSLa7Oht/ElZdF/UbMUmAH3rLmAk3ODNjw0mZajDEgatA03tRjB4+Dp/tzA==
|
||||
|
||||
"@types/puppeteer@^2.0.0":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-2.1.1.tgz#dfbec9de3db4328ec9b66ab2cbb1875033bc22f6"
|
||||
integrity sha512-FqPZvUtnpTGrqbHvPUn76pvVcBPEVEqZftrdOjr6YRkaaxkjKQ8dQLNaQBjER7Lvd1Q6+0R0XR+N3tYGWBSzNw==
|
||||
"@types/puppeteer@^3.0.2":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-3.0.2.tgz#20085220593b560c7332b6d46aecaf81ae263540"
|
||||
integrity sha512-JRuHPSbHZBadOxxFwpyZPeRlpPTTeMbQneMdpFd8LXdyNfFSiX950CGewdm69g/ipzEAXAmMyFF1WOWJOL/nKw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
|
|
@ -1855,25 +1891,15 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
|
||||
integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
|
||||
|
||||
"@types/styled-components@^4.4.0":
|
||||
version "4.4.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-4.4.3.tgz#74dd00ad760845a98890a8539361d8afc32059de"
|
||||
integrity sha512-U0udeNOZBfUkJycmGJwmzun0FBt11rZy08weVQmE2xfUNAbX8AGOEWxWna2d+qAUKxKgMlcG+TZT0+K2FfDcnQ==
|
||||
"@types/styled-components@^4.4.0", "@types/styled-components@^5.0.0", "@types/styled-components@^5.1.3":
|
||||
version "5.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.3.tgz#6fab3d9c8f7d9a15cbb89d379d850c985002f363"
|
||||
integrity sha512-HGpirof3WOhiX17lb61Q/tpgqn48jxO8EfZkdJ8ueYqwLbK2AHQe/G08DasdA2IdKnmwOIP1s9X2bopxKXgjRw==
|
||||
dependencies:
|
||||
"@types/hoist-non-react-statics" "*"
|
||||
"@types/react" "*"
|
||||
"@types/react-native" "*"
|
||||
csstype "^2.2.0"
|
||||
|
||||
"@types/styled-components@^5.0.1":
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.0.1.tgz#44d210b0a0218a70df998d1a8e1f69c82d9cc68b"
|
||||
integrity sha512-1yRYO1dAE2MGEuYKF1yQFeMdoyerIQn6ZDnFFkxZamcs3rn8RQVn98edPsTROAxbTz81tqnVN4BJ3Qs1cm/tKg==
|
||||
dependencies:
|
||||
"@types/hoist-non-react-statics" "*"
|
||||
"@types/react" "*"
|
||||
"@types/react-native" "*"
|
||||
csstype "^2.2.0"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/styled-system@5.1.2":
|
||||
version "5.1.2"
|
||||
|
|
@ -1882,12 +1908,12 @@
|
|||
dependencies:
|
||||
csstype "^2.6.4"
|
||||
|
||||
"@types/styled-system__css@^5.0.11":
|
||||
version "5.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/styled-system__css/-/styled-system__css-5.0.11.tgz#a9ff7e5d75e69a0d5ccff36acb4bbd491f1a9da9"
|
||||
integrity sha512-hUieAt4sFS7zwbdU9Vlnn/c3vkfhTMhyiccYGpUSX96nJ4BF3NjLIjMu3cQOYS5EX4gPkHJZhkfdw41ov1NjhQ==
|
||||
"@types/styled-system__css@^5.0.14":
|
||||
version "5.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/styled-system__css/-/styled-system__css-5.0.14.tgz#97559d823216d475f716fb5b8dd1766f2d3eeafa"
|
||||
integrity sha512-dvhSQ5upz6TqiQmWLNF0sqdoL5nTomza58vtTSklpE9lDS+5w/ew8PQ+HPSRaXMGrmPGUiL7F0vwryVdxHWfpA==
|
||||
dependencies:
|
||||
csstype "^2.6.6"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/testing-library__dom@*", "@types/testing-library__dom@^6.12.1":
|
||||
version "6.12.1"
|
||||
|
|
@ -1924,6 +1950,13 @@
|
|||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@types/yauzl@^2.9.1":
|
||||
version "2.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.1.tgz#d10f69f9f522eef3cf98e30afb684a1e1ec923af"
|
||||
integrity sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@webassemblyjs/ast@1.8.5":
|
||||
version "1.8.5"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359"
|
||||
|
|
@ -2235,13 +2268,6 @@ agent-base@5:
|
|||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c"
|
||||
integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==
|
||||
|
||||
agent-base@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
||||
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
|
||||
dependencies:
|
||||
es6-promisify "^5.0.0"
|
||||
|
||||
ajv-errors@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
|
||||
|
|
@ -2683,9 +2709,9 @@ babel-plugin-macros@2.8.0:
|
|||
resolve "^1.12.0"
|
||||
|
||||
"babel-plugin-styled-components@>= 1":
|
||||
version "1.10.7"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.7.tgz#3494e77914e9989b33cc2d7b3b29527a949d635c"
|
||||
integrity sha512-MBMHGcIA22996n9hZRf/UJLVVgkEOITuR2SvjHLb5dSTUyR4ZRGn+ngITapes36FI3WLxZHfRhkA1ffHxihOrg==
|
||||
version "1.11.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.11.1.tgz#5296a9e557d736c3186be079fff27c6665d63d76"
|
||||
integrity sha512-YwrInHyKUk1PU3avIRdiLyCpM++18Rs1NgyMXEAQC33rIXs/vro0A+stf4sT0Gf22Got+xRWB8Cm0tw+qkRzBA==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.0.0"
|
||||
"@babel/helper-module-imports" "^7.0.0"
|
||||
|
|
@ -2786,7 +2812,7 @@ balanced-match@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||
|
||||
base64-js@^1.0.2:
|
||||
base64-js@^1.0.2, base64-js@^1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
|
||||
integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
|
||||
|
|
@ -2844,6 +2870,15 @@ bl@^1.0.0:
|
|||
readable-stream "^2.3.5"
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
bl@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489"
|
||||
integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==
|
||||
dependencies:
|
||||
buffer "^5.5.0"
|
||||
inherits "^2.0.4"
|
||||
readable-stream "^3.4.0"
|
||||
|
||||
bluebird@^3.5.5:
|
||||
version "3.5.5"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
|
||||
|
|
@ -3077,6 +3112,14 @@ buffer@^5.1.0:
|
|||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
|
||||
buffer@^5.2.1, buffer@^5.5.0:
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.0.tgz#88afbd29fc89fa7b58e82b39206f31f2cf34feed"
|
||||
integrity sha512-cd+5r1VLBwUqTrmnzW+D7ABkJUM6mr7uv1dv+6jRw4Rcl7tFIFHDqHPL98LhpGFn3dbAt3gtLxtrWp4m1kFrqg==
|
||||
dependencies:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
builtin-status-codes@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||
|
|
@ -3538,7 +3581,7 @@ concat-map@0.0.1:
|
|||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
concat-stream@1.6.2, concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.5.2:
|
||||
concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.5.2:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
|
||||
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
|
||||
|
|
@ -3888,10 +3931,10 @@ csstype@^2.6.4:
|
|||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.9.tgz#05141d0cd557a56b8891394c1911c40c8a98d098"
|
||||
integrity sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==
|
||||
|
||||
csstype@^2.6.6:
|
||||
version "2.6.10"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b"
|
||||
integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w==
|
||||
csstype@^3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.3.tgz#2b410bbeba38ba9633353aff34b05d9755d065f8"
|
||||
integrity sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag==
|
||||
|
||||
cwd@^0.10.0:
|
||||
version "0.10.0"
|
||||
|
|
@ -3954,7 +3997,7 @@ debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
|
|||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^3.1.0, debug@^3.2.6:
|
||||
debug@^3.2.6:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
|
||||
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
|
||||
|
|
@ -4113,6 +4156,11 @@ detect-node@^2.0.4:
|
|||
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
|
||||
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
|
||||
|
||||
devtools-protocol@0.0.809251:
|
||||
version "0.0.809251"
|
||||
resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.809251.tgz#300b3366be107d5c46114ecb85274173e3999518"
|
||||
integrity sha512-pf+2OY6ghMDPjKkzSWxHMq+McD+9Ojmq5XVRYpv/kPd9sTMQxzEt21592a31API8qRjro0iYYOc3ag46qF/1FA==
|
||||
|
||||
diff-sequences@^24.9.0:
|
||||
version "24.9.0"
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
|
||||
|
|
@ -4350,6 +4398,13 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
|
|||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
end-of-stream@^1.4.1:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
end-of-stream@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.1.0.tgz#e9353258baa9108965efc41cb0ef8ade2f3cfb07"
|
||||
|
|
@ -4462,11 +4517,6 @@ es6-promise@^2.0.1:
|
|||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-2.3.0.tgz#96edb9f2fdb01995822b263dd8aadab6748181bc"
|
||||
integrity sha1-lu258v2wGZWCKyY92KratnSBgbw=
|
||||
|
||||
es6-promise@^4.0.3:
|
||||
version "4.2.8"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
|
||||
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
|
||||
|
||||
es6-promisify@6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.0.2.tgz#525c23725b8510f5f1f2feb5a1fbad93a93e29b4"
|
||||
|
|
@ -4477,13 +4527,6 @@ es6-promisify@6.1.0:
|
|||
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.1.0.tgz#32e3e7e796f924a6723f09ded24e71100ea57472"
|
||||
integrity sha512-jCsk2fpfEFusVv1MDkF4Uf0hAzIKNDMgR6LyOIw6a3jwkN1sCgWzuwgnsHY9YSQ8n8P31HoncvE0LC44cpWTrw==
|
||||
|
||||
es6-promisify@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
|
||||
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
|
||||
dependencies:
|
||||
es6-promise "^4.0.3"
|
||||
|
||||
es6-set@~0.1.5:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
|
||||
|
|
@ -4927,15 +4970,16 @@ extglob@^2.0.4:
|
|||
snapdragon "^0.8.1"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
extract-zip@^1.6.6:
|
||||
version "1.6.7"
|
||||
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9"
|
||||
integrity sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=
|
||||
extract-zip@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
|
||||
integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
|
||||
dependencies:
|
||||
concat-stream "1.6.2"
|
||||
debug "2.6.9"
|
||||
mkdirp "0.5.1"
|
||||
yauzl "2.4.1"
|
||||
debug "^4.1.1"
|
||||
get-stream "^5.1.0"
|
||||
yauzl "^2.10.0"
|
||||
optionalDependencies:
|
||||
"@types/yauzl" "^2.9.1"
|
||||
|
||||
extsprintf@1.3.0:
|
||||
version "1.3.0"
|
||||
|
|
@ -4996,13 +5040,6 @@ fb-watchman@^2.0.0:
|
|||
dependencies:
|
||||
bser "2.1.1"
|
||||
|
||||
fd-slicer@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65"
|
||||
integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=
|
||||
dependencies:
|
||||
pend "~1.2.0"
|
||||
|
||||
fd-slicer@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
|
||||
|
|
@ -5128,7 +5165,7 @@ find-up@^3.0.0:
|
|||
dependencies:
|
||||
locate-path "^3.0.0"
|
||||
|
||||
find-up@^4.1.0:
|
||||
find-up@^4.0.0, find-up@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
|
||||
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
|
||||
|
|
@ -5834,14 +5871,6 @@ https-browserify@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
|
||||
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
|
||||
|
||||
https-proxy-agent@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz#b8c286433e87602311b01c8ea34413d856a4af81"
|
||||
integrity sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==
|
||||
dependencies:
|
||||
agent-base "^4.3.0"
|
||||
debug "^3.1.0"
|
||||
|
||||
https-proxy-agent@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b"
|
||||
|
|
@ -5879,6 +5908,11 @@ icss-utils@^4.1.0:
|
|||
dependencies:
|
||||
postcss "^7.0.14"
|
||||
|
||||
ieee754@^1.1.13:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
||||
ieee754@^1.1.4:
|
||||
version "1.1.13"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
|
||||
|
|
@ -5958,7 +5992,7 @@ inflight@^1.0.4:
|
|||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
|
@ -7263,6 +7297,11 @@ lodash@^4.0.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.12,
|
|||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
|
||||
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
|
||||
|
||||
lodash@^4.17.19:
|
||||
version "4.17.20"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||
|
||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
|
|
@ -7572,18 +7611,23 @@ mixin-object@^2.0.1:
|
|||
for-in "^0.1.3"
|
||||
is-extendable "^0.1.1"
|
||||
|
||||
mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
|
||||
dependencies:
|
||||
minimist "0.0.8"
|
||||
mkdirp-classic@^0.5.2:
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
||||
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
||||
|
||||
mkdirp@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea"
|
||||
integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g==
|
||||
|
||||
mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
|
||||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
mkdirp@^0.5.3:
|
||||
version "0.5.5"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
||||
|
|
@ -7747,6 +7791,11 @@ node-fetch@^2.1.2:
|
|||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
|
||||
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
|
||||
|
||||
node-fetch@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
||||
node-forge@^0.7.1:
|
||||
version "0.7.6"
|
||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac"
|
||||
|
|
@ -8417,6 +8466,13 @@ pkg-dir@^3.0.0:
|
|||
dependencies:
|
||||
find-up "^3.0.0"
|
||||
|
||||
pkg-dir@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
|
||||
integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
|
||||
dependencies:
|
||||
find-up "^4.0.0"
|
||||
|
||||
pluralize@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"
|
||||
|
|
@ -8486,9 +8542,9 @@ postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1:
|
|||
integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
|
||||
|
||||
postcss-value-parser@^4.0.2:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d"
|
||||
integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
|
||||
integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
|
||||
|
||||
postcss@7.0.27:
|
||||
version "7.0.27"
|
||||
|
|
@ -8597,7 +8653,7 @@ prompts@^2.0.1, prompts@^2.3.0:
|
|||
kleur "^3.0.3"
|
||||
sisteransi "^1.0.4"
|
||||
|
||||
prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
|
|
@ -8686,19 +8742,23 @@ punycode@^2.1.0, punycode@^2.1.1:
|
|||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
puppeteer@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-2.0.0.tgz#0612992e29ec418e0a62c8bebe61af1a64d7ec01"
|
||||
integrity sha512-t3MmTWzQxPRP71teU6l0jX47PHXlc4Z52sQv4LJQSZLq1ttkKS2yGM3gaI57uQwZkNaoGd0+HPPMELZkcyhlqA==
|
||||
puppeteer@^5.4.1:
|
||||
version "5.4.1"
|
||||
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-5.4.1.tgz#f2038eb23a0f593ed2cce0d6e7cd5c43aecd6756"
|
||||
integrity sha512-8u6r9tFm3gtMylU4uCry1W/CeAA8uczKMONvGvivkTsGqKA7iB7DWO2CBFYlB9GY6/IEoq9vkI5slJWzUBkwNw==
|
||||
dependencies:
|
||||
debug "^4.1.0"
|
||||
extract-zip "^1.6.6"
|
||||
https-proxy-agent "^3.0.0"
|
||||
mime "^2.0.3"
|
||||
devtools-protocol "0.0.809251"
|
||||
extract-zip "^2.0.0"
|
||||
https-proxy-agent "^4.0.0"
|
||||
node-fetch "^2.6.1"
|
||||
pkg-dir "^4.2.0"
|
||||
progress "^2.0.1"
|
||||
proxy-from-env "^1.0.0"
|
||||
rimraf "^2.6.1"
|
||||
ws "^6.1.0"
|
||||
rimraf "^3.0.2"
|
||||
tar-fs "^2.0.0"
|
||||
unbzip2-stream "^1.3.3"
|
||||
ws "^7.2.3"
|
||||
|
||||
qs@6.7.0:
|
||||
version "6.7.0"
|
||||
|
|
@ -8788,15 +8848,14 @@ react-clientside-effect@^1.2.2:
|
|||
dependencies:
|
||||
"@babel/runtime" "^7.0.0"
|
||||
|
||||
react-dom@^16.13.0:
|
||||
version "16.13.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.0.tgz#cdde54b48eb9e8a0ca1b3dc9943d9bb409b81866"
|
||||
integrity sha512-y09d2c4cG220DzdlFkPTnVvGTszVvNpC73v+AaLGLHbkpy3SSgvYq8x0rNwPJ/Rk/CicTNgk0hbHNw1gMEZAXg==
|
||||
react-dom@^17.0.1:
|
||||
version "17.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.1.tgz#1de2560474ec9f0e334285662ede52dbc5426fc6"
|
||||
integrity sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.2"
|
||||
scheduler "^0.19.0"
|
||||
scheduler "^0.20.1"
|
||||
|
||||
react-fast-compare@^2.0.4:
|
||||
version "2.0.4"
|
||||
|
|
@ -8880,7 +8939,7 @@ react-window@^1.8.5:
|
|||
"@babel/runtime" "^7.0.0"
|
||||
memoize-one ">=3.1.1 <6"
|
||||
|
||||
react@^16.10.2, react@^16.13.0:
|
||||
react@^16.10.2:
|
||||
version "16.13.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.13.0.tgz#d046eabcdf64e457bbeed1e792e235e1b9934cf7"
|
||||
integrity sha512-TSavZz2iSLkq5/oiE7gnFzmURKZMltmi193rm5HEoUDAXpzT9Kzw6oNZnGoai/4+fUnm7FqS5dwgUL34TujcWQ==
|
||||
|
|
@ -8889,6 +8948,14 @@ react@^16.10.2, react@^16.13.0:
|
|||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
react@^17.0.1:
|
||||
version "17.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127"
|
||||
integrity sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
read-pkg-up@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978"
|
||||
|
|
@ -8928,6 +8995,15 @@ readable-stream@^3.1.1:
|
|||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
readable-stream@^3.4.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
readdirp@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
|
||||
|
|
@ -9425,10 +9501,10 @@ sax@>=0.6.0, sax@^1.2.4:
|
|||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
|
||||
scheduler@^0.19.0:
|
||||
version "0.19.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.0.tgz#a715d56302de403df742f4a9be11975b32f5698d"
|
||||
integrity sha512-xowbVaTPe9r7y7RUejcK73/j8tt2jfiyTednOvHbA8JoClvMYCp+r8QegLwK/n8zWQAtZb1fFnER4XLBZXrCxA==
|
||||
scheduler@^0.20.1:
|
||||
version "0.20.1"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.1.tgz#da0b907e24026b01181ecbc75efdc7f27b5a000c"
|
||||
integrity sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
|
@ -10139,14 +10215,14 @@ strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
|
|||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
||||
|
||||
styled-components@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.0.1.tgz#57782a6471031abefb2db5820a1876ae853bc619"
|
||||
integrity sha512-E0xKTRIjTs4DyvC1MHu/EcCXIj6+ENCP8hP01koyoADF++WdBUOrSGwU1scJRw7/YaYOhDvvoad6VlMG+0j53A==
|
||||
styled-components@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.2.0.tgz#6dcb5aa8a629c84b8d5ab34b7167e3e0c6f7ed74"
|
||||
integrity sha512-9qE8Vgp8C5cpGAIdFaQVAl89Zgx1TDM4Yf4tlHbO9cPijtpSXTMLHy9lmP0lb+yImhgPFb1AmZ1qMUubmg3HLg==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.0.0"
|
||||
"@babel/traverse" "^7.4.5"
|
||||
"@emotion/is-prop-valid" "^0.8.3"
|
||||
"@emotion/is-prop-valid" "^0.8.8"
|
||||
"@emotion/stylis" "^0.8.4"
|
||||
"@emotion/unitless" "^0.7.4"
|
||||
babel-plugin-styled-components ">= 1"
|
||||
|
|
@ -10256,6 +10332,16 @@ tapable@^1.0.0, tapable@^1.1.3:
|
|||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
|
||||
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
|
||||
|
||||
tar-fs@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.0.tgz#d1cdd121ab465ee0eb9ccde2d35049d3f3daf0d5"
|
||||
integrity sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==
|
||||
dependencies:
|
||||
chownr "^1.1.1"
|
||||
mkdirp-classic "^0.5.2"
|
||||
pump "^3.0.0"
|
||||
tar-stream "^2.0.0"
|
||||
|
||||
tar-stream@^1.5.0:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
|
||||
|
|
@ -10269,6 +10355,17 @@ tar-stream@^1.5.0:
|
|||
to-buffer "^1.1.1"
|
||||
xtend "^4.0.0"
|
||||
|
||||
tar-stream@^2.0.0:
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.4.tgz#c4fb1a11eb0da29b893a5b25476397ba2d053bfa"
|
||||
integrity sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==
|
||||
dependencies:
|
||||
bl "^4.0.3"
|
||||
end-of-stream "^1.4.1"
|
||||
fs-constants "^1.0.0"
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
tar@^4:
|
||||
version "4.4.11"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.11.tgz#7ac09801445a3cf74445ed27499136b5240ffb73"
|
||||
|
|
@ -10358,7 +10455,7 @@ through2@^2.0.0:
|
|||
readable-stream "~2.3.6"
|
||||
xtend "~4.0.1"
|
||||
|
||||
through@2, through@^2.3.6:
|
||||
through@2, through@^2.3.6, through@^2.3.8:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
||||
|
|
@ -10590,10 +10687,10 @@ typedarray@^0.0.6:
|
|||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@^3.7.2:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb"
|
||||
integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==
|
||||
typescript@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5"
|
||||
integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==
|
||||
|
||||
uglify-js@^3.6.0:
|
||||
version "3.6.0"
|
||||
|
|
@ -10618,6 +10715,14 @@ uglifyjs-webpack-plugin@^2.1.2:
|
|||
webpack-sources "^1.4.0"
|
||||
worker-farm "^1.7.0"
|
||||
|
||||
unbzip2-stream@^1.3.3:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7"
|
||||
integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==
|
||||
dependencies:
|
||||
buffer "^5.2.1"
|
||||
through "^2.3.8"
|
||||
|
||||
unicode-canonical-property-names-ecmascript@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
|
||||
|
|
@ -11252,13 +11357,18 @@ ws@^5.2.0:
|
|||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
|
||||
ws@^6.0.0, ws@^6.1.0:
|
||||
ws@^6.0.0:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
|
||||
integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
|
||||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
|
||||
ws@^7.2.3:
|
||||
version "7.3.1"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8"
|
||||
integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==
|
||||
|
||||
xdg-basedir@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
|
||||
|
|
@ -11409,7 +11519,7 @@ yargs@^13.3.0:
|
|||
y18n "^4.0.0"
|
||||
yargs-parser "^13.1.2"
|
||||
|
||||
yauzl@2.10.0:
|
||||
yauzl@2.10.0, yauzl@^2.10.0:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
|
||||
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
|
||||
|
|
@ -11417,13 +11527,6 @@ yauzl@2.10.0:
|
|||
buffer-crc32 "~0.2.3"
|
||||
fd-slicer "~1.1.0"
|
||||
|
||||
yauzl@2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005"
|
||||
integrity sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=
|
||||
dependencies:
|
||||
fd-slicer "~1.0.1"
|
||||
|
||||
zip-dir@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/zip-dir/-/zip-dir-1.0.2.tgz#253f907aead62a21acd8721d8b88032b2411c051"
|
||||
|
|
|
|||
Loading…
Reference in a new issue