From 2ba2d48f43a40c08cff4492a5889bbffe2a51aab Mon Sep 17 00:00:00 2001 From: Tan Nhu Date: Mon, 19 Jun 2023 22:36:01 +0000 Subject: [PATCH] Add support for rendering pdf, video, image and other binary files (#151) --- web/package.json | 1 + web/src/App.tsx | 4 +- web/src/AppContext.tsx | 3 +- web/src/AppProps.ts | 3 + web/src/bootstrap.tsx | 2 +- .../components/LatestCommit/LatestCommit.tsx | 13 +- web/src/framework/strings/stringTypes.ts | 3 + web/src/hooks/useDownloadRawFile.ts | 51 ++ web/src/i18n/strings.en.yaml | 3 + web/src/pages/Compare/Compare.tsx | 2 +- .../PullRequestActionsBox.tsx | 3 +- .../FileContent/FileContent.tsx | 214 ++++++-- web/src/utils/FileUtils.ts | 460 ++++++++++++++++++ web/src/utils/GitUtils.ts | 15 +- web/src/utils/Utils.ts | 26 +- web/yarn.lock | 275 ++++++++++- 16 files changed, 1023 insertions(+), 55 deletions(-) create mode 100644 web/src/hooks/useDownloadRawFile.ts create mode 100644 web/src/utils/FileUtils.ts diff --git a/web/package.json b/web/package.json index 6d08363bb..63c15f112 100644 --- a/web/package.json +++ b/web/package.json @@ -88,6 +88,7 @@ "react-keywords": "^0.0.5", "react-markdown": "^8.0.3", "react-monaco-editor": "^0.52.0", + "react-pdf": "^7.1.2", "react-resize-detector": "^7.1.2", "react-router-dom": "^5.2.0", "react-split-pane": "^0.1.92", diff --git a/web/src/App.tsx b/web/src/App.tsx index 0b46c75bd..e1c7ecbc9 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -37,7 +37,8 @@ const App: React.FC = React.memo(function App({ (): Partial => buildResfulReactRequestOptions(hooks?.useGetToken?.() || token), [token, hooks] ) - const queryParams = useMemo(() => (!standalone ? { routingId: space.split('/').shift() } : {}), [space, standalone]) + const routingId = useMemo(() => (standalone ? '' : space.split('/').shift() || ''), [standalone, space]) + const queryParams = useMemo(() => (!standalone ? { routingId } : {}), [standalone, routingId]) useEffect(() => { languageLoader(lang).then(setStrings) @@ -62,6 +63,7 @@ const App: React.FC = React.memo(function App({ ({ routes, hooks: {}, currentUser: defaultCurrentUser, - currentUserProfileURL: '' + currentUserProfileURL: '', + routingId: '' }) export const AppContextProvider: React.FC<{ value: AppProps }> = React.memo(function AppContextProvider({ diff --git a/web/src/AppProps.ts b/web/src/AppProps.ts index 9a036e4a8..54951c893 100644 --- a/web/src/AppProps.ts +++ b/web/src/AppProps.ts @@ -24,6 +24,9 @@ export interface AppProps { /** Flag to tell if App is mounted as a standalone app */ standalone: boolean + /** Harness routingId */ + routingId: string + /** App children. When provided, children is a remote view which will be mounted under App contexts */ children?: React.ReactNode diff --git a/web/src/bootstrap.tsx b/web/src/bootstrap.tsx index 6229e8ba5..7c9e286bf 100644 --- a/web/src/bootstrap.tsx +++ b/web/src/bootstrap.tsx @@ -11,6 +11,6 @@ import './bootstrap.scss' window.STRIP_CODE_PREFIX = true ReactDOM.render( - , + , document.getElementById('react-root') ) diff --git a/web/src/components/LatestCommit/LatestCommit.tsx b/web/src/components/LatestCommit/LatestCommit.tsx index 760fb255e..39a42fa22 100644 --- a/web/src/components/LatestCommit/LatestCommit.tsx +++ b/web/src/components/LatestCommit/LatestCommit.tsx @@ -7,7 +7,7 @@ import cx from 'classnames' import type { TypesCommit } from 'services/code' import { CommitActions } from 'components/CommitActions/CommitActions' import { useAppContext } from 'AppContext' -import { formatDate } from 'utils/Utils' +import { formatBytes, formatDate } from 'utils/Utils' import type { GitInfoProps } from 'utils/GitUtils' import { PipeSeparator } from 'components/PipeSeparator/PipeSeparator' import css from './LatestCommit.module.scss' @@ -15,6 +15,7 @@ import css from './LatestCommit.module.scss' interface LatestCommitProps extends Pick { latestCommit?: TypesCommit standaloneStyle?: boolean + size?: number } export function LatestCommitForFolder({ repoMetadata, latestCommit, standaloneStyle }: LatestCommitProps) { @@ -46,7 +47,7 @@ export function LatestCommitForFolder({ repoMetadata, latestCommit, standaloneSt ) } -export function LatestCommitForFile({ repoMetadata, latestCommit, standaloneStyle }: LatestCommitProps) { +export function LatestCommitForFile({ repoMetadata, latestCommit, standaloneStyle, size }: LatestCommitProps) { const { routes } = useAppContext() const commitURL = routes.toCODECommits({ repoPath: repoMetadata.path as string, @@ -72,6 +73,14 @@ export function LatestCommitForFile({ repoMetadata, latestCommit, standaloneStyl {formatDate(latestCommit?.author?.when as string)} + {size && size > 0 && ( + <> + + + {formatBytes(size)} + + + )} diff --git a/web/src/framework/strings/stringTypes.ts b/web/src/framework/strings/stringTypes.ts index bf46f5fea..63339f759 100644 --- a/web/src/framework/strings/stringTypes.ts +++ b/web/src/framework/strings/stringTypes.ts @@ -43,6 +43,7 @@ export interface StringsMap { checkRuns: string checkSuites: string checks: string + clickHereToDownload: string clone: string cloneHTTPS: string cloneText: string @@ -131,6 +132,7 @@ export interface StringsMap { failedToDeleteBranch: string failedToDeleteWebhook: string fileDeleted: string + fileTooLarge: string files: string filesChanged: string findATag: string @@ -192,6 +194,7 @@ export interface StringsMap { open: string optional: string optionalExtendedDescription: string + overview: string pageLoading: string pageNotFound: string password: string diff --git a/web/src/hooks/useDownloadRawFile.ts b/web/src/hooks/useDownloadRawFile.ts new file mode 100644 index 000000000..b517c54d8 --- /dev/null +++ b/web/src/hooks/useDownloadRawFile.ts @@ -0,0 +1,51 @@ +import { useCallback, useEffect, useState } from 'react' +import { useToaster } from '@harness/uicore' +import { useGet } from 'restful-react' +import { getErrorMessage } from 'utils/Utils' +import type { GitInfoProps } from 'utils/GitUtils' + +interface UseDownloadRawFileParams extends Pick { + filename: string +} + +export function useDownloadRawFile() { + const { error, response, refetch } = useGet({ + path: '', + lazy: true + }) + const [name, setName] = useState('') + const { showError } = useToaster() + const callback = useCallback(async () => { + if (response) { + const imageBlog = await response.blob() + const imageURL = URL.createObjectURL(imageBlog) + + const anchor = document.createElement('a') + anchor.href = imageURL + anchor.download = name + + document.body.appendChild(anchor) + anchor.click() + document.body.removeChild(anchor) + + URL.revokeObjectURL(imageURL) + } + }, [name, response]) + + useEffect(() => { + if (error) { + showError(getErrorMessage(error)) + } else if (response) { + callback() + } + }, [error, showError, response, callback]) + + return useCallback( + ({ repoMetadata, resourcePath, gitRef, filename = 'download' }: UseDownloadRawFileParams) => { + const rawURL = `/api/v1/repos/${repoMetadata?.path}/+/raw/${resourcePath}` + setName(filename) + refetch({ path: rawURL, queryParams: { git_ref: gitRef } }) + }, + [refetch] + ) +} diff --git a/web/src/i18n/strings.en.yaml b/web/src/i18n/strings.en.yaml index bf81b72f9..7b81de33b 100644 --- a/web/src/i18n/strings.en.yaml +++ b/web/src/i18n/strings.en.yaml @@ -419,6 +419,9 @@ tagger: Tagger confirmDelete: Confirm delete tagEmpty: Here is no Tag. Try to newTag: New Tag +overview: Overview +fileTooLarge: File is too large to open. {download} +clickHereToDownload: Click here to download. viewFile: View the file at this point in the history viewRepo: View the repository at this point in the history hideCommitHistory: Hide Rename History for {{file}} diff --git a/web/src/pages/Compare/Compare.tsx b/web/src/pages/Compare/Compare.tsx index f0366f64b..55858156f 100644 --- a/web/src/pages/Compare/Compare.tsx +++ b/web/src/pages/Compare/Compare.tsx @@ -223,7 +223,7 @@ export default function Compare() { tabList={[ { id: 'general', - title: , + title: , panel: ( diff --git a/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.tsx b/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.tsx index 0f8ed5c86..c0f2e3a29 100644 --- a/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.tsx +++ b/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.tsx @@ -78,6 +78,7 @@ export const PullRequestActionsBox: React.FC = ({ ) const isClosed = pullRequestMetadata.state === PullRequestState.CLOSED const isOpen = pullRequestMetadata.state === PullRequestState.OPEN + const isConflict = pullRequestMetadata.merge_check_status === MergeCheckStatus.CONFLICT const unchecked = useMemo( () => pullRequestMetadata.merge_check_status === MergeCheckStatus.UNCHECKED && !isClosed, [pullRequestMetadata, isClosed] @@ -287,7 +288,7 @@ export const PullRequestActionsBox: React.FC = ({ })}> ) { const { routes } = useAppContext() const { getString } = useStrings() + const downloadFile = useDownloadRawFile() + const { category, isFileTooLarge, isViewable, filename, extension, size, base64Data, rawURL } = + useFileContentViewerDecision({ repoMetadata, gitRef, resourcePath, resourceContent }) const history = useHistory() const [activeTab, setActiveTab] = React.useState(FileSection.CONTENT) @@ -83,7 +91,7 @@ export function FileContent({ const { standalone } = useAppContext() const { hooks } = useAppContext() const space = useGetSpaceParam() - + const isATextFile = category === FileCategory.TEXT const permPushResult = hooks?.usePermissionTranslate?.( { resource: { @@ -106,6 +114,19 @@ export function FileContent({ } return { disabled: isRefATag(gitRef) || false, tooltip: undefined } }, [permPushResult, gitRef]) // eslint-disable-line react-hooks/exhaustive-deps + const [pdfWidth, setPdfWidth] = useState(700) + const ref = useRef(null) + const [numPages, setNumPages] = useState() + + useEffect(() => { + if (ref.current) { + const width = Math.min(Math.max(ref.current.clientWidth - 100, 700), 1800) + + if (pdfWidth !== width) { + setPdfWidth(width) + } + } + }, [pdfWidth, ref.current?.clientWidth]) const [page] = usePageIndex() const { data: commits } = useGet<{ commits: TypesCommit[]; rename_details: RenameDetails[] }>({ @@ -120,7 +141,7 @@ export function FileContent({ }) return ( - + @@ -155,7 +177,7 @@ export function FileContent({ icon="code-edit" tooltipProps={{ isDark: true }} tooltip={permsFinal.tooltip} - disabled={permsFinal.disabled} + disabled={permsFinal.disabled || !isATextFile} onClick={() => { history.push( routes.toCODEFileEdit({ @@ -177,24 +199,14 @@ export function FileContent({ hasIcon: true, iconName: 'arrow-right', text: getString('viewRaw'), - onClick: () => { - window.open( - `/code/api/v1/repos/${ - repoMetadata?.path - }/+/raw/${resourcePath}?${`git_ref=${gitRef}`}`, - '_blank' - ) - } + onClick: () => window.open(rawURL, '_blank') // TODO: This is still not working due to token is not stored in cookies }, '-', { hasIcon: true, iconName: 'cloud-download', text: getString('download'), - download: resourceContent?.name || 'download', - href: `/code/api/v1/repos/${ - repoMetadata?.path - }/+/raw/${resourcePath}?${`git_ref=${gitRef}`}` + onClick: () => downloadFile({ repoMetadata, resourcePath, gitRef, filename }) }, { hasIcon: true, @@ -219,18 +231,154 @@ export function FileContent({ - - - - - - + + +
+ { + Utils.stopEvent(e) + downloadFile({ repoMetadata, resourcePath, gitRef, filename }) + }}> + + + {getString('download')} + + +
+
+ + + +
+ + + setNumPages(nextNumPages)}> + {Array.from(new Array(numPages), (_el, index) => ( + + ))} + + + + + + + + + + { + Utils.stopEvent(e) + downloadFile({ repoMetadata, resourcePath, gitRef, filename }) + }}> + + + {getString('clickHereToDownload')} + + + ) + }} + /> + + +
+
+ + + + + + +
+ + + {filename} + + + {filename} + + + setNumPages(nextNumPages)}> + {Array.from(new Array(numPages), (_el, index) => ( + + ))} + + + + + + + + + + + + +
+
+
+
+
+
+
@@ -286,3 +434,9 @@ export function FileContent({
) } + +const Center: React.FC = ({ children }) => ( + + {children} + +) diff --git a/web/src/utils/FileUtils.ts b/web/src/utils/FileUtils.ts new file mode 100644 index 000000000..7a754af8b --- /dev/null +++ b/web/src/utils/FileUtils.ts @@ -0,0 +1,460 @@ +import { useEffect, useMemo } from 'react' +import { pdfjs } from 'react-pdf' +import { useAppContext } from 'AppContext' +import type { RepoFileContent } from 'services/code' +import type { GitInfoProps } from './GitUtils' + +// TODO: Configure this to use a local worker/webpack loader +// Maybe use pdfjs directly: https://github.com/mozilla/pdf.js/blob/master/examples/webpack/webpack.config.js +pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.js` + +type UseFileViewerDecisionProps = Pick + +interface UseFileViewerDecisionResult { + category: FileCategory + isFileTooLarge: boolean + isViewable: string | boolean + filename: string + extension: string + size: number + base64Data: string + rawURL: string +} + +export function useFileContentViewerDecision({ + repoMetadata, + gitRef, + resourcePath, + resourceContent +}: UseFileViewerDecisionProps): UseFileViewerDecisionResult { + const { routingId } = useAppContext() + const metadata = useMemo(() => { + const filename = resourceContent.name as string + const extension = filename?.split('.').pop() || '' + const isMarkdown = extension.toLowerCase() === 'md' + const isPdf = extension.toLowerCase() === 'pdf' + const isSVG = extension.toLowerCase() === 'svg' + const isImage = ImageExtensions.includes(extension.toLowerCase()) + const isAudio = AudioExtensions.includes(extension.toLowerCase()) + const isVideo = VideoExtensions.includes(extension.toLowerCase()) + const isText = + SpecialTextFiles.find(name => name.toLowerCase() === filename?.toLowerCase()) || + TextExtensions.includes(extension.toLowerCase()) + const category = isMarkdown + ? FileCategory.MARKDOWN + : isSVG + ? FileCategory.SVG + : isPdf + ? FileCategory.PDF + : isImage + ? FileCategory.IMAGE + : isAudio + ? FileCategory.AUDIO + : isVideo + ? FileCategory.VIDEO + : isText + ? FileCategory.TEXT + : FileCategory.OTHER + const isViewable = isPdf || isSVG || isImage || isAudio || isVideo || isText + const resourceData = resourceContent?.content as RepoFileContent + const isFileTooLarge = resourceData?.size !== resourceData?.data_size + const rawURL = `/code/api/v1/repos/${repoMetadata?.path}/+/raw/${resourcePath}?routingId=${routingId}&git_ref=${gitRef}` + + // TODO: TEST ONLY + // const rawURL = `https://localhost:8181/rawfile/${filename}` + + return { + category, + + isFileTooLarge, + isViewable, + + filename, + extension, + size: resourceData?.size || 0, + + // base64 data returned from content API. This snapshot can be truncated by backend + base64Data: resourceData?.data || '', + rawURL + } + }, []) // eslint-disable-line react-hooks/exhaustive-deps + + useEffect(() => { + switch (metadata.category) { + case FileCategory.SVG: + case FileCategory.PDF: + case FileCategory.IMAGE: + case FileCategory.AUDIO: + case FileCategory.VIDEO: + case FileCategory.TEXT: + break + default: + break + } + }, []) // eslint-disable-line react-hooks/exhaustive-deps + + return metadata +} + +export const MAX_VIEWABLE_FILE_SIZE = 100 * 1024 * 1024 // 100 MB + +export enum FileCategory { + MARKDOWN = 'MARKDOWN', + SVG = 'SVG', + PDF = 'PDF', + IMAGE = 'IMAGE', + AUDIO = 'AUDIO', + VIDEO = 'VIDEO', + TEXT = 'TEXT', + OTHER = 'OTHER' +} + +// Parts are copied from https://github.com/sindresorhus/text-extensions +// MIT License +// Copyright (c) Sindre Sorhus (https://sindresorhus.com) +const TextExtensions = [ + 'ada', + 'adb', + 'ads', + 'applescript', + 'as', + 'asc', + 'ascii', + 'ascx', + 'asm', + 'asmx', + 'asp', + 'aspx', + 'atom', + 'au3', + 'awk', + 'bas', + 'bash', + 'bashrc', + 'bat', + 'bbcolors', + 'bcp', + 'bdsgroup', + 'bdsproj', + 'bib', + 'bowerrc', + 'c', + 'cbl', + 'cc', + 'cfc', + 'cfg', + 'cfm', + 'cfml', + 'cgi', + 'cjs', + 'clj', + 'cljs', + 'cls', + 'cmake', + 'cmd', + 'cnf', + 'cob', + 'code-snippets', + 'coffee', + 'coffeekup', + 'conf', + 'cp', + 'cpp', + 'cpt', + 'cpy', + 'crt', + 'cs', + 'csh', + 'cson', + 'csproj', + 'csr', + 'css', + 'csslintrc', + 'csv', + 'ctl', + 'curlrc', + 'cxx', + 'd', + 'dart', + 'dfm', + 'diff', + 'dof', + 'dpk', + 'dpr', + 'dproj', + 'dtd', + 'eco', + 'editorconfig', + 'ejs', + 'el', + 'elm', + 'emacs', + 'eml', + 'ent', + 'erb', + 'erl', + 'eslintignore', + 'eslintrc', + 'ex', + 'exs', + 'f', + 'f03', + 'f77', + 'f90', + 'f95', + 'fish', + 'for', + 'fpp', + 'frm', + 'fs', + 'fsproj', + 'fsx', + 'ftn', + 'gemrc', + 'gemspec', + 'gitattributes', + 'gitconfig', + 'gitignore', + 'gitkeep', + 'gitmodules', + 'go', + 'gpp', + 'gradle', + 'graphql', + 'groovy', + 'groupproj', + 'grunit', + 'gtmpl', + 'gvimrc', + 'h', + 'haml', + 'hbs', + 'hgignore', + 'hh', + 'hpp', + 'hrl', + 'hs', + 'hta', + 'htaccess', + 'htc', + 'htm', + 'html', + 'htpasswd', + 'hxx', + 'iced', + 'iml', + 'inc', + 'inf', + 'info', + 'ini', + 'ino', + 'int', + 'irbrc', + 'itcl', + 'itermcolors', + 'itk', + 'jade', + 'java', + 'jhtm', + 'jhtml', + 'js', + 'jscsrc', + 'jshintignore', + 'jshintrc', + 'json', + 'json5', + 'jsonld', + 'jsp', + 'jspx', + 'jsx', + 'ksh', + 'less', + 'lhs', + 'lisp', + 'log', + 'ls', + 'lsp', + 'lua', + 'm', + 'm4', + 'mak', + 'map', + 'markdown', + 'master', + 'md', + 'mdown', + 'mdwn', + 'mdx', + 'metadata', + 'mht', + 'mhtml', + 'mjs', + 'mk', + 'mkd', + 'mkdn', + 'mkdown', + 'ml', + 'mli', + 'mm', + 'mxml', + 'nfm', + 'nfo', + 'noon', + 'npmignore', + 'npmrc', + 'nuspec', + 'nvmrc', + 'ops', + 'pas', + 'pasm', + 'patch', + 'pbxproj', + 'pch', + 'pem', + 'pg', + 'php', + 'php3', + 'php4', + 'php5', + 'phpt', + 'phtml', + 'pir', + 'pl', + 'pm', + 'pmc', + 'pod', + 'pot', + 'prettierrc', + 'properties', + 'props', + 'pt', + 'pug', + 'purs', + 'py', + 'pyx', + 'r', + 'rake', + 'rb', + 'rbw', + 'rc', + 'rdoc', + 'rdoc_options', + 'resx', + 'rexx', + 'rhtml', + 'rjs', + 'rlib', + 'ron', + 'rs', + 'rss', + 'rst', + 'rtf', + 'rvmrc', + 'rxml', + 's', + 'sass', + 'scala', + 'scm', + 'scss', + 'seestyle', + 'sh', + 'shtml', + 'sln', + 'sls', + 'spec', + 'sql', + 'sqlite', + 'sqlproj', + 'srt', + 'ss', + 'sss', + 'st', + 'strings', + 'sty', + 'styl', + 'stylus', + 'sub', + 'sublime-build', + 'sublime-commands', + 'sublime-completions', + 'sublime-keymap', + 'sublime-macro', + 'sublime-menu', + 'sublime-project', + 'sublime-settings', + 'sublime-workspace', + 'sv', + 'svc', + 'svg', + 'swift', + 't', + 'tcl', + 'tcsh', + 'terminal', + 'tex', + 'text', + 'textile', + 'tg', + 'tk', + 'tmLanguage', + 'tmpl', + 'tmTheme', + 'tpl', + 'ts', + 'tsv', + 'tsx', + 'tt', + 'tt2', + 'ttml', + 'twig', + 'txt', + 'v', + 'vb', + 'vbproj', + 'vbs', + 'vcproj', + 'vcxproj', + 'vh', + 'vhd', + 'vhdl', + 'vim', + 'viminfo', + 'vimrc', + 'vm', + 'vue', + 'webapp', + 'webmanifest', + 'wsc', + 'x-php', + 'xaml', + 'xht', + 'xhtml', + 'xml', + 'xs', + 'xsd', + 'xsl', + 'xslt', + 'y', + 'yaml', + 'yml', + 'zsh', + 'zshrc', + 'ics' +] + +const SpecialTextFiles = [ + 'Dockerfile', + '.gitignore', + 'yarn.lock', + 'README', + 'LICENSE', + 'CHANGELOG', + 'Makefile', + 'Procfile' +] + +const ImageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'ico', 'bmp'] + +const VideoExtensions = ['ogg', 'mp4', 'webm', 'mpeg'] + +const AudioExtensions = ['mp3', 'wav'] diff --git a/web/src/utils/GitUtils.ts b/web/src/utils/GitUtils.ts index 9e31b1878..31c056ea3 100644 --- a/web/src/utils/GitUtils.ts +++ b/web/src/utils/GitUtils.ts @@ -149,4 +149,17 @@ export const diffRefsToRefs = (diffRefs: string) => { } } -export const decodeGitContent = (content = '') => decodeURIComponent(escape(window.atob(content))) +export const decodeGitContent = (content = '') => { + try { + // Decode base64 content for text file + return decodeURIComponent(escape(window.atob(content))) + } catch (_exception) { + try { + // Return original base64 content for binary file + return content + } catch (exception) { + console.error(exception) // eslint-disable-line no-console + } + } + return '' +} diff --git a/web/src/utils/Utils.ts b/web/src/utils/Utils.ts index 76787ed94..6254ec695 100644 --- a/web/src/utils/Utils.ts +++ b/web/src/utils/Utils.ts @@ -40,8 +40,8 @@ export function generateAlphaNumericHash(length: number) { export const dayAgoInMS = 86400000 -export const getErrorMessage = (error: Unknown): string => - get(error, 'data.error', get(error, 'data.message', get(error, 'message', error))) +export const getErrorMessage = (error: Unknown): string | undefined => + error ? get(error, 'data.error', get(error, 'data.message', get(error, 'message', error))) : undefined export interface PageBrowserProps { page: string @@ -254,5 +254,25 @@ export const voidFn = (f: Function) => () => { export enum MergeCheckStatus { MERGEABLE = 'mergeable', - UNCHECKED = 'unchecked' + UNCHECKED = 'unchecked', + CONFLICT = 'conflict' +} + +/** + * Convert number of bytes into human readable format + * + * @param integer bytes Number of bytes to convert + * @param integer precision Number of digits after the decimal separator + * @return string + * @link https://stackoverflow.com/a/18650828/1114931 + */ +export function formatBytes(bytes: number, decimals = 2) { + if (!+bytes) return '0 Bytes' + + const k = 1024 + const dm = decimals < 0 ? 0 : decimals + const sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] + const i = Math.floor(Math.log(bytes) / Math.log(k)) + + return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}` } diff --git a/web/yarn.lock b/web/yarn.lock index 37d0dc39a..94ed34239 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -1144,6 +1144,21 @@ "@lezer/highlight" "^1.0.0" "@lezer/lr" "^1.0.0" +"@mapbox/node-pre-gyp@^1.0.0": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c" + integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA== + dependencies: + detect-libc "^2.0.0" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.7" + nopt "^5.0.0" + npmlog "^5.0.1" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.11" + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -2761,6 +2776,11 @@ append-transform@^2.0.0: dependencies: default-require-extensions "^3.0.0" +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -2771,6 +2791,14 @@ archy@^1.0.0: resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -3533,6 +3561,15 @@ canonicalize@^1.0.1: resolved "https://registry.yarnpkg.com/canonicalize/-/canonicalize-1.0.8.tgz#24d1f1a00ed202faafd9bf8e63352cd4450c6df1" integrity sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A== +canvas@^2.11.2: + version "2.11.2" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.11.2.tgz#553d87b1e0228c7ac0fc72887c3adbac4abbd860" + integrity sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.0" + nan "^2.17.0" + simple-get "^3.0.3" + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -3654,6 +3691,11 @@ chownr@^1.1.1: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + chrome-launcher@^0.13.4: version "0.13.4" resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.13.4.tgz#4c7d81333c98282899c4e38256da23e00ed32f73" @@ -3832,7 +3874,7 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== -clsx@^1.1.1: +clsx@^1.1.1, clsx@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== @@ -3889,6 +3931,11 @@ color-name@^1.1.4, color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + colorette@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" @@ -4055,6 +4102,11 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -4459,6 +4511,13 @@ decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + deep-equal@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" @@ -4580,6 +4639,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -4618,6 +4682,11 @@ details-element-polyfill@^2.4.0: resolved "https://registry.yarnpkg.com/details-element-polyfill/-/details-element-polyfill-2.4.0.tgz#e0622adef7902662faf27b4ab8acba5dc4e3a6e6" integrity sha512-jnZ/m0+b1gz3EcooitqL7oDEkKHEro659dt8bWB/T/HjiILucoQhHvvi5MEOAIFJXxxO+rIYJ/t3qCgfUOSU5g== +detect-libc@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" + integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -5942,6 +6011,13 @@ fs-extra@^9.0.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + fs-monkey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" @@ -6000,6 +6076,21 @@ functions-have-names@^1.2.2, functions-have-names@^1.2.3: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -6335,6 +6426,11 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -8642,6 +8738,11 @@ lz-string@^1.4.4, lz-string@^1.5.0: resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== +make-cancellable-promise@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/make-cancellable-promise/-/make-cancellable-promise-1.3.1.tgz#3bd89704c75afe6251cdd6a82baca1fcfbd2c792" + integrity sha512-DWOzWdO3xhY5ESjVR+wVFy03rpt0ZccS4bunccNwngoX6rllKlMZm6S9ZnJ5nMuDDweqDMjtaO0g6tZeh+cCUA== + make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" @@ -8657,7 +8758,7 @@ make-dir@^2.0.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.0, make-dir@^3.0.2: +make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -8669,6 +8770,11 @@ make-error@1.x, make-error@^1.1.1: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== +make-event-props@^1.5.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/make-event-props/-/make-event-props-1.6.1.tgz#1d587017c3f1f3b42719b775af93d5253656ccdd" + integrity sha512-JhvWq/iz1BvlmnPvLJjXv+xnMPJZuychrDC68V+yCGQJn5chcA8rLGKo5EP1XwIKVrigSXKLmbeXAGkf36wdCQ== + makeerror@1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" @@ -8955,6 +9061,13 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== +merge-refs@^1.1.3: + version "1.2.1" + resolved "https://registry.yarnpkg.com/merge-refs/-/merge-refs-1.2.1.tgz#abddc800375395a4a4eb5c45ebf2a52557fdbe34" + integrity sha512-pRPz39HQz2xzHdXAGvtJ9S8aEpNgpUjzb5yPC3ytozodmsHg+9nqgRs7/YOmn9fM/TLzntAC8AdGTidKxOq9TQ== + dependencies: + "@types/react" "*" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -9312,6 +9425,11 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + min-indent@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" @@ -9355,6 +9473,26 @@ minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" @@ -9384,7 +9522,7 @@ mkdirp@0.3.0: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" integrity sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew== -mkdirp@1.x, mkdirp@^1.0.4: +mkdirp@1.x, mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -9510,7 +9648,7 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.12.1: +nan@^2.12.1, nan@^2.17.0: version "2.17.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== @@ -9582,6 +9720,13 @@ node-fetch-h2@^2.3.0: dependencies: http2-client "^1.2.5" +node-fetch@^2.6.7: + version "2.6.11" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" + integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== + dependencies: + whatwg-url "^5.0.0" + node-forge@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" @@ -9672,6 +9817,13 @@ nopt@1.0.10: dependencies: abbrev "1" +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -9738,6 +9890,16 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + nth-check@^2.0.0, nth-check@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" @@ -10372,6 +10534,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +path2d-polyfill@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz#24c554a738f42700d6961992bf5f1049672f2391" + integrity sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA== + pbkdf2@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" @@ -10383,6 +10550,16 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +pdfjs-dist@3.6.172: + version "3.6.172" + resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-3.6.172.tgz#f9efdfc5e850e1fecfc70b7f6f45c5dc990d8096" + integrity sha512-bfOhCg+S9DXh/ImWhWYTOiq3aVMFSCvzGiBzsIJtdMC71kVWDBw7UXr32xh0y56qc5wMVylIeqV3hBaRsu+e+w== + dependencies: + path2d-polyfill "^2.0.1" + web-streams-polyfill "^3.2.1" + optionalDependencies: + canvas "^2.11.2" + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -10974,6 +11151,20 @@ react-monaco-editor@*, react-monaco-editor@^0.52.0: dependencies: prop-types "^15.8.1" +react-pdf@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/react-pdf/-/react-pdf-7.1.2.tgz#c6979cff9ac09c3e5ab7ea9e0182f79a499768e5" + integrity sha512-hmTUKh3WVYDJlP8XvebGN8HH0Gk/tXh9WgNAtvdHn79FHL78UEPSbVj3veHHGqmMa2hz1wJCItLUqGVP68Qsjw== + dependencies: + clsx "^1.2.1" + make-cancellable-promise "^1.0.0" + make-event-props "^1.5.0" + merge-refs "^1.1.3" + pdfjs-dist "3.6.172" + prop-types "^15.6.2" + tiny-invariant "^1.0.0" + tiny-warning "^1.0.0" + react-popper@^1.3.7: version "1.3.11" resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.11.tgz#a2cc3f0a67b75b66cfa62d2c409f9dd1fcc71ffd" @@ -12039,6 +12230,20 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + sirv@^1.0.7: version "1.0.19" resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" @@ -12386,15 +12591,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -12403,6 +12600,14 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2 is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string.prototype.matchall@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" @@ -12655,6 +12860,18 @@ tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar@^6.1.11: + version "6.1.15" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.15.tgz#c9738b0b98845a3b344d334b8fa3041aaba53a69" + integrity sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" @@ -12774,7 +12991,7 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" -tiny-invariant@^1.0.2: +tiny-invariant@^1.0.0, tiny-invariant@^1.0.2: version "1.3.1" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== @@ -12888,6 +13105,11 @@ tr46@^2.1.0: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + trim-lines@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" @@ -13617,6 +13839,16 @@ web-namespaces@^2.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692" integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== +web-streams-polyfill@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + webidl-conversions@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" @@ -13838,6 +14070,14 @@ whatwg-mimetype@^2.3.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^8.0.0, whatwg-url@^8.5.0: version "8.7.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" @@ -13899,6 +14139,13 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + widest-line@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc"