From 619fd2c9de4e6c90bd579fbcc0e180bf4fc25da2 Mon Sep 17 00:00:00 2001 From: Tan Nhu Date: Mon, 12 Dec 2022 16:39:14 -0800 Subject: [PATCH] Add PR listing page + Commits tab for PR detail page (#123) * Add PR listing page + Commits tab for PR detail page * Add commits place-holder in Compare view * Add commits place-holder in Compare view * Correct PR number after creation * Minor CSS improvement * Add diff sample * Diff side by side (3.4.2 is better than latest) * Big PR diff example * Implement diff view * Scrolling optimization * Add placeholder to allow click at line number --- web/package.json | 2 + web/src/RouteDefinitions.ts | 14 +- .../CommitDivergence/CommitDivergence.tsx | 3 +- .../CommitsView/CommitsView.module.scss} | 0 .../CommitsView/CommitsView.module.scss.d.ts} | 0 .../CommitsView/CommitsView.tsx} | 6 +- .../ContainerSpinner.module.scss | 8 + .../ContainerSpinner.module.scss.d.ts | 6 + .../ContainerSpinner/ContainerSpinner.tsx | 12 + .../DiffViewer/DiffViewer.module.scss | 106 + .../DiffViewer/DiffViewer.module.scss.d.ts | 12 + web/src/components/DiffViewer/DiffViewer.tsx | 285 + .../StringSubstitute/StringSubstitute.tsx | 66 - web/src/framework/strings/stringTypes.ts | 19 + web/src/hooks/useUserPreference.ts | 19 + web/src/i18n/strings.en.yaml | 19 + web/src/pages/Compare/Compare.tsx | 29 +- .../CompareContentHeader.tsx | 2 +- .../pages/PullRequest/PullRequest.module.scss | 20 +- .../PullRequest/PullRequest.module.scss.d.ts | 1 + web/src/pages/PullRequest/PullRequest.tsx | 51 +- .../PullRequestCommits.module.scss.d.ts | 6 + .../PullRequestCommits/PullRequestCommits.tsx | 28 +- .../PullRequestConversation.tsx | 16 +- .../PullRequestDiff.module.scss | 52 +- .../PullRequestDiff.module.scss.d.ts | 12 + .../PullRequestDiff/PullRequestDiff.tsx | 231 +- .../PullRequest/PullRequestDiff/example.diff | 31177 ++++++++++++++++ .../PullRequest/PullRequestDiff/example2.diff | 358 + .../PullRequestMetaLine.module.scss | 43 + ...s => PullRequestMetaLine.module.scss.d.ts} | 3 + .../pages/PullRequest/PullRequestMetaLine.tsx | 87 + .../PullRequestMetadataInfo.module.scss | 25 - .../PullRequest/PullRequestMetadataInfo.tsx | 46 - .../PullRequestTabContentWrapper.tsx | 30 + .../PullRequests/PullRequests.module.scss | 12 + .../PullRequests.module.scss.d.ts | 3 + web/src/pages/PullRequests/PullRequests.tsx | 116 +- .../PullRequestsContentHeader.module.scss | 16 + ...PullRequestsContentHeader.module.scss.d.ts | 7 + .../PullRequestsContentHeader.tsx | 78 + .../PullRequests/pull-request-failed.svg | 7 + .../pages/PullRequests/pull-request-open.svg | 8 + .../RepositoryCommits/RepositoryCommits.tsx | 4 +- .../CreateWebhookForm.tsx | 1 - .../RepositoryCreateWebhook.tsx | 30 +- .../RepositoryCreateWebhookHeader.tsx | 35 - web/src/utils/GitUtils.ts | 14 + web/src/utils/Utils.ts | 26 +- web/yarn.lock | 42 +- 50 files changed, 32936 insertions(+), 257 deletions(-) rename web/src/{pages/RepositoryCommits/RepositoryCommitsContent/CommitsContent/CommitsContent.module.scss => components/CommitsView/CommitsView.module.scss} (100%) rename web/src/{pages/RepositoryCommits/RepositoryCommitsContent/CommitsContent/CommitsContent.module.scss.d.ts => components/CommitsView/CommitsView.module.scss.d.ts} (100%) rename web/src/{pages/RepositoryCommits/RepositoryCommitsContent/CommitsContent/CommitsContent.tsx => components/CommitsView/CommitsView.tsx} (93%) create mode 100644 web/src/components/ContainerSpinner/ContainerSpinner.module.scss create mode 100644 web/src/components/ContainerSpinner/ContainerSpinner.module.scss.d.ts create mode 100644 web/src/components/ContainerSpinner/ContainerSpinner.tsx create mode 100644 web/src/components/DiffViewer/DiffViewer.module.scss create mode 100644 web/src/components/DiffViewer/DiffViewer.module.scss.d.ts create mode 100644 web/src/components/DiffViewer/DiffViewer.tsx delete mode 100644 web/src/components/StringSubstitute/StringSubstitute.tsx create mode 100644 web/src/hooks/useUserPreference.ts create mode 100644 web/src/pages/PullRequest/PullRequestCommits/PullRequestCommits.module.scss.d.ts create mode 100644 web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.module.scss.d.ts create mode 100644 web/src/pages/PullRequest/PullRequestDiff/example.diff create mode 100644 web/src/pages/PullRequest/PullRequestDiff/example2.diff create mode 100644 web/src/pages/PullRequest/PullRequestMetaLine.module.scss rename web/src/pages/PullRequest/{PullRequestMetadataInfo.module.scss.d.ts => PullRequestMetaLine.module.scss.d.ts} (71%) create mode 100644 web/src/pages/PullRequest/PullRequestMetaLine.tsx delete mode 100644 web/src/pages/PullRequest/PullRequestMetadataInfo.module.scss delete mode 100644 web/src/pages/PullRequest/PullRequestMetadataInfo.tsx create mode 100644 web/src/pages/PullRequest/PullRequestTabContentWrapper.tsx create mode 100644 web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.module.scss create mode 100644 web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.module.scss.d.ts create mode 100644 web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.tsx create mode 100644 web/src/pages/PullRequests/pull-request-failed.svg create mode 100644 web/src/pages/PullRequests/pull-request-open.svg delete mode 100644 web/src/pages/RepositoryCreateWebhook/RepositoryCreateWebhookHeader.tsx diff --git a/web/package.json b/web/package.json index 57d24ddde..53c3e7410 100644 --- a/web/package.json +++ b/web/package.json @@ -56,6 +56,7 @@ "copy-to-clipboard": "^3.3.1", "cron-validator": "^1.2.1", "cronstrue": "^1.114.0", + "diff2html": "3.4.22", "event-source-polyfill": "^1.0.22", "formik": "2.2.9", "github-markdown-css": "^5.1.0", @@ -83,6 +84,7 @@ "react-contenteditable": "^3.3.5", "react-dom": "^17.0.2", "react-draggable": "^4.4.2", + "react-intersection-observer": "^9.4.1", "react-join": "^1.1.4", "react-keywords": "^0.0.5", "react-lottie-player": "^1.4.0", diff --git a/web/src/RouteDefinitions.ts b/web/src/RouteDefinitions.ts index 82cef12e6..67b16b8ba 100644 --- a/web/src/RouteDefinitions.ts +++ b/web/src/RouteDefinitions.ts @@ -8,6 +8,7 @@ export interface CODEProps { branch?: string diffRefs?: string pullRequestId?: string + pullRequestSection?: string } export interface CODEQueryProps { @@ -21,7 +22,8 @@ export const pathProps: Readonly, 'repoPath' | 'branch' resourcePath: ':resourcePath*', commitRef: ':commitRef*', diffRefs: ':diffRefs*', - pullRequestId: ':pullRequestId' + pullRequestId: ':pullRequestId', + pullRequestSection: ':pullRequestSection*' } export interface CODERoutes { @@ -32,7 +34,12 @@ export interface CODERoutes { toCODEFileEdit: (args: Required>) => string toCODECommits: (args: Required>) => string toCODEPullRequests: (args: Required>) => string - toCODEPullRequest: (args: Required>) => string + toCODEPullRequest: ( + args: RequiredField< + Pick, + 'repoPath' | 'pullRequestId' + > + ) => string toCODECompare: (args: Required>) => string toCODEBranches: (args: Required>) => string toCODESettings: (args: Required>) => string @@ -48,7 +55,8 @@ export const routes: CODERoutes = { toCODEFileEdit: ({ repoPath, gitRef, resourcePath }) => `/${repoPath}/edit/${gitRef}/~/${resourcePath}`, toCODECommits: ({ repoPath, commitRef }) => `/${repoPath}/commits/${commitRef}`, toCODEPullRequests: ({ repoPath }) => `/${repoPath}/pulls`, - toCODEPullRequest: ({ repoPath, pullRequestId }) => `/${repoPath}/pulls/${pullRequestId}`, + toCODEPullRequest: ({ repoPath, pullRequestId, pullRequestSection }) => + `/${repoPath}/pulls/${pullRequestId}${pullRequestSection ? '/' + pullRequestSection : ''}`, toCODECompare: ({ repoPath, diffRefs }) => `/${repoPath}/pulls/compare/${diffRefs}`, toCODEBranches: ({ repoPath }) => `/${repoPath}/branches`, toCODESettings: ({ repoPath }) => `/${repoPath}/settings`, diff --git a/web/src/components/CommitDivergence/CommitDivergence.tsx b/web/src/components/CommitDivergence/CommitDivergence.tsx index c95305ebe..ff32a9d51 100644 --- a/web/src/components/CommitDivergence/CommitDivergence.tsx +++ b/web/src/components/CommitDivergence/CommitDivergence.tsx @@ -1,7 +1,6 @@ import React, { CSSProperties } from 'react' -import { Container, Popover, Text } from '@harness/uicore' +import { Container, Popover, StringSubstitute, Text } from '@harness/uicore' import { useStrings } from 'framework/strings' -import { StringSubstitute } from 'components/StringSubstitute/StringSubstitute' import css from './CommitDivergence.module.scss' interface CommitDivergenceProps { diff --git a/web/src/pages/RepositoryCommits/RepositoryCommitsContent/CommitsContent/CommitsContent.module.scss b/web/src/components/CommitsView/CommitsView.module.scss similarity index 100% rename from web/src/pages/RepositoryCommits/RepositoryCommitsContent/CommitsContent/CommitsContent.module.scss rename to web/src/components/CommitsView/CommitsView.module.scss diff --git a/web/src/pages/RepositoryCommits/RepositoryCommitsContent/CommitsContent/CommitsContent.module.scss.d.ts b/web/src/components/CommitsView/CommitsView.module.scss.d.ts similarity index 100% rename from web/src/pages/RepositoryCommits/RepositoryCommitsContent/CommitsContent/CommitsContent.module.scss.d.ts rename to web/src/components/CommitsView/CommitsView.module.scss.d.ts diff --git a/web/src/pages/RepositoryCommits/RepositoryCommitsContent/CommitsContent/CommitsContent.tsx b/web/src/components/CommitsView/CommitsView.tsx similarity index 93% rename from web/src/pages/RepositoryCommits/RepositoryCommitsContent/CommitsContent/CommitsContent.tsx rename to web/src/components/CommitsView/CommitsView.tsx index 6c811fab8..f9966e729 100644 --- a/web/src/pages/RepositoryCommits/RepositoryCommitsContent/CommitsContent/CommitsContent.tsx +++ b/web/src/components/CommitsView/CommitsView.tsx @@ -8,13 +8,13 @@ import type { RepoCommit } from 'services/code' import { CommitActions } from 'components/CommitActions/CommitActions' import { formatDate } from 'utils/Utils' import { CodeIcon, GitInfoProps } from 'utils/GitUtils' -import css from './CommitsContent.module.scss' +import css from './CommitsView.module.scss' -interface CommitsContentProps extends Pick { +interface CommitsViewProps extends Pick { commits: RepoCommit[] } -export function CommitsContent({ repoMetadata, commits }: CommitsContentProps) { +export function CommitsView({ repoMetadata, commits }: CommitsViewProps) { const { getString } = useStrings() const { routes } = useAppContext() const columns: Column[] = useMemo( diff --git a/web/src/components/ContainerSpinner/ContainerSpinner.module.scss b/web/src/components/ContainerSpinner/ContainerSpinner.module.scss new file mode 100644 index 000000000..c037cbce3 --- /dev/null +++ b/web/src/components/ContainerSpinner/ContainerSpinner.module.scss @@ -0,0 +1,8 @@ +.spinner { + width: 100%; + height: 100%; + + > div { + position: relative !important; + } +} diff --git a/web/src/components/ContainerSpinner/ContainerSpinner.module.scss.d.ts b/web/src/components/ContainerSpinner/ContainerSpinner.module.scss.d.ts new file mode 100644 index 000000000..25367990c --- /dev/null +++ b/web/src/components/ContainerSpinner/ContainerSpinner.module.scss.d.ts @@ -0,0 +1,6 @@ +/* eslint-disable */ +// this is an auto-generated file +declare const styles: { + readonly spinner: string +} +export default styles diff --git a/web/src/components/ContainerSpinner/ContainerSpinner.tsx b/web/src/components/ContainerSpinner/ContainerSpinner.tsx new file mode 100644 index 000000000..a5b1d7f6e --- /dev/null +++ b/web/src/components/ContainerSpinner/ContainerSpinner.tsx @@ -0,0 +1,12 @@ +import React from 'react' +import cx from 'classnames' +import { Container, PageSpinner } from '@harness/uicore' +import css from './ContainerSpinner.module.scss' + +export const ContainerSpinner: React.FC> = ({ className, ...props }) => { + return ( + + + + ) +} diff --git a/web/src/components/DiffViewer/DiffViewer.module.scss b/web/src/components/DiffViewer/DiffViewer.module.scss new file mode 100644 index 000000000..b1c92a709 --- /dev/null +++ b/web/src/components/DiffViewer/DiffViewer.module.scss @@ -0,0 +1,106 @@ +.main { + --border-color: var(--grey-200); + + border-radius: 5px; + min-height: 36px; + + :global { + .d2h-wrapper > div { + margin-bottom: 0; + } + + .d2h-file-wrapper { + border: 0; + } + + .d2h-file-header { + display: none; + } + + .d2h-files-diff { + .d2h-code-side-linenumber { + border-left: 0; + } + } + + .d2h-file-side-diff { + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + } + + .d2h-code-side-linenumber { + width: 56px; + } + + .d2h-diff-tbody { + position: relative; + } + } + + &.collapsed { + .diffHeader { + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + } + + .diffContent { + display: none; + } + } + + &.offscreen { + .diffContent { + display: none; + } + } + + .diffHeader { + display: grid; + align-items: center; + background-color: var(--grey-100); + position: sticky; + top: var(--diff-viewer-sticky-top, 0); + z-index: 1; + padding: 5px 10px 5px 5px; + border: 1px solid var(--border-color); + border-top-left-radius: 5px; + border-top-right-radius: 5px; + + .fname { + font-size: 13px !important; + font-weight: 600 !important; + color: var(--grey-900) !important; + align-self: center; + } + } + + .viewLabel { + display: flex; + font-size: 12px; + color: var(--grey-600); + border: 1px solid var(--grey-200); + padding: 3px 6px; + border-radius: 3px; + cursor: pointer; + + input { + display: inline-block; + margin-right: var(--spacing-small); + } + } + + .diffContent { + border-left: 1px solid var(--border-color); + border-right: 1px solid var(--border-color); + border-bottom: 1px solid var(--border-color); + + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + + max-width: calc(100vw - 320px); + + // &[data-display='none'] { + // visibility: hidden; + // } + } +} diff --git a/web/src/components/DiffViewer/DiffViewer.module.scss.d.ts b/web/src/components/DiffViewer/DiffViewer.module.scss.d.ts new file mode 100644 index 000000000..3f4a473d2 --- /dev/null +++ b/web/src/components/DiffViewer/DiffViewer.module.scss.d.ts @@ -0,0 +1,12 @@ +/* eslint-disable */ +// this is an auto-generated file +declare const styles: { + readonly main: string + readonly collapsed: string + readonly diffHeader: string + readonly diffContent: string + readonly offscreen: string + readonly fname: string + readonly viewLabel: string +} +export default styles diff --git a/web/src/components/DiffViewer/DiffViewer.tsx b/web/src/components/DiffViewer/DiffViewer.tsx new file mode 100644 index 000000000..004820a7c --- /dev/null +++ b/web/src/components/DiffViewer/DiffViewer.tsx @@ -0,0 +1,285 @@ +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useInView } from 'react-intersection-observer' +import { Button, Color, Container, FlexExpander, ButtonVariation, Layout, Text, ButtonSize } from '@harness/uicore' +import type * as Diff2Html from 'diff2html' +import HoganJsUtils from 'diff2html/lib/hoganjs-utils' +import { Diff2HtmlUI } from 'diff2html/lib-esm/ui/js/diff2html-ui' +import 'highlight.js/styles/github.css' +import 'diff2html/bundles/css/diff2html.min.css' +import type { DiffFile } from 'diff2html/lib/types' +import { useStrings } from 'framework/strings' +import { CodeIcon } from 'utils/GitUtils' +import { PipeSeparator } from 'components/PipeSeparator/PipeSeparator' +import css from './DiffViewer.module.scss' + +export enum DiffViewStyle { + SPLIT = 'side-by-side', + UNIFIED = 'line-by-line' +} + +const DIFF_HEADER_HEIGHT = 36 +const LINE_NUMBER_CLASS = 'diff-viewer-line-number' + +export const DIFF2HTML_CONFIG = { + outputFormat: 'side-by-side', + drawFileList: false, + fileListStartVisible: false, + fileContentToggle: true, + matching: 'lines', + synchronisedScroll: true, + highlight: true, + renderNothingWhenEmpty: false, + compiledTemplates: { + 'generic-line': HoganJsUtils.compile(` + + + {{{lineNumber}}} + + +
+ {{#prefix}} + {{{prefix}}} + {{/prefix}} + {{^prefix}} +   + {{/prefix}} + {{#content}} + {{{content}}} + {{/content}} + {{^content}} +
+ {{/content}} +
+ + + `), + 'line-by-line-numbers': HoganJsUtils.compile(` +
{{oldNumber}}
+
{{newNumber}}
+ `) + } +} as Readonly + +interface DiffViewerProps { + index: number + diff: DiffFile + viewStyle: DiffViewStyle + stickyTopPosition?: number +} + +// +// Note: Lots of direct DOM manipulations are used to boost performance +// Avoid React re-rendering at all cost as it might cause unresponsive UI +// when diff content is big, or when a PR has a lot of changed files. +// +export const DiffViewer: React.FC = ({ index, diff, viewStyle, stickyTopPosition = 0 }) => { + const { getString } = useStrings() + const [viewed, setViewed] = useState(false) + const [collapsed, setCollapsed] = useState(false) + const [fileUnchanged] = useState(diff.unchangedPercentage === 100) + const [fileDeleted] = useState(diff.isDeleted) + const [renderCustomContent, setRenderCustomContent] = useState(fileUnchanged || fileDeleted) + const containerId = useMemo(() => `file-diff-container-${index}`, [index]) + const contentId = useMemo(() => `${containerId}-content`, [containerId]) + const [height, setHeight] = useState('auto') + const [diffRenderer, setDiffRenderer] = useState() + const { ref: inViewRef, inView } = useInView({ rootMargin: '100px 0px' }) + const containerRef = useRef(null) + const setContainerRef = useCallback( + node => { + containerRef.current = node + inViewRef(node) + }, + [inViewRef] + ) + const contentRef = useRef(null) + const setupViewerInitialStates = useCallback(() => { + setDiffRenderer( + new Diff2HtmlUI( + document.getElementById(contentId) as HTMLElement, + [diff], + Object.assign({}, DIFF2HTML_CONFIG, { + outputFormat: viewStyle + }) + ) + ) + }, [diff, contentId, viewStyle]) + const renderDiffAndUpdateContainerHeightIfNeeded = useCallback( + (enforced = false) => { + const contentDOM = contentRef.current as HTMLDivElement + const containerDOM = containerRef.current as HTMLDivElement + + if (!contentDOM.dataset.rendered || enforced) { + if (!renderCustomContent || enforced) { + containerDOM.style.height = 'auto' + diffRenderer?.draw() + } + contentDOM.dataset.rendered = 'true' + setHeight(containerDOM.clientHeight) + } + }, + [diffRenderer, renderCustomContent] + ) + + useEffect( + function createDiffRenderer() { + if (inView && !diffRenderer) { + setupViewerInitialStates() + } + }, + [inView, diffRenderer, setupViewerInitialStates] + ) + + useEffect( + function renderInitialContent() { + if (diffRenderer) { + const container = containerRef.current as HTMLDivElement + const { classList: containerClassList } = container + + if (inView) { + containerClassList.remove(css.offscreen) + renderDiffAndUpdateContainerHeightIfNeeded() + } else { + containerClassList.add(css.offscreen) + } + } + }, + [inView, diffRenderer, renderDiffAndUpdateContainerHeightIfNeeded] + ) + + useEffect( + function handleCollapsedState() { + const containerDOM = containerRef.current as HTMLDivElement & { scrollIntoViewIfNeeded: () => void } + const { classList: containerClassList, style: containerStyle } = containerDOM + + if (collapsed) { + containerClassList.add(css.collapsed) + + // Fix scrolling position messes up with sticky header + const { y } = containerDOM.getBoundingClientRect() + if (y - stickyTopPosition < 1) { + containerDOM.scrollIntoView() + + if (stickyTopPosition) { + window.scroll({ top: window.scrollY - stickyTopPosition }) + } + } + + if (parseInt(containerStyle.height) != DIFF_HEADER_HEIGHT) { + containerStyle.height = `${DIFF_HEADER_HEIGHT}px` + } + } else { + containerClassList.remove(css.collapsed) + + if (parseInt(containerStyle.height) != height) { + containerStyle.height = `${height}px` + } + } + }, + [collapsed, height, stickyTopPosition] + ) + + useEffect(function () { + const onClick = (event: MouseEvent) => { + const target = event.target as HTMLDivElement + + if (target.classList.contains(LINE_NUMBER_CLASS)) { + console.log('line number clicked') + } + console.log({ event, target }) + } + const containerDOM = containerRef.current as HTMLDivElement + containerDOM.addEventListener('click', onClick) + return () => { + containerDOM.removeEventListener('click', onClick) + } + }, []) + + return ( + + + + + + )} + {getString(fileDeleted ? 'pr.fileDeleted' : 'pr.fileUnchanged')} + + + )} + + + + ) +} diff --git a/web/src/components/StringSubstitute/StringSubstitute.tsx b/web/src/components/StringSubstitute/StringSubstitute.tsx deleted file mode 100644 index b56241d13..000000000 --- a/web/src/components/StringSubstitute/StringSubstitute.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import React, { Fragment } from 'react' - -type SubstituteVars = Record // eslint-disable-line @typescript-eslint/no-explicit-any - -function translateExpression(str: string, key: string, vars: SubstituteVars) { - // Replace simple i18n expression {key|match1:value1,match2:value2} - // Sample: '{user} wants to merge {number} {number|1:commit,commits} into {target} from {source}' - // Find `{number|` - const startIndex = str.indexOf(`{${key}|`) - const MATCH_ELSE_KEY = '___' - - if (startIndex !== -1) { - // Find closing `}` - const endIndex = str.indexOf('}', startIndex) - - if (endIndex !== -1) { - // Get whole expression of `{number|1:commit,commits}` - const expression = str.substring(startIndex, endIndex + 1) - - // Build value mapping from expression - const mapping = expression - .split('|')[1] // Get `1:commit,commits}` - .slice(0, -1) // Remove last closing `}` - .split(',') // ['1:commit', 'commits'] - .reduce((map, token) => { - // Convert to a map { 1: commit, [MATCH_ELSE_KEY]: commits } - const [k, v] = token.split(':') - map[v ? k : MATCH_ELSE_KEY] = v || k - return map - }, {} as Record) - - const matchedValue = mapping[vars[key]] || mapping[MATCH_ELSE_KEY] - - if (matchedValue) { - return str.replace(expression, matchedValue) - } - } - } - - return str -} - -export const StringSubstitute: React.FC<{ - str: string - vars: SubstituteVars -}> = ({ str, vars }) => { - const re = Object.keys(vars) - .map(key => { - str = translateExpression(str, key, vars) - return `{${key}}` - }) - .join('|') - - return ( - <> - {str - .split(new RegExp('(' + re + ')', 'gi')) - .filter(token => !!(token || '').trim()) - .map((token, index) => ( - - {token.startsWith('{') && token.endsWith('}') ? vars[token.substring(1, token.length - 1)] || token : token} - - ))} - - ) -} diff --git a/web/src/framework/strings/stringTypes.ts b/web/src/framework/strings/stringTypes.ts index 94ca467f8..77045317c 100644 --- a/web/src/framework/strings/stringTypes.ts +++ b/web/src/framework/strings/stringTypes.ts @@ -7,6 +7,7 @@ export interface StringsMap { addGitIgnore: string addLicense: string addReadMe: string + all: string allBranches: string allEvents: string botAlerts: string @@ -31,6 +32,7 @@ export interface StringsMap { checkSuites: string clone: string cloneHTTPS: string + closed: string commit: string commitChanges: string commitDirectlyTo: string @@ -91,6 +93,7 @@ export interface StringsMap { inactiveBranches: string individualEvents: string loading: string + merged: string name: string nameYourBranch: string nameYourFile: string @@ -105,6 +108,7 @@ export interface StringsMap { none: string ok: string onDate: string + open: string optional: string optionalExtendedDescription: string pageNotFound: string @@ -115,10 +119,22 @@ export interface StringsMap { 'pr.buttonText': string 'pr.cantMerge': string 'pr.descriptionPlaceHolder': string + 'pr.diffStatus': string + 'pr.diffView': string 'pr.failedToCreate': string + 'pr.fileDeleted': string + 'pr.fileUnchanged': string 'pr.metaLine': string 'pr.modalTitle': string + 'pr.openBy': string + 'pr.reviewChanges': string + 'pr.showDiff': string + 'pr.showLabel': string + 'pr.showLink': string + 'pr.split': string + 'pr.state': string 'pr.titlePlaceHolder': string + 'pr.unified': string prefixBase: string prefixCompare: string prev: string @@ -128,6 +144,7 @@ export interface StringsMap { pullRequestEmpty: string pullRequests: string pushEvent: string + rejected: string renameFile: string 'repos.activities': string 'repos.data': string @@ -139,6 +156,7 @@ export interface StringsMap { repositories: string samplePayloadUrl: string scanAlerts: string + scrollToTop: string search: string searchBranches: string secret: string @@ -165,4 +183,5 @@ export interface StringsMap { webhookListingContent: string webhooks: string yourBranches: string + yours: string } diff --git a/web/src/hooks/useUserPreference.ts b/web/src/hooks/useUserPreference.ts new file mode 100644 index 000000000..57ec47954 --- /dev/null +++ b/web/src/hooks/useUserPreference.ts @@ -0,0 +1,19 @@ +import { useCallback, useState } from 'react' + +export enum UserPreference { + DIFF_VIEW_STYLE = 'DIFF_VIEW_STYLE' +} + +export function useUserPreference(key: UserPreference, defaultValue: string) { + const prefKey = `CODE_MODULE_USER_PREFERENCE_${key}` + const [preference, setPreference] = useState(localStorage[prefKey] || defaultValue) + const savePreference = useCallback( + val => { + localStorage[prefKey] = val + setPreference(val) + }, + [prefKey] + ) + + return [preference, savePreference] +} diff --git a/web/src/i18n/strings.en.yaml b/web/src/i18n/strings.en.yaml index 4facbed1f..63e5ec4e3 100644 --- a/web/src/i18n/strings.en.yaml +++ b/web/src/i18n/strings.en.yaml @@ -161,6 +161,25 @@ pr: modalTitle: Open a pull request buttonText: Open pull request metaLine: '{user} wants to merge {number} {number|1:commit,commits} into {target} from {source}' + state: '{state|closed:Closed,merged:Merged,rejected:Rejected,Open}' + openBy: '#{number} opened {time} by {user}' + diffStatus: '{status|deleted:Deleted,new:Added,renamed:Renamed,copied:Copied,Changed}' + showDiff: Show Diff + fileDeleted: This file was deleted. + fileUnchanged: File without changes. + showLink: '{count} changed {count|1:file,files}' + showLabel: 'Showing {showLink} with {addedLines} {addedLines|1:addition,additions} and {deletedLines} {deletedLines|1:deletion,deletions} {config}' + diffView: Diff View + split: Split + unified: Unified + reviewChanges: Review changes webhookListingContent: 'create,delete,deployment ...' general: 'General' webhooks: 'Webhooks' +open: Open +merged: Merged +closed: Closed +rejected: Rejected +yours: Yours +all: All +scrollToTop: Scroll to top diff --git a/web/src/pages/Compare/Compare.tsx b/web/src/pages/Compare/Compare.tsx index 98cd58d05..163be723d 100644 --- a/web/src/pages/Compare/Compare.tsx +++ b/web/src/pages/Compare/Compare.tsx @@ -1,6 +1,7 @@ import React, { useState } from 'react' import { Container, PageBody, NoDataCard, Tabs } from '@harness/uicore' import { useHistory } from 'react-router-dom' +import { useGet } from 'restful-react' import { useAppContext } from 'AppContext' import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata' import { useStrings } from 'framework/strings' @@ -8,6 +9,8 @@ import { RepositoryPageHeader } from 'components/RepositoryPageHeader/Repository import { getErrorMessage } from 'utils/Utils' import emptyStateImage from 'images/empty-state.svg' import { makeDiffRefs } from 'utils/GitUtils' +import { CommitsView } from 'components/CommitsView/CommitsView' +import type { RepoCommit } from 'services/code' import { CompareContentHeader } from './CompareContentHeader/CompareContentHeader' import css from './Compare.module.scss' @@ -18,6 +21,18 @@ export default function Compare() { const { repoMetadata, error, loading, refetch, diffRefs } = useGetRepositoryMetadata() const [sourceGitRef, setSourceGitRef] = useState(diffRefs.sourceGitRef) const [targetGitRef, setTargetGitRef] = useState(diffRefs.targetGitRef) + const { + data: commits, + error: commitsError, + loading: commitsLoading, + refetch: commitsRefetch + } = useGet({ + path: `/api/v1/repos/${repoMetadata?.path}/+/commits`, + queryParams: { + git_ref: sourceGitRef + }, + lazy: !repoMetadata + }) return ( @@ -60,22 +75,28 @@ export default function Compare() { ))} - {!!targetGitRef && !!sourceGitRef && ( + {!!repoMetadata && !!targetGitRef && !!sourceGitRef && ( Commit + panel: commits?.length ? ( + + + + ) : ( + <> + ) }, { id: 'diff', title: getString('diff'), - panel:
Diff
+ panel: To be defined... } ]} /> diff --git a/web/src/pages/Compare/CompareContentHeader/CompareContentHeader.tsx b/web/src/pages/Compare/CompareContentHeader/CompareContentHeader.tsx index 87f83611a..74d6a5189 100644 --- a/web/src/pages/Compare/CompareContentHeader/CompareContentHeader.tsx +++ b/web/src/pages/Compare/CompareContentHeader/CompareContentHeader.tsx @@ -60,7 +60,7 @@ export function CompareContentHeader({ history.replace( routes.toCODEPullRequest({ repoPath: repoMetadata.path as string, - pullRequestId: String(data.id) + pullRequestId: String(data.number) }) ) }} diff --git a/web/src/pages/PullRequest/PullRequest.module.scss b/web/src/pages/PullRequest/PullRequest.module.scss index bbde1d307..90707764c 100644 --- a/web/src/pages/PullRequest/PullRequest.module.scss +++ b/web/src/pages/PullRequest/PullRequest.module.scss @@ -9,6 +9,14 @@ .tabsContainer { padding-top: var(--spacing-xsmall); + // TODO: This looks bad and does not + // perform well. Need a way to fix + :global { + .Tabs--main .bp3-tab:not([aria-disabled='true']):hover .bp3-icon svg path { + fill: var(--grey-50) !important; + } + } + [role='tablist'] { background-color: var(--white) !important; padding-left: var(--spacing-medium); @@ -21,9 +29,10 @@ } [aria-selected='true'] { - .tabTitle { - color: var(--grey-900); - font-weight: 600; + .tabTitle, + .tabTitle:hover { + color: var(--grey-900) !important; + font-weight: 600 !important; } } @@ -51,3 +60,8 @@ color: var(--grey-500); padding-left: var(--spacing-small); } + +.tabContentContainer { + min-height: calc(100vh - 153px) !important; + background-color: var(--primary-bg) !important; +} diff --git a/web/src/pages/PullRequest/PullRequest.module.scss.d.ts b/web/src/pages/PullRequest/PullRequest.module.scss.d.ts index 3f3c68869..27076b0bd 100644 --- a/web/src/pages/PullRequest/PullRequest.module.scss.d.ts +++ b/web/src/pages/PullRequest/PullRequest.module.scss.d.ts @@ -6,5 +6,6 @@ declare const styles: { readonly tabTitle: string readonly count: string readonly prNumber: string + readonly tabContentContainer: string } export default styles diff --git a/web/src/pages/PullRequest/PullRequest.tsx b/web/src/pages/PullRequest/PullRequest.tsx index ad9e87166..45cb13e6c 100644 --- a/web/src/pages/PullRequest/PullRequest.tsx +++ b/web/src/pages/PullRequest/PullRequest.tsx @@ -1,6 +1,7 @@ -import React from 'react' +import React, { useMemo } from 'react' import { Container, PageBody, Text, FontVariation, Tabs, IconName } from '@harness/uicore' import { useGet } from 'restful-react' +import { useHistory } from 'react-router-dom' import { useAppContext } from 'AppContext' import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata' import { useStrings } from 'framework/strings' @@ -8,16 +9,30 @@ import { RepositoryPageHeader } from 'components/RepositoryPageHeader/Repository import { getErrorMessage } from 'utils/Utils' import type { PullRequestResponse } from 'utils/types' import { CodeIcon } from 'utils/GitUtils' -import { PullRequestMetadataInfo } from './PullRequestMetadataInfo' +import { PullRequestMetaLine } from './PullRequestMetaLine' import { PullRequestConversation } from './PullRequestConversation/PullRequestConversation' import { PullRequestDiff } from './PullRequestDiff/PullRequestDiff' import { PullRequestCommits } from './PullRequestCommits/PullRequestCommits' import css from './PullRequest.module.scss' +enum PullRequestSection { + CONVERSATION = 'conversation', + COMMITS = 'commits', + DIFFS = 'diffs' +} + export default function PullRequest() { + const history = useHistory() const { getString } = useStrings() const { routes } = useAppContext() - const { repoMetadata, error, loading, refetch, pullRequestId } = useGetRepositoryMetadata() + const { + repoMetadata, + error, + loading, + refetch, + pullRequestId, + pullRequestSection = PullRequestSection.CONVERSATION + } = useGetRepositoryMetadata() const { data: prData, error: prError, @@ -26,6 +41,13 @@ export default function PullRequest() { path: `/api/v1/repos/${repoMetadata?.path}/+/pullreq/${pullRequestId}`, lazy: !repoMetadata }) + const activeTab = useMemo( + () => + Object.values(PullRequestSection).find(value => value === pullRequestSection) + ? pullRequestSection + : PullRequestSection.CONVERSATION, + [pullRequestSection] + ) return ( @@ -46,26 +68,35 @@ export default function PullRequest() { {repoMetadata ? ( prData ? ( <> - + { + history.replace( + routes.toCODEPullRequest({ + repoPath: repoMetadata.path as string, + pullRequestId, + pullRequestSection: tabId !== PullRequestSection.CONVERSATION ? (tabId as string) : undefined + }) + ) + }} tabList={[ { - id: 'conversation', + id: PullRequestSection.CONVERSATION, title: , panel: }, { - id: 'commits', + id: PullRequestSection.COMMITS, title: , panel: }, { - id: 'diff', - title: , + id: PullRequestSection.DIFFS, + title: , panel: } ]} @@ -87,7 +118,7 @@ const PullRequestTitle: React.FC = ({ title, number }) => ( const TabTitle: React.FC<{ icon: IconName; title: string; count?: number }> = ({ icon, title, count }) => ( - {title}{' '} + {title} {!!count && ( {count} diff --git a/web/src/pages/PullRequest/PullRequestCommits/PullRequestCommits.module.scss.d.ts b/web/src/pages/PullRequest/PullRequestCommits/PullRequestCommits.module.scss.d.ts new file mode 100644 index 000000000..9e614bf2d --- /dev/null +++ b/web/src/pages/PullRequest/PullRequestCommits/PullRequestCommits.module.scss.d.ts @@ -0,0 +1,6 @@ +/* eslint-disable */ +// this is an auto-generated file +declare const styles: { + readonly main: string +} +export default styles diff --git a/web/src/pages/PullRequest/PullRequestCommits/PullRequestCommits.tsx b/web/src/pages/PullRequest/PullRequestCommits/PullRequestCommits.tsx index 50b091f1d..42d598582 100644 --- a/web/src/pages/PullRequest/PullRequestCommits/PullRequestCommits.tsx +++ b/web/src/pages/PullRequest/PullRequestCommits/PullRequestCommits.tsx @@ -1,20 +1,30 @@ import React from 'react' -import { Container } from '@harness/uicore' -import { useAppContext } from 'AppContext' -import { useStrings } from 'framework/strings' +import { useGet } from 'restful-react' +import type { RepoCommit } from 'services/code' import type { GitInfoProps } from 'utils/GitUtils' -import css from './PullRequestCommits.module.scss' +import { CommitsView } from 'components/CommitsView/CommitsView' +import { PullRequestTabContentWrapper } from '../PullRequestTabContentWrapper' export const PullRequestCommits: React.FC> = ({ repoMetadata, pullRequestMetadata }) => { - const { getString } = useStrings() - const { routes } = useAppContext() + const { + data: commits, + error, + loading, + refetch + } = useGet({ + path: `/api/v1/repos/${repoMetadata?.path}/+/commits`, + queryParams: { + git_ref: pullRequestMetadata.sourceBranch + }, + lazy: !repoMetadata + }) return ( - - COMMITS... - + refetch()}> + {!!commits?.length && } + ) } diff --git a/web/src/pages/PullRequest/PullRequestConversation/PullRequestConversation.tsx b/web/src/pages/PullRequest/PullRequestConversation/PullRequestConversation.tsx index 17e41e7c2..bf44566c7 100644 --- a/web/src/pages/PullRequest/PullRequestConversation/PullRequestConversation.tsx +++ b/web/src/pages/PullRequest/PullRequestConversation/PullRequestConversation.tsx @@ -1,20 +1,18 @@ import React from 'react' import { Container } from '@harness/uicore' -import { useAppContext } from 'AppContext' -import { useStrings } from 'framework/strings' import type { GitInfoProps } from 'utils/GitUtils' -import css from './PullRequestConversation.module.scss' +import { MarkdownViewer } from 'components/SourceCodeViewer/SourceCodeViewer' +import { PullRequestTabContentWrapper } from '../PullRequestTabContentWrapper' export const PullRequestConversation: React.FC> = ({ repoMetadata, pullRequestMetadata }) => { - const { getString } = useStrings() - const { routes } = useAppContext() - return ( - - CONVERSATION... - + {}}> + + + + ) } diff --git a/web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.module.scss b/web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.module.scss index 662ecf803..dcf1db5a9 100644 --- a/web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.module.scss +++ b/web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.module.scss @@ -1,2 +1,52 @@ -.main { +.wrapper { + padding-top: 0 !important; +} + +.header { + position: sticky; + top: 0; + padding: var(--spacing-medium) 0 !important; + background-color: var(--white) !important; + z-index: 2; +} + +.showLabel { + font-size: 12px !important; + font-weight: 600 !important; + color: var(--grey-700) !important; + + .showLabelLink { + all: unset !important; + height: auto !important; + min-height: auto !important; + padding: 0 !important; + font-size: 12px !important; + font-weight: 600 !important; + color: var(--grey-700) !important; + color: var(--primary-7) !important; + display: inline-block !important; + margin: 0 4px !important; + cursor: pointer !important; + } +} + +.layout { + border-radius: 5px; +} + +.filesMenu { + max-height: 350px; + overflow: auto; + padding: var(--spacing-xsmall) !important; + + :global { + .bp3-menu-item:hover { + background-color: rgba(167, 182, 194, 0.3); + color: inherit; + } + } + + .menuItem { + align-items: center; + } } diff --git a/web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.module.scss.d.ts b/web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.module.scss.d.ts new file mode 100644 index 000000000..254455bff --- /dev/null +++ b/web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.module.scss.d.ts @@ -0,0 +1,12 @@ +/* eslint-disable */ +// this is an auto-generated file +declare const styles: { + readonly wrapper: string + readonly header: string + readonly showLabel: string + readonly showLabelLink: string + readonly layout: string + readonly filesMenu: string + readonly menuItem: string +} +export default styles diff --git a/web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.tsx b/web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.tsx index 4870b7795..8ac0433a0 100644 --- a/web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.tsx +++ b/web/src/pages/PullRequest/PullRequestDiff/PullRequestDiff.tsx @@ -1,20 +1,227 @@ -import React from 'react' -import { Container } from '@harness/uicore' -import { useAppContext } from 'AppContext' +import React, { useEffect, useMemo, useState } from 'react' +import { + Container, + FlexExpander, + ButtonVariation, + Layout, + Text, + StringSubstitute, + FontVariation, + Button, + Icon, + Color +} from '@harness/uicore' +import { ButtonGroup, Button as BButton, Classes, Menu, MenuItem } from '@blueprintjs/core' +import { noop } from 'lodash-es' +import cx from 'classnames' +import * as Diff2Html from 'diff2html' +// import { useAppContext } from 'AppContext' +// import { useStrings } from 'framework/strings' +import 'highlight.js/styles/github.css' +import 'diff2html/bundles/css/diff2html.min.css' +import type { DiffFile } from 'diff2html/lib/types' import { useStrings } from 'framework/strings' -import type { GitInfoProps } from 'utils/GitUtils' +import { CodeIcon, GitInfoProps } from 'utils/GitUtils' +import { ButtonRoleProps, formatNumber, waitUntil } from 'utils/Utils' +import { DiffViewer, DIFF2HTML_CONFIG, DiffViewStyle } from 'components/DiffViewer/DiffViewer' +import { UserPreference, useUserPreference } from 'hooks/useUserPreference' +import { PipeSeparator } from 'components/PipeSeparator/PipeSeparator' +import { PullRequestTabContentWrapper } from '../PullRequestTabContentWrapper' +import diffExample from 'raw-loader!./example2.diff' import css from './PullRequestDiff.module.scss' -export const PullRequestDiff: React.FC> = ({ - repoMetadata, - pullRequestMetadata -}) => { +const STICKY_TOP_POSITION = 64 + +export const PullRequestDiff: React.FC> = () => { const { getString } = useStrings() - const { routes } = useAppContext() + const [viewStyle, setViewStyle] = useUserPreference(UserPreference.DIFF_VIEW_STYLE, DiffViewStyle.SPLIT) + const [diffs, setDiffs] = useState([]) + const [stickyInAction, setStickyInAction] = useState(false) + const diffStats = useMemo(() => { + return (diffs || []).reduce( + (obj, diff) => { + obj.addedLines += diff.addedLines + obj.deletedLines += diff.deletedLines + return obj + }, + { addedLines: 0, deletedLines: 0 } + ) + }, [diffs]) + + useEffect(() => { + setDiffs(Diff2Html.parse(diffExample, DIFF2HTML_CONFIG)) + }, []) + + useEffect(() => { + const onScroll = () => { + if (window.scrollY >= 150) { + if (!stickyInAction) { + setStickyInAction(true) + } + } else { + if (stickyInAction) { + setStickyInAction(false) + } + } + } + window.addEventListener('scroll', onScroll) + + return () => { + window.removeEventListener('scroll', onScroll) + } + }, [stickyInAction]) + + // console.log({ diffs, viewStyle }) return ( - - DIFF - + + + + + + + {diffs?.map((diff, index) => ( + } + labelElement={ + + {!!diff.addedLines && ( + + +{diff.addedLines} + + )} + {!!diff.addedLines && !!diff.deletedLines && } + {!!diff.deletedLines && ( + + -{diff.deletedLines} + + )} + + } + text={ + diff.isDeleted + ? diff.oldName + : diff.isRename + ? `${diff.oldName} -> ${diff.newName}` + : diff.newName + } + onClick={() => { + const containerDOM = document.getElementById(`file-diff-container-${index}`) + + if (containerDOM) { + containerDOM.scrollIntoView() + waitUntil( + () => !!containerDOM.querySelector('[data-rendered="true"]'), + () => { + containerDOM.scrollIntoView() + // Fix scrolling position messes up with sticky header + const { y } = containerDOM.getBoundingClientRect() + if (y - STICKY_TOP_POSITION < 1) { + if (STICKY_TOP_POSITION) { + window.scroll({ top: window.scrollY - STICKY_TOP_POSITION }) + } + } + } + ) + } + }} + /> + ))} + + } + tooltipProps={{ interactionKind: 'click', hasBackdrop: true }}> + + + ), + addedLines: formatNumber(diffStats.addedLines), + deletedLines: formatNumber(diffStats.deletedLines), + config: ( + + + + {getString('pr.diffView')} + + + { + setViewStyle(DiffViewStyle.SPLIT) + window.scroll({ top: 0 }) + }}> + {getString('pr.split')} + + { + setViewStyle(DiffViewStyle.UNIFIED) + window.scroll({ top: 0 }) + }}> + {getString('pr.unified')} + + + + + } + iconProps={{ size: 14, padding: { right: 3 } }} + rightIconProps={{ size: 13, padding: { left: 0 } }} + padding={{ left: 'small' }} + {...ButtonRoleProps} + /> + ) + }} + /> + + {stickyInAction && ( + + + +- diff2html +- +- +- +- +- +-

Diff Prettifier +- +- +-

+-

GitHub, Bitbucket and GitLab commit and pull request compatible

+-

Just paste the GitHub, Bitbucket or GitLab commit, pull request or merge request url +- or any other git or unified compatible diff and we will render a pretty html representation of it +- with code syntax highlight and line similarity matching for better code reviews. +-

+-

Options:

+-
+-
+- +-
+-
+- +-
+-
+- +-
+-
+- +-
+-
+- +-
+-
+-
+-
+- +- Load +-
+-
+-
+-
+-
+-

Help:

+-
    +-
  • +- Why should I use this instead of GitHub, Bitbucket or GitLab? +-

    Code Syntax Highlight

    +-

    Line similarity match (similar lines are together)

    +-

    Line by Line and Side by Side diffs

    +-

    Supports any git and unified compatible diffs

    +-

    Easy code selection

    +-
  • +-
  • +- What urls are supported? +-

    Any GitHub, Bitbucket or GitLab Commit, Pull Request or Merge Request urls.

    +-

    Any Git or Unified Raw Diff or Patch urls.

    +-
  • +-
  • +- Can I send a custom url for a friend, colleague or co-worker? +-

    Just add a url parameter called diff to current url using as value your Commit, Pull Request, Merge Request, Diff +- or Patch url.

    +-

    ex: https://diff2html.xyz/demo.html?diff=https://github.com/rtfpessoa/diff2html/pull/106 +-

    +-
  • +-
  • +- Why can't I paste a diff? +-

    diffy.org is an amazing tool created by pbu88 +- to share your diffs and uses diff2html under the hood.

    +-

    Also, diff2html cli can directly publish diffs to diffy.org

    +-
  • +-
+-
+-

Thank you

+-

I want to thank kevinsimper for this great idea, +- providing better diff support for existing online services. +-

+- +- +- +- +-
+-

+- Website originally designed and built by +- @mdo, +- @fat, and +- @dhg, +- adapted with by +- @rtfpessoa. +-

+- +-
+- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +diff --git a/docs/demo.js b/docs/demo.js +deleted file mode 100644 +index a81d6023..00000000 +--- a/docs/demo.js ++++ /dev/null +@@ -1,769 +0,0 @@ +-(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i -1 +- }; +- } +- +- function normalizeName(name) { +- if (typeof name !== 'string') { +- name = String(name); +- } +- if (/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(name)) { +- throw new TypeError('Invalid character in header field name') +- } +- return name.toLowerCase() +- } +- +- function normalizeValue(value) { +- if (typeof value !== 'string') { +- value = String(value); +- } +- return value +- } +- +- // Build a destructive iterator for the value list +- function iteratorFor(items) { +- var iterator = { +- next: function() { +- var value = items.shift(); +- return {done: value === undefined, value: value} +- } +- }; +- +- if (support.iterable) { +- iterator[Symbol.iterator] = function() { +- return iterator +- }; +- } +- +- return iterator +- } +- +- function Headers(headers) { +- this.map = {}; +- +- if (headers instanceof Headers) { +- headers.forEach(function(value, name) { +- this.append(name, value); +- }, this); +- } else if (Array.isArray(headers)) { +- headers.forEach(function(header) { +- this.append(header[0], header[1]); +- }, this); +- } else if (headers) { +- Object.getOwnPropertyNames(headers).forEach(function(name) { +- this.append(name, headers[name]); +- }, this); +- } +- } +- +- Headers.prototype.append = function(name, value) { +- name = normalizeName(name); +- value = normalizeValue(value); +- var oldValue = this.map[name]; +- this.map[name] = oldValue ? oldValue + ', ' + value : value; +- }; +- +- Headers.prototype['delete'] = function(name) { +- delete this.map[normalizeName(name)]; +- }; +- +- Headers.prototype.get = function(name) { +- name = normalizeName(name); +- return this.has(name) ? this.map[name] : null +- }; +- +- Headers.prototype.has = function(name) { +- return this.map.hasOwnProperty(normalizeName(name)) +- }; +- +- Headers.prototype.set = function(name, value) { +- this.map[normalizeName(name)] = normalizeValue(value); +- }; +- +- Headers.prototype.forEach = function(callback, thisArg) { +- for (var name in this.map) { +- if (this.map.hasOwnProperty(name)) { +- callback.call(thisArg, this.map[name], name, this); +- } +- } +- }; +- +- Headers.prototype.keys = function() { +- var items = []; +- this.forEach(function(value, name) { +- items.push(name); +- }); +- return iteratorFor(items) +- }; +- +- Headers.prototype.values = function() { +- var items = []; +- this.forEach(function(value) { +- items.push(value); +- }); +- return iteratorFor(items) +- }; +- +- Headers.prototype.entries = function() { +- var items = []; +- this.forEach(function(value, name) { +- items.push([name, value]); +- }); +- return iteratorFor(items) +- }; +- +- if (support.iterable) { +- Headers.prototype[Symbol.iterator] = Headers.prototype.entries; +- } +- +- function consumed(body) { +- if (body.bodyUsed) { +- return Promise.reject(new TypeError('Already read')) +- } +- body.bodyUsed = true; +- } +- +- function fileReaderReady(reader) { +- return new Promise(function(resolve, reject) { +- reader.onload = function() { +- resolve(reader.result); +- }; +- reader.onerror = function() { +- reject(reader.error); +- }; +- }) +- } +- +- function readBlobAsArrayBuffer(blob) { +- var reader = new FileReader(); +- var promise = fileReaderReady(reader); +- reader.readAsArrayBuffer(blob); +- return promise +- } +- +- function readBlobAsText(blob) { +- var reader = new FileReader(); +- var promise = fileReaderReady(reader); +- reader.readAsText(blob); +- return promise +- } +- +- function readArrayBufferAsText(buf) { +- var view = new Uint8Array(buf); +- var chars = new Array(view.length); +- +- for (var i = 0; i < view.length; i++) { +- chars[i] = String.fromCharCode(view[i]); +- } +- return chars.join('') +- } +- +- function bufferClone(buf) { +- if (buf.slice) { +- return buf.slice(0) +- } else { +- var view = new Uint8Array(buf.byteLength); +- view.set(new Uint8Array(buf)); +- return view.buffer +- } +- } +- +- function Body() { +- this.bodyUsed = false; +- +- this._initBody = function(body) { +- this._bodyInit = body; +- if (!body) { +- this._bodyText = ''; +- } else if (typeof body === 'string') { +- this._bodyText = body; +- } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { +- this._bodyBlob = body; +- } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { +- this._bodyFormData = body; +- } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { +- this._bodyText = body.toString(); +- } else if (support.arrayBuffer && support.blob && isDataView(body)) { +- this._bodyArrayBuffer = bufferClone(body.buffer); +- // IE 10-11 can't handle a DataView body. +- this._bodyInit = new Blob([this._bodyArrayBuffer]); +- } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) { +- this._bodyArrayBuffer = bufferClone(body); +- } else { +- this._bodyText = body = Object.prototype.toString.call(body); +- } +- +- if (!this.headers.get('content-type')) { +- if (typeof body === 'string') { +- this.headers.set('content-type', 'text/plain;charset=UTF-8'); +- } else if (this._bodyBlob && this._bodyBlob.type) { +- this.headers.set('content-type', this._bodyBlob.type); +- } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { +- this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8'); +- } +- } +- }; +- +- if (support.blob) { +- this.blob = function() { +- var rejected = consumed(this); +- if (rejected) { +- return rejected +- } +- +- if (this._bodyBlob) { +- return Promise.resolve(this._bodyBlob) +- } else if (this._bodyArrayBuffer) { +- return Promise.resolve(new Blob([this._bodyArrayBuffer])) +- } else if (this._bodyFormData) { +- throw new Error('could not read FormData body as blob') +- } else { +- return Promise.resolve(new Blob([this._bodyText])) +- } +- }; +- +- this.arrayBuffer = function() { +- if (this._bodyArrayBuffer) { +- return consumed(this) || Promise.resolve(this._bodyArrayBuffer) +- } else { +- return this.blob().then(readBlobAsArrayBuffer) +- } +- }; +- } +- +- this.text = function() { +- var rejected = consumed(this); +- if (rejected) { +- return rejected +- } +- +- if (this._bodyBlob) { +- return readBlobAsText(this._bodyBlob) +- } else if (this._bodyArrayBuffer) { +- return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)) +- } else if (this._bodyFormData) { +- throw new Error('could not read FormData body as text') +- } else { +- return Promise.resolve(this._bodyText) +- } +- }; +- +- if (support.formData) { +- this.formData = function() { +- return this.text().then(decode) +- }; +- } +- +- this.json = function() { +- return this.text().then(JSON.parse) +- }; +- +- return this +- } +- +- // HTTP methods whose capitalization should be normalized +- var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']; +- +- function normalizeMethod(method) { +- var upcased = method.toUpperCase(); +- return methods.indexOf(upcased) > -1 ? upcased : method +- } +- +- function Request(input, options) { +- options = options || {}; +- var body = options.body; +- +- if (input instanceof Request) { +- if (input.bodyUsed) { +- throw new TypeError('Already read') +- } +- this.url = input.url; +- this.credentials = input.credentials; +- if (!options.headers) { +- this.headers = new Headers(input.headers); +- } +- this.method = input.method; +- this.mode = input.mode; +- this.signal = input.signal; +- if (!body && input._bodyInit != null) { +- body = input._bodyInit; +- input.bodyUsed = true; +- } +- } else { +- this.url = String(input); +- } +- +- this.credentials = options.credentials || this.credentials || 'same-origin'; +- if (options.headers || !this.headers) { +- this.headers = new Headers(options.headers); +- } +- this.method = normalizeMethod(options.method || this.method || 'GET'); +- this.mode = options.mode || this.mode || null; +- this.signal = options.signal || this.signal; +- this.referrer = null; +- +- if ((this.method === 'GET' || this.method === 'HEAD') && body) { +- throw new TypeError('Body not allowed for GET or HEAD requests') +- } +- this._initBody(body); +- } +- +- Request.prototype.clone = function() { +- return new Request(this, {body: this._bodyInit}) +- }; +- +- function decode(body) { +- var form = new FormData(); +- body +- .trim() +- .split('&') +- .forEach(function(bytes) { +- if (bytes) { +- var split = bytes.split('='); +- var name = split.shift().replace(/\+/g, ' '); +- var value = split.join('=').replace(/\+/g, ' '); +- form.append(decodeURIComponent(name), decodeURIComponent(value)); +- } +- }); +- return form +- } +- +- function parseHeaders(rawHeaders) { +- var headers = new Headers(); +- // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space +- // https://tools.ietf.org/html/rfc7230#section-3.2 +- var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' '); +- preProcessedHeaders.split(/\r?\n/).forEach(function(line) { +- var parts = line.split(':'); +- var key = parts.shift().trim(); +- if (key) { +- var value = parts.join(':').trim(); +- headers.append(key, value); +- } +- }); +- return headers +- } +- +- Body.call(Request.prototype); +- +- function Response(bodyInit, options) { +- if (!options) { +- options = {}; +- } +- +- this.type = 'default'; +- this.status = options.status === undefined ? 200 : options.status; +- this.ok = this.status >= 200 && this.status < 300; +- this.statusText = 'statusText' in options ? options.statusText : 'OK'; +- this.headers = new Headers(options.headers); +- this.url = options.url || ''; +- this._initBody(bodyInit); +- } +- +- Body.call(Response.prototype); +- +- Response.prototype.clone = function() { +- return new Response(this._bodyInit, { +- status: this.status, +- statusText: this.statusText, +- headers: new Headers(this.headers), +- url: this.url +- }) +- }; +- +- Response.error = function() { +- var response = new Response(null, {status: 0, statusText: ''}); +- response.type = 'error'; +- return response +- }; +- +- var redirectStatuses = [301, 302, 303, 307, 308]; +- +- Response.redirect = function(url, status) { +- if (redirectStatuses.indexOf(status) === -1) { +- throw new RangeError('Invalid status code') +- } +- +- return new Response(null, {status: status, headers: {location: url}}) +- }; +- +- exports.DOMException = self.DOMException; +- try { +- new exports.DOMException(); +- } catch (err) { +- exports.DOMException = function(message, name) { +- this.message = message; +- this.name = name; +- var error = Error(message); +- this.stack = error.stack; +- }; +- exports.DOMException.prototype = Object.create(Error.prototype); +- exports.DOMException.prototype.constructor = exports.DOMException; +- } +- +- function fetch(input, init) { +- return new Promise(function(resolve, reject) { +- var request = new Request(input, init); +- +- if (request.signal && request.signal.aborted) { +- return reject(new exports.DOMException('Aborted', 'AbortError')) +- } +- +- var xhr = new XMLHttpRequest(); +- +- function abortXhr() { +- xhr.abort(); +- } +- +- xhr.onload = function() { +- var options = { +- status: xhr.status, +- statusText: xhr.statusText, +- headers: parseHeaders(xhr.getAllResponseHeaders() || '') +- }; +- options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL'); +- var body = 'response' in xhr ? xhr.response : xhr.responseText; +- resolve(new Response(body, options)); +- }; +- +- xhr.onerror = function() { +- reject(new TypeError('Network request failed')); +- }; +- +- xhr.ontimeout = function() { +- reject(new TypeError('Network request failed')); +- }; +- +- xhr.onabort = function() { +- reject(new exports.DOMException('Aborted', 'AbortError')); +- }; +- +- xhr.open(request.method, request.url, true); +- +- if (request.credentials === 'include') { +- xhr.withCredentials = true; +- } else if (request.credentials === 'omit') { +- xhr.withCredentials = false; +- } +- +- if ('responseType' in xhr && support.blob) { +- xhr.responseType = 'blob'; +- } +- +- request.headers.forEach(function(value, name) { +- xhr.setRequestHeader(name, value); +- }); +- +- if (request.signal) { +- request.signal.addEventListener('abort', abortXhr); +- +- xhr.onreadystatechange = function() { +- // DONE (success or failure) +- if (xhr.readyState === 4) { +- request.signal.removeEventListener('abort', abortXhr); +- } +- }; +- } +- +- xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit); +- }) +- } +- +- fetch.polyfill = true; +- +- if (!self.fetch) { +- self.fetch = fetch; +- self.Headers = Headers; +- self.Request = Request; +- self.Response = Response; +- } +- +- exports.Headers = Headers; +- exports.Request = Request; +- exports.Response = Response; +- exports.fetch = fetch; +- +- Object.defineProperty(exports, '__esModule', { value: true }); +- +-}))); +- +-},{}],2:[function(require,module,exports){ +-/* global Diff2HtmlUI */ +- +-/* +- * Example URLs: +- * +- * https://github.com/rtfpessoa/diff2html/commit/7d02e67f3b3386ac5d804f974d025cd7a1165839 +- * https://github.com/rtfpessoa/diff2html/pull/106 +- * +- * https://gitlab.com/gitlab-org/gitlab-ce/commit/4e963fed42ad518caa7353d361a38a1250c99c41 +- * https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6763 +- * +- * https://bitbucket.org/atlassian/amps/commits/52c38116f12475f75af4a147b7a7685478b83eca +- * https://bitbucket.org/atlassian/amps/pull-requests/236 +- */ +- +-$(document).ready(function() { +- // Improves browser compatibility +- require('whatwg-fetch'); +- +- var searchParam = 'diff'; +- +- var $container = $('.container'); +- var $url = $('#url'); +- var $outputFormat = $('#diff-url-options-output-format'); +- var $showFiles = $('#diff-url-options-show-files'); +- var $matching = $('#diff-url-options-matching'); +- var $wordsThreshold = $('#diff-url-options-match-words-threshold'); +- var $matchingMaxComparisons = $('#diff-url-options-matching-max-comparisons'); +- +- if (window.location.search) { +- var url = getUrlFromSearch(window.location.search); +- $url.val(url); +- smartDraw(url); +- } +- +- bind(); +- +- $outputFormat +- .add($showFiles) +- .add($matching) +- .add($wordsThreshold) +- .add($matchingMaxComparisons) +- .change(function(e) { +- console.log(''); +- console.log(e); +- console.log(''); +- smartDraw(null, true); +- }); +- +- function getUrlFromSearch(search) { +- try { +- return search +- .split('?')[1] +- .split(searchParam + '=')[1] +- .split('&')[0]; +- } catch (_ignore) { +- } +- +- return null; +- } +- +- function getParamsFromSearch(search) { +- var map = {}; +- try { +- search +- .split('?')[1] +- .split('&') +- .map(function(e) { +- var values = e.split('='); +- map[values[0]] = values[1]; +- }); +- } catch (_ignore) { +- } +- +- return map; +- } +- +- function bind() { +- $('#url-btn').click(function(e) { +- e.preventDefault(); +- var url = $url.val(); +- smartDraw(url); +- }); +- +- $url.on('paste', function(e) { +- var url = e.originalEvent.clipboardData.getData('Text'); +- smartDraw(url); +- }); +- } +- +- function prepareUrl(url) { +- var fetchUrl; +- var headers = new Headers(); +- +- var githubCommitUrl = /^https?:\/\/(?:www\.)?github\.com\/(.*?)\/(.*?)\/commit\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; +- var githubPrUrl = /^https?:\/\/(?:www\.)?github\.com\/(.*?)\/(.*?)\/pull\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; +- +- var gitlabCommitUrl = /^https?:\/\/(?:www\.)?gitlab\.com\/(.*?)\/(.*?)\/commit\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; +- var gitlabPrUrl = /^https?:\/\/(?:www\.)?gitlab\.com\/(.*?)\/(.*?)\/merge_requests\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; +- +- var bitbucketCommitUrl = /^https?:\/\/(?:www\.)?bitbucket\.org\/(.*?)\/(.*?)\/commits\/(.*?)(?:\/raw)?(?:\/.*)?$/; +- var bitbucketPrUrl = /^https?:\/\/(?:www\.)?bitbucket\.org\/(.*?)\/(.*?)\/pull-requests\/(.*?)(?:\/.*)?$/; +- +- function gitLabUrlGen(userName, projectName, type, value) { +- return 'https://crossorigin.me/https://gitlab.com/' + userName + '/' + projectName + '/' + type + '/' + value + '.diff'; +- } +- +- function gitHubUrlGen(userName, projectName, type, value) { +- headers.append('Accept', 'application/vnd.github.v3.diff'); +- return 'https://api.github.com/repos/' + userName + '/' + projectName + '/' + type + '/' + value; +- } +- +- function bitbucketUrlGen(userName, projectName, type, value) { +- var baseUrl = 'https://bitbucket.org/api/2.0/repositories/'; +- if (type === 'pullrequests') { +- return baseUrl + userName + '/' + projectName + '/pullrequests/' + value + '/diff'; +- } +- return baseUrl + userName + '/' + projectName + '/diff/' + value; +- } +- +- var values; +- if ((values = githubCommitUrl.exec(url))) { +- fetchUrl = gitHubUrlGen(values[1], values[2], 'commits', values[3]); +- } else if ((values = githubPrUrl.exec(url))) { +- fetchUrl = gitHubUrlGen(values[1], values[2], 'pulls', values[3]); +- } else if ((values = gitlabCommitUrl.exec(url))) { +- fetchUrl = gitLabUrlGen(values[1], values[2], 'commit', values[3]); +- } else if ((values = gitlabPrUrl.exec(url))) { +- fetchUrl = gitLabUrlGen(values[1], values[2], 'merge_requests', values[3]); +- } else if ((values = bitbucketCommitUrl.exec(url))) { +- fetchUrl = bitbucketUrlGen(values[1], values[2], 'commit', values[3]); +- } else if ((values = bitbucketPrUrl.exec(url))) { +- fetchUrl = bitbucketUrlGen(values[1], values[2], 'pullrequests', values[3]); +- } else { +- console.info('Could not parse url, using the provided url.'); +- fetchUrl = 'https://crossorigin.me/' + url; +- } +- +- return { +- originalUrl: url, +- url: fetchUrl, +- headers: headers +- }; +- } +- +- function smartDraw(urlOpt, forced) { +- var url = urlOpt || $url.val(); +- var req = prepareUrl(url); +- draw(req, forced); +- } +- +- function draw(req, forced) { +- if (!validateUrl(req.url)) { +- console.error('Invalid url provided!'); +- return; +- } +- +- if (validateUrl(req.originalUrl)) updateUrl(req.originalUrl); +- +- var outputFormat = $outputFormat.val(); +- var showFiles = $showFiles.is(':checked'); +- var matching = $matching.val(); +- var wordsThreshold = $wordsThreshold.val(); +- var matchingMaxComparisons = $matchingMaxComparisons.val(); +- +- fetch(req.url, { +- method: 'GET', +- headers: req.headers, +- mode: 'cors', +- cache: 'default' +- }) +- .then(function(res) { +- return res.text(); +- }) +- .then(function(data) { +- var container = '#url-diff-container'; +- var diff2htmlUi = new Diff2HtmlUI({diff: data}); +- +- if (outputFormat === 'side-by-side') { +- $container.css({'width': '100%'}); +- } else { +- $container.css({'width': ''}); +- } +- +- var params = getParamsFromSearch(window.location.search); +- delete params[searchParam]; +- +- if (forced) { +- params['outputFormat'] = outputFormat; +- params['showFiles'] = showFiles; +- params['matching'] = matching; +- params['wordsThreshold'] = wordsThreshold; +- params['matchingMaxComparisons'] = matchingMaxComparisons; +- } else { +- params['outputFormat'] = params['outputFormat'] || outputFormat; +- params['showFiles'] = String(params['showFiles']) !== 'false' || (params['showFiles'] === null && showFiles); +- params['matching'] = params['matching'] || matching; +- params['wordsThreshold'] = params['wordsThreshold'] || wordsThreshold; +- params['matchingMaxComparisons'] = params['matchingMaxComparisons'] || matchingMaxComparisons; +- +- $outputFormat.val(params['outputFormat']); +- $showFiles.prop('checked', params['showFiles']); +- $matching.val(params['matching']); +- $wordsThreshold.val(params['wordsThreshold']); +- $matchingMaxComparisons.val(params['matchingMaxComparisons']); +- } +- +- params['synchronisedScroll'] = params['synchronisedScroll'] || true; +- +- diff2htmlUi.draw(container, params); +- diff2htmlUi.fileListCloseable(container, params['fileListCloseable'] || false); +- if (params['highlight'] === undefined || params['highlight']) { +- diff2htmlUi.highlightCode(container); +- } +- }); +- } +- +- function validateUrl(url) { +- return /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(url); +- } +- +- function updateUrl(url) { +- var params = getParamsFromSearch(window.location.search); +- +- if (params[searchParam] === url) return; +- +- params[searchParam] = url; +- +- var paramString = Object.keys(params).map(function(k) { return k + '=' + params[k]; }).join('&'); +- +- window.location = 'demo.html?' + paramString; +- } +-}); +- +-},{"whatwg-fetch":1}]},{},[2]); +diff --git a/docs/demo.min.js b/docs/demo.min.js +deleted file mode 100644 +index 63d41d1e..00000000 +--- a/docs/demo.min.js ++++ /dev/null +@@ -1 +0,0 @@ +-!function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i +- +- +- +- +- +- +- +- +- +- +- diff2html +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-
+- +-
+- +- +-
+- +- diff2html +- +-

Diff parser and pretty html generator

+-

Better diffs, unmatched reviews.

+-

Demo

+- +-
+- +- +- +- +- +- +- +- +- +-
+-
+- +-
+-
+-
+-

Each diff provides a comprehensive visualization of the code changes, +- helping developers identify problems and better understand the changes.

+-
+-
+- +-
+-
+- +- +- +-
Line by Line and Side by Side changes
+-

Each diff features a line by line and side by side preview of your +- changes.

+-
+- +-
+- +- +- +-
Code syntax highlight
+-

All the code changes are syntax highlighted using highlight.js, +- providing more readability.

+-
+- +-
+- +- +- +-
Line similarity matching
+-

Similar lines are paired, allowing for easier change tracking.

+-
+-
+- +-
+-
+-
+-
+-

Install with Bower

+-

You can install and manage diff2html's CSS and JS using Bower:

+-
+-

> $ bower install diff2html

+- Copy +-
+-
+-
+-
+-
+-

Install with npm

+-

You can also install diff2html using npm:

+-
+-

> $ npm install diff2html

+- Copy +-
+-
+-
+- +-
+-
+- +-
+-
+-

With command line integration

+-

We work hard to make sure you can have your diffs in a simple and flexible +- way. Go here full +- documentation.

+-
+-
+-
+-

+- > $ npm install -g diff2html-cli
+- diff2html cli installed! +-

+-

+- > $ diff2html
+- Previous commit changes on your browser +-

+-

+- > $ is that it?
+- Yup, it's that simple.
+-

+-
+-
+-
+- +-
+-
+-
+-
+-

Projects using diff2html

+-
+-
+-
+-
+-
+-
+-
diff2html-cli
+-

diff2html from your terminal to the browser.

+- +- View GitHub +- +-
+-
+-
+-
+-
+-
+-
Codacy
+-

Check code style, security, duplication, complexity and coverage on every change.

+- +- Website +- +-
+-
+-
+-
+-
+-
+-
Ungit
+-

The easiest way to use git. On any platform. Anywhere.

+- +- View GitHub +- +-
+-
+-
+-
+-
+-
+-
Diffy
+-

Share your diffs and explain your ideas without committing.

+- +- Website +- +-
+-
+-
+-
+-
+-
+-
diff-pane
+-

Atom - Diff two panes.

+- +- View GitHub +- +-
+-
+-
+-
+-
+-
+-
node-giff
+-

Display git diff on browser.

+- +- View GitHub +- +-
+-
+-
+-
+-
+-
+-
edgar-monitor
+-

A module that processes new Edgar filings and sends out +- notifications.

+- +- View GitHub +- +-
+-
+-
+-
+-
+-
+-
node-git
+-

Execute Git Command by Node.js.

+- +- View GitHub +- +-
+-
+-
+-
+-
+-
+-
Jenkins
+-

Show diffs between builds

+- +- Website +- +-
+-
+-
+-
+-
+-
+-
Light Review
+-

Code Reviews with maximum control for the leading developers

+- +- Website +- +-
+-
+-
+-
+-
+-
+-
Simple Git
+-

A simple package to be able to drive GIT

+- +- View GitHub +- +-
+-
+-
+-
+-
+-
+- +-
+-
+-

Open Source

+-

diff2html is open source. +- If you'd like to be part of the diff2html community or help us improve, +- find us on GitHub and +- Gitter. Need any help? +-

+- +- Read more in the Docs +- +-
+-
+- +-
+- +- +-
+- +-
+-

+- Website originally designed and built by +- @mdo, +- @fat, and +- @dhg, +- adapted with by +- @rtfpessoa. +-

+- +-
+- +-
+- +- +- +- +- +- +- +- +- +- +- +- +- +diff --git a/docs/main.css b/docs/main.css +deleted file mode 100644 +index 020636b4..00000000 +--- a/docs/main.css ++++ /dev/null +@@ -1,564 +0,0 @@ +-/*! +- * Copyright Colossal 2015 +- * Adapted by @rtfpessoa +- */ +- +-.template-index { +- width: 100%; +-} +- +-.template-index-min { +- min-width: 700px; +-} +- +-.container { +- width: 100%; +- padding: 0 8%; +-} +- +-.m-b-md { +- margin-bottom: 23px !important +-} +- +-.p-t { +- padding-top: 15px !important +-} +- +-@media (min-width: 768px) { +- p.m-b { +- height: 75px; +- overflow-y: hidden; +- } +-} +- +-.btn { +- display: inline-block; +- color: #fff; +- background: #26A65B; +- font-weight: 400 +-} +- +-.btn:hover { +- color: #fff; +- background: #5dbe5d; +-} +- +-.btn-clipboard { +- position: absolute; +- top: 0; +- right: 0; +- z-index: 10; +- display: block; +- padding: 5px 8px; +- font-size: 12px; +- color: #fff; +- background-color: #767676; +- border-radius: 0 4px 0 4px; +- cursor: pointer; +-} +- +-.btn-clipboard:hover { +- color: #000; +- background-color: #dcdfe4; +-} +- +-.footer { +- position: relative; +- padding: 40px 0; +- text-align: center; +- font-size: 14px; +- border-top: 1px solid #dcdfe4 +-} +- +-.footer p { +- margin-bottom: 5px +-} +- +-.footer a { +- color: #26A65B; +-} +- +-.container a { +- color: #26A65B; +-} +- +-.container a.btn { +- color: #fff; +-} +- +-.footer-list-item { +- display: inline-block +-} +- +-.footer-list-item:not(:last-child):after { +- content: "\b7" +-} +- +-.footer > ul { +- padding: 0; +-} +- +-@media (min-width: 768px) { +- .footer { +- padding: 60px 0; +- } +-} +- +-@media (min-width: 768px) { +- .row-centered { +- display: flex; +- align-items: center; +- } +-} +- +-.row-bordered { +- position: relative +-} +- +-.row-bordered:before { +- content: ''; +- display: block; +- width: 80%; +- position: absolute; +- bottom: 0; +- left: 50%; +- margin-left: -40%; +- height: 1px; +- background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.2) 0, rgba(255, 255, 255, 0) 75%) +-} +- +-.hero { +- position: relative; +- text-align: center; +- padding: 80px 0; +- border-bottom: 1px solid #dcdfe4 +-} +- +-.hero-booticon { +- font-family: Helvetica Neue, Helvetica, Arial, sans-serif; +- margin: 0 auto 30px; +- width: 100%; +- font-size: 8vw; +- display: block; +- font-weight: 500; +- text-align: center; +- cursor: default; +-} +- +-.hero-homepage.hero { +- padding-top: 0; +- padding-bottom: 40px; +- overflow: hidden; +- border-bottom: 0; +- border-bottom: 1px solid #dcdfe4; +-} +- +-.hero-homepage > .btn { +- margin-top: 20px +-} +- +-.swag-line:before { +- content: ''; +- position: fixed; +- display: block; +- top: 0; +- left: 0; +- right: 0; +- height: 5px; +- z-index: 2; +- background-color: #26A65B; +- background: linear-gradient(45deg, #28a142, #26A65B) +-} +- +-.navbar { +- background-color: #fff; +- border: 0 #fff; +-} +- +-.navbar-header { +- text-align: center +-} +- +-.navbar-brand { +- height: auto; +- padding: 19px 25px; +- font-size: 16px; +- display: inline-block; +- float: none; +- text-align: center; +- margin: 5px 0 0 +-} +- +-.navbar-nav { +- margin-right: -15px +-} +- +-.navbar-nav > li > a { +- font-size: 14px +-} +- +-.navbar-default .navbar-brand, .navbar-default .navbar-brand:focus, .navbar-default .navbar-brand:hover, .navbar-default .navbar-nav > li > a, .navbar-default .navbar-nav > li > a:focus, .navbar-default .navbar-nav > li > a:hover { +- background: transparent; +- color: #293a46; +- font-weight: 300 +-} +- +-.navbar-default .navbar-toggle { +- position: absolute; +- left: 0; +- top: 7px; +- border-color: #fff; +- color: #293a46; +- margin-right: 0 +-} +- +-.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus { +- background: #f9f9f9; +- border-color: #f9f9f9 +-} +- +-@media (min-width: 768px) { +- .navbar-full .navbar-brand { +- margin-left: -25px +- } +- +- .navbar-tall { +- height: 125px +- } +- +- .navbar-tall .navbar-header, .navbar-tall .navbar-nav { +- line-height: 125px; +- text-align: left +- } +- +- .navbar-brand { +- float: none; +- display: inline-block; +- text-align: left; +- margin: 0 +- } +- +- .navbar-nav > li > a { +- display: inline-block; +- margin-left: 13px +- } +- +- .navbar-nav > li:first-child > a { +- margin-left: 0 +- } +- +-} +- +-.screenshot { +- display: block; +- overflow: hidden; +-} +- +-.screenshot > img { +- width: 100% +-} +- +-.screenshots-fan { +- margin-top: 50px +-} +- +-.screenshots-fan .screenshot { +- position: relative; +- width: auto; +- display: inline-block; +- text-align: center; +-} +- +-.screenshots-fan .screenshot:last-child, .screenshots-fan .screenshot:first-child { +- z-index: 2 +-} +- +-.screenshots-fan .screenshot { +- z-index: 3 +-} +- +-@media (min-width: 768px) { +- .screenshots-fan { +- position: relative; +- overflow: hidden; +- margin-top: 60px; +- height: 200px +- } +- +- .screenshots-fan .screenshot { +- height: auto; +- top: 10px; +- width: 350px +- } +- +- .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { +- width: 250px; +- position: absolute; +- top: 65px +- } +- +- .screenshots-fan .screenshot:first-child { +- left: 10px +- } +- +- .screenshots-fan .screenshot:last-child { +- left: auto; +- right: 10px +- } +-} +- +-@media (min-width: 992px) { +- .screenshots-fan { +- margin-top: 60px; +- height: 240px +- } +- +- .screenshots-fan .screenshot { +- width: 400px +- } +- +- .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { +- width: 300px +- } +-} +- +-@media (min-width: 1200px) { +- .screenshots-fan { +- margin-top: 80px; +- height: 380px +- } +- +- .screenshots-fan .screenshot { +- width: 550px +- } +- +- .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { +- width: 450px +- } +-} +- +-body { +- font-size: 16px; +- font-family: Roboto, sans-serif; +- font-weight: 300; +- line-height: 1.6 +-} +- +-h1 { +- font-size: 26px; +- font-weight: 300 +-} +- +-h2 { +- font-size: 18px; +- font-weight: 300 +-} +- +-h3 { +- font-size: 26px; +- font-weight: 300 +-} +- +-h4 { +- font-size: 16px; +- font-weight: 300 +-} +- +-h5 { +- font-size: 16px; +- font-weight: 400 +-} +- +-h1, h2, h3, h4, h5 { +- line-height: 1.4 +-} +- +-h1, h2 { +- margin: 10px 0 +-} +- +-h5 { +- margin: 6px 0 +-} +- +-@media (min-width: 768px) { +- body { +- font-size: 16px; +- font-family: Roboto, sans-serif; +- font-weight: 300; +- line-height: 1.6 +- } +- +- h1 { +- font-size: 38px; +- font-weight: 300 +- } +- +- h2 { +- font-size: 26px; +- font-weight: 300; +- line-height: 1.4 +- } +- +- h3 { +- font-size: 26px; +- font-weight: 300 +- } +- +- h4 { +- font-size: 18px; +- font-weight: 300 +- } +- +- h5 { +- font-size: 16px; +- font-weight: 400 +- } +-} +- +-body { +- color: #293a46; +-} +- +-a { +- text-decoration: none; +- color: inherit; +-} +- +-a:hover, a:focus { +- text-decoration: underline; +-} +- +-.nav li a { +- text-decoration: none; +- color: inherit; +-} +- +-.nav li a:hover { +- text-decoration: underline; +-} +- +-.text-muted { +- color: #697176 +-} +- +-.template-index h3 { +- font-size: 21px; +- margin-bottom: 12px +-} +- +-.template-index h4 { +- color: #697176; +- line-height: 1.6 +-} +- +-.template-index h4 a, .template-index p a { +- color: #26A65B; +-} +- +-.template-index h5 { +- font-size: 17px; +- margin-bottom: 8px +-} +- +-.homepage-terminal-example, .homepage-code-example { +- position: relative; +- font-family: monospace; +- background: #272b38; +- color: #48d8a0; +- border-radius: 8px; +- padding: 30px +-} +- +-.homepage-terminal-example .text-muted, +-.homepage-code-example .text-muted { +- color: #6a7490 +-} +- +-@media (min-width: 768px) { +- .homepage-terminal-example { +- padding: 50px; +- } +- +- .homepage-code-example { +- padding: 10px; +- } +- +- .homepage-code-example > p { +- margin: 0; +- } +-} +- +-.hero-green { +- color: #26A65B; +-} +- +-.hero-black { +- color: #353535; +-} +- +-.hero-red { +- color: #CB2C37; +-} +- +-.svg-icon-large { +- width: 50px; +- display: block; +- margin: 0 auto; +-} +- +-.svg-icon-large > svg { +- width: 100%; +- height: auto; +-} +- +-.row-padded-small { +- padding: 40px 0; +-} +- +-*.unselectable { +- -webkit-touch-callout: none; +- -webkit-user-select: none; +- -moz-user-select: none; +- -ms-user-select: none; +- user-select: none; +-} +- +-.url-diff-container { +- width: 980px; +-} +- +-.diff-url-wrapper { +- display: flex; +- width: 100%; +-} +- +-.diff-url-input { +- display: inline-block; +- margin-right: 10px; +- flex-grow: 1; +- height: 31px; +-} +- +-.diff-url-btn { +- display: inline-block; +- float: right; +- width: 48px; +-} +- +-.options-label-value { +- font-weight: normal; +-} +- +-.diff-url-options-container label select, +-.diff-url-options-container label input { +- display: block; +-} +- +-/* 15 columns */ +- +-.col-md- *.col-md-15 { +- width: 20%; +-} +- +-/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3dlYnNpdGUvbWFpbi5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztFQUdFOztBQUVGO0VBQ0UsV0FBVztBQUNiOztBQUVBO0VBQ0UsZ0JBQWdCO0FBQ2xCOztBQUVBO0VBQ0UsV0FBVztFQUNYLGFBQWE7QUFDZjs7QUFFQTtFQUNFO0FBQ0Y7O0FBRUE7RUFDRTtBQUNGOztBQUVBO0VBQ0U7SUFDRSxZQUFZO0lBQ1osa0JBQWtCO0VBQ3BCO0FBQ0Y7O0FBRUE7RUFDRSxxQkFBcUI7RUFDckIsV0FBVztFQUNYLG1CQUFtQjtFQUNuQjtBQUNGOztBQUVBO0VBQ0UsV0FBVztFQUNYLG1CQUFtQjtBQUNyQjs7QUFFQTtFQUNFLGtCQUFrQjtFQUNsQixNQUFNO0VBQ04sUUFBUTtFQUNSLFdBQVc7RUFDWCxjQUFjO0VBQ2QsZ0JBQWdCO0VBQ2hCLGVBQWU7RUFDZixXQUFXO0VBQ1gseUJBQXlCO0VBQ3pCLDBCQUEwQjtFQUMxQixlQUFlO0FBQ2pCOztBQUVBO0VBQ0UsV0FBVztFQUNYLHlCQUF5QjtBQUMzQjs7QUFFQTtFQUNFLGtCQUFrQjtFQUNsQixlQUFlO0VBQ2Ysa0JBQWtCO0VBQ2xCLGVBQWU7RUFDZjtBQUNGOztBQUVBO0VBQ0U7QUFDRjs7QUFFQTtFQUNFLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSxjQUFjO0FBQ2hCOztBQUVBO0VBQ0UsV0FBVztBQUNiOztBQUVBO0VBQ0U7QUFDRjs7QUFFQTtFQUNFO0FBQ0Y7O0FBRUE7RUFDRSxVQUFVO0FBQ1o7O0FBRUE7RUFDRTtJQUNFLGVBQWU7RUFDakI7QUFDRjs7QUFFQTtFQUNFO0lBR0UsYUFBYTtJQUdiLG1CQUFtQjtFQUNyQjtBQUNGOztBQUVBO0VBQ0U7QUFDRjs7QUFFQTtFQUNFLFdBQVc7RUFDWCxjQUFjO0VBQ2QsVUFBVTtFQUNWLGtCQUFrQjtFQUNsQixTQUFTO0VBQ1QsU0FBUztFQUNULGlCQUFpQjtFQUNqQixXQUFXO0VBRVg7QUFDRjs7QUFFQTtFQUNFLGtCQUFrQjtFQUNsQixrQkFBa0I7RUFDbEIsZUFBZTtFQUNmO0FBQ0Y7O0FBRUE7RUFDRSx5REFBeUQ7RUFDekQsbUJBQW1CO0VBQ25CLFdBQVc7RUFDWCxjQUFjO0VBQ2QsY0FBYztFQUNkLGdCQUFnQjtFQUNoQixrQkFBa0I7RUFDbEIsZUFBZTtBQUNqQjs7QUFFQTtFQUNFLGNBQWM7RUFDZCxvQkFBb0I7RUFDcEIsZ0JBQWdCO0VBQ2hCLGdCQUFnQjtFQUNoQixnQ0FBZ0M7QUFDbEM7O0FBRUE7RUFDRTtBQUNGOztBQUVBO0VBQ0UsV0FBVztFQUNYLGVBQWU7RUFDZixjQUFjO0VBQ2QsTUFBTTtFQUNOLE9BQU87RUFDUCxRQUFRO0VBQ1IsV0FBVztFQUNYLFVBQVU7RUFDVix5QkFBeUI7RUFFekI7QUFDRjs7QUFFQTtFQUNFLHNCQUFzQjtFQUN0QixjQUFjO0FBQ2hCOztBQUVBO0VBQ0U7QUFDRjs7QUFFQTtFQUNFLFlBQVk7RUFDWixrQkFBa0I7RUFDbEIsZUFBZTtFQUNmLHFCQUFxQjtFQUNyQixXQUFXO0VBQ1gsa0JBQWtCO0VBQ2xCO0FBQ0Y7O0FBRUE7RUFDRTtBQUNGOztBQUVBO0VBQ0U7QUFDRjs7QUFFQTtFQUNFLHVCQUF1QjtFQUN2QixjQUFjO0VBQ2Q7QUFDRjs7QUFFQTtFQUNFLGtCQUFrQjtFQUNsQixPQUFPO0VBQ1AsUUFBUTtFQUNSLGtCQUFrQjtFQUNsQixjQUFjO0VBQ2Q7QUFDRjs7QUFFQTtFQUNFLG1CQUFtQjtFQUNuQjtBQUNGOztBQUVBO0VBQ0U7SUFDRTtFQUNGOztFQUVBO0lBQ0U7RUFDRjs7RUFFQTtJQUNFLGtCQUFrQjtJQUNsQjtFQUNGOztFQUVBO0lBQ0UsV0FBVztJQUNYLHFCQUFxQjtJQUNyQixnQkFBZ0I7SUFDaEI7RUFDRjs7RUFFQTtJQUNFLHFCQUFxQjtJQUNyQjtFQUNGOztFQUVBO0lBQ0U7RUFDRjs7QUFFRjs7QUFFQTtFQUNFLGNBQWM7RUFDZCxnQkFBZ0I7QUFDbEI7O0FBRUE7RUFDRTtBQUNGOztBQUVBO0VBQ0U7QUFDRjs7QUFFQTtFQUNFLGtCQUFrQjtFQUNsQixXQUFXO0VBQ1gscUJBQXFCO0VBQ3JCLGtCQUFrQjtBQUNwQjs7QUFFQTtFQUNFO0FBQ0Y7O0FBRUE7RUFDRTtBQUNGOztBQUVBO0VBQ0U7SUFDRSxrQkFBa0I7SUFDbEIsZ0JBQWdCO0lBQ2hCLGdCQUFnQjtJQUNoQjtFQUNGOztFQUVBO0lBQ0UsWUFBWTtJQUNaLFNBQVM7SUFDVDtFQUNGOztFQUVBO0lBQ0UsWUFBWTtJQUNaLGtCQUFrQjtJQUNsQjtFQUNGOztFQUVBO0lBQ0U7RUFDRjs7RUFFQTtJQUNFLFVBQVU7SUFDVjtFQUNGO0FBQ0Y7O0FBRUE7RUFDRTtJQUNFLGdCQUFnQjtJQUNoQjtFQUNGOztFQUVBO0lBQ0U7RUFDRjs7RUFFQTtJQUNFO0VBQ0Y7QUFDRjs7QUFFQTtFQUNFO0lBQ0UsZ0JBQWdCO0lBQ2hCO0VBQ0Y7O0VBRUE7SUFDRTtFQUNGOztFQUVBO0lBQ0U7RUFDRjtBQUNGOztBQUVBO0VBQ0UsZUFBZTtFQUNmLCtCQUErQjtFQUMvQixnQkFBZ0I7RUFDaEI7QUFDRjs7QUFFQTtFQUNFLGVBQWU7RUFDZjtBQUNGOztBQUVBO0VBQ0UsZUFBZTtFQUNmO0FBQ0Y7O0FBRUE7RUFDRSxlQUFlO0VBQ2Y7QUFDRjs7QUFFQTtFQUNFLGVBQWU7RUFDZjtBQUNGOztBQUVBO0VBQ0UsZUFBZTtFQUNmO0FBQ0Y7O0FBRUE7RUFDRTtBQUNGOztBQUVBO0VBQ0U7QUFDRjs7QUFFQTtFQUNFO0FBQ0Y7O0FBRUE7RUFDRTtJQUNFLGVBQWU7SUFDZiwrQkFBK0I7SUFDL0IsZ0JBQWdCO0lBQ2hCO0VBQ0Y7O0VBRUE7SUFDRSxlQUFlO0lBQ2Y7RUFDRjs7RUFFQTtJQUNFLGVBQWU7SUFDZixnQkFBZ0I7SUFDaEI7RUFDRjs7RUFFQTtJQUNFLGVBQWU7SUFDZjtFQUNGOztFQUVBO0lBQ0UsZUFBZTtJQUNmO0VBQ0Y7O0VBRUE7SUFDRSxlQUFlO0lBQ2Y7RUFDRjtBQUNGOztBQUVBO0VBQ0UsY0FBYztBQUNoQjs7QUFFQTtFQUNFLHFCQUFxQjtFQUNyQixjQUFjO0FBQ2hCOztBQUVBO0VBQ0UsMEJBQTBCO0FBQzVCOztBQUVBO0VBQ0UscUJBQXFCO0VBQ3JCLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSwwQkFBMEI7QUFDNUI7O0FBRUE7RUFDRTtBQUNGOztBQUVBO0VBQ0UsZUFBZTtFQUNmO0FBQ0Y7O0FBRUE7RUFDRSxjQUFjO0VBQ2Q7QUFDRjs7QUFFQTtFQUNFLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSxlQUFlO0VBQ2Y7QUFDRjs7QUFFQTtFQUNFLGtCQUFrQjtFQUNsQixzQkFBc0I7RUFDdEIsbUJBQW1CO0VBQ25CLGNBQWM7RUFDZCxrQkFBa0I7RUFDbEI7QUFDRjs7QUFFQTs7RUFFRTtBQUNGOztBQUVBO0VBQ0U7SUFDRSxhQUFhO0VBQ2Y7O0VBRUE7SUFDRSxhQUFhO0VBQ2Y7O0VBRUE7SUFDRSxTQUFTO0VBQ1g7QUFDRjs7QUFFQTtFQUNFLGNBQWM7QUFDaEI7O0FBRUE7RUFDRSxjQUFjO0FBQ2hCOztBQUVBO0VBQ0UsY0FBYztBQUNoQjs7QUFFQTtFQUNFLFdBQVc7RUFDWCxjQUFjO0VBQ2QsY0FBYztBQUNoQjs7QUFFQTtFQUNFLFdBQVc7RUFDWCxZQUFZO0FBQ2Q7O0FBRUE7RUFDRSxlQUFlO0FBQ2pCOztBQUVBO0VBQ0UsMkJBQTJCO0VBQzNCLHlCQUF5QjtFQUN6QixzQkFBc0I7RUFDdEIscUJBQXFCO0VBQ3JCLGlCQUFpQjtBQUNuQjs7QUFFQTtFQUNFLFlBQVk7QUFDZDs7QUFFQTtFQUNFLGFBQWE7RUFDYixXQUFXO0FBQ2I7O0FBRUE7RUFDRSxxQkFBcUI7RUFDckIsa0JBQWtCO0VBQ2xCLFlBQVk7RUFDWixZQUFZO0FBQ2Q7O0FBRUE7RUFDRSxxQkFBcUI7RUFDckIsWUFBWTtFQUNaLFdBQVc7QUFDYjs7QUFFQTtFQUNFLG1CQUFtQjtBQUNyQjs7QUFFQTs7RUFFRSxjQUFjO0FBQ2hCOztBQUVBLGVBQWU7O0FBRWY7RUFDRSxVQUFVO0FBQ1oiLCJmaWxlIjoibWFpbi5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIENvcHlyaWdodCBDb2xvc3NhbCAyMDE1XG4gKiBBZGFwdGVkIGJ5IEBydGZwZXNzb2FcbiAqL1xuXG4udGVtcGxhdGUtaW5kZXgge1xuICB3aWR0aDogMTAwJTtcbn1cblxuLnRlbXBsYXRlLWluZGV4LW1pbiB7XG4gIG1pbi13aWR0aDogNzAwcHg7XG59XG5cbi5jb250YWluZXIge1xuICB3aWR0aDogMTAwJTtcbiAgcGFkZGluZzogMCA4JTtcbn1cblxuLm0tYi1tZCB7XG4gIG1hcmdpbi1ib3R0b206IDIzcHggIWltcG9ydGFudFxufVxuXG4ucC10IHtcbiAgcGFkZGluZy10b3A6IDE1cHggIWltcG9ydGFudFxufVxuXG5AbWVkaWEgKG1pbi13aWR0aDogNzY4cHgpIHtcbiAgcC5tLWIge1xuICAgIGhlaWdodDogNzVweDtcbiAgICBvdmVyZmxvdy15OiBoaWRkZW47XG4gIH1cbn1cblxuLmJ0biB7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgY29sb3I6ICNmZmY7XG4gIGJhY2tncm91bmQ6ICMyNkE2NUI7XG4gIGZvbnQtd2VpZ2h0OiA0MDBcbn1cblxuLmJ0bjpob3ZlciB7XG4gIGNvbG9yOiAjZmZmO1xuICBiYWNrZ3JvdW5kOiAjNWRiZTVkO1xufVxuXG4uYnRuLWNsaXBib2FyZCB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgdG9wOiAwO1xuICByaWdodDogMDtcbiAgei1pbmRleDogMTA7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICBwYWRkaW5nOiA1cHggOHB4O1xuICBmb250LXNpemU6IDEycHg7XG4gIGNvbG9yOiAjZmZmO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNzY3Njc2O1xuICBib3JkZXItcmFkaXVzOiAwIDRweCAwIDRweDtcbiAgY3Vyc29yOiBwb2ludGVyO1xufVxuXG4uYnRuLWNsaXBib2FyZDpob3ZlciB7XG4gIGNvbG9yOiAjMDAwO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNkZmU0O1xufVxuXG4uZm9vdGVyIHtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xuICBwYWRkaW5nOiA0MHB4IDA7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgZm9udC1zaXplOiAxNHB4O1xuICBib3JkZXItdG9wOiAxcHggc29saWQgI2RjZGZlNFxufVxuXG4uZm9vdGVyIHAge1xuICBtYXJnaW4tYm90dG9tOiA1cHhcbn1cblxuLmZvb3RlciBhIHtcbiAgY29sb3I6ICMyNkE2NUI7XG59XG5cbi5jb250YWluZXIgYSB7XG4gIGNvbG9yOiAjMjZBNjVCO1xufVxuXG4uY29udGFpbmVyIGEuYnRuIHtcbiAgY29sb3I6ICNmZmY7XG59XG5cbi5mb290ZXItbGlzdC1pdGVtIHtcbiAgZGlzcGxheTogaW5saW5lLWJsb2NrXG59XG5cbi5mb290ZXItbGlzdC1pdGVtOm5vdCg6bGFzdC1jaGlsZCk6YWZ0ZXIge1xuICBjb250ZW50OiBcIlxcYjdcIlxufVxuXG4uZm9vdGVyID4gdWwge1xuICBwYWRkaW5nOiAwO1xufVxuXG5AbWVkaWEgKG1pbi13aWR0aDogNzY4cHgpIHtcbiAgLmZvb3RlciB7XG4gICAgcGFkZGluZzogNjBweCAwO1xuICB9XG59XG5cbkBtZWRpYSAobWluLXdpZHRoOiA3NjhweCkge1xuICAucm93LWNlbnRlcmVkIHtcbiAgICBkaXNwbGF5OiAtd2Via2l0LWJveDtcbiAgICBkaXNwbGF5OiAtbXMtZmxleGJveDtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIC13ZWJraXQtYm94LWFsaWduOiBjZW50ZXI7XG4gICAgLW1zLWZsZXgtYWxpZ246IGNlbnRlcjtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICB9XG59XG5cbi5yb3ctYm9yZGVyZWQge1xuICBwb3NpdGlvbjogcmVsYXRpdmVcbn1cblxuLnJvdy1ib3JkZXJlZDpiZWZvcmUge1xuICBjb250ZW50OiAnJztcbiAgZGlzcGxheTogYmxvY2s7XG4gIHdpZHRoOiA4MCU7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgYm90dG9tOiAwO1xuICBsZWZ0OiA1MCU7XG4gIG1hcmdpbi1sZWZ0OiAtNDAlO1xuICBoZWlnaHQ6IDFweDtcbiAgYmFja2dyb3VuZDogLXdlYmtpdC1yYWRpYWwtZ3JhZGllbnQoZWxsaXBzZSBhdCBjZW50ZXIsIHJnYmEoMCwgMCwgMCwgMC4yKSAwLCByZ2JhKDI1NSwgMjU1LCAyNTUsIDApIDc1JSk7XG4gIGJhY2tncm91bmQ6IHJhZGlhbC1ncmFkaWVudChlbGxpcHNlIGF0IGNlbnRlciwgcmdiYSgwLCAwLCAwLCAwLjIpIDAsIHJnYmEoMjU1LCAyNTUsIDI1NSwgMCkgNzUlKVxufVxuXG4uaGVybyB7XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgdGV4dC1hbGlnbjogY2VudGVyO1xuICBwYWRkaW5nOiA4MHB4IDA7XG4gIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjZGNkZmU0XG59XG5cbi5oZXJvLWJvb3RpY29uIHtcbiAgZm9udC1mYW1pbHk6IEhlbHZldGljYSBOZXVlLCBIZWx2ZXRpY2EsIEFyaWFsLCBzYW5zLXNlcmlmO1xuICBtYXJnaW46IDAgYXV0byAzMHB4O1xuICB3aWR0aDogMTAwJTtcbiAgZm9udC1zaXplOiA4dnc7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICBmb250LXdlaWdodDogNTAwO1xuICB0ZXh0LWFsaWduOiBjZW50ZXI7XG4gIGN1cnNvcjogZGVmYXVsdDtcbn1cblxuLmhlcm8taG9tZXBhZ2UuaGVybyB7XG4gIHBhZGRpbmctdG9wOiAwO1xuICBwYWRkaW5nLWJvdHRvbTogNDBweDtcbiAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgYm9yZGVyLWJvdHRvbTogMDtcbiAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNkY2RmZTQ7XG59XG5cbi5oZXJvLWhvbWVwYWdlID4gLmJ0biB7XG4gIG1hcmdpbi10b3A6IDIwcHhcbn1cblxuLnN3YWctbGluZTpiZWZvcmUge1xuICBjb250ZW50OiAnJztcbiAgcG9zaXRpb246IGZpeGVkO1xuICBkaXNwbGF5OiBibG9jaztcbiAgdG9wOiAwO1xuICBsZWZ0OiAwO1xuICByaWdodDogMDtcbiAgaGVpZ2h0OiA1cHg7XG4gIHotaW5kZXg6IDI7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyNkE2NUI7XG4gIGJhY2tncm91bmQ6IC13ZWJraXQtbGluZWFyLWdyYWRpZW50KDQ1ZGVnLCAjMjhhMTQyLCAjMjZBNjVCKTtcbiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDQ1ZGVnLCAjMjhhMTQyLCAjMjZBNjVCKVxufVxuXG4ubmF2YmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZjtcbiAgYm9yZGVyOiAwICNmZmY7XG59XG5cbi5uYXZiYXItaGVhZGVyIHtcbiAgdGV4dC1hbGlnbjogY2VudGVyXG59XG5cbi5uYXZiYXItYnJhbmQge1xuICBoZWlnaHQ6IGF1dG87XG4gIHBhZGRpbmc6IDE5cHggMjVweDtcbiAgZm9udC1zaXplOiAxNnB4O1xuICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gIGZsb2F0OiBub25lO1xuICB0ZXh0LWFsaWduOiBjZW50ZXI7XG4gIG1hcmdpbjogNXB4IDAgMFxufVxuXG4ubmF2YmFyLW5hdiB7XG4gIG1hcmdpbi1yaWdodDogLTE1cHhcbn1cblxuLm5hdmJhci1uYXYgPiBsaSA+IGEge1xuICBmb250LXNpemU6IDE0cHhcbn1cblxuLm5hdmJhci1kZWZhdWx0IC5uYXZiYXItYnJhbmQsIC5uYXZiYXItZGVmYXVsdCAubmF2YmFyLWJyYW5kOmZvY3VzLCAubmF2YmFyLWRlZmF1bHQgLm5hdmJhci1icmFuZDpob3ZlciwgLm5hdmJhci1kZWZhdWx0IC5uYXZiYXItbmF2ID4gbGkgPiBhLCAubmF2YmFyLWRlZmF1bHQgLm5hdmJhci1uYXYgPiBsaSA+IGE6Zm9jdXMsIC5uYXZiYXItZGVmYXVsdCAubmF2YmFyLW5hdiA+IGxpID4gYTpob3ZlciB7XG4gIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICBjb2xvcjogIzI5M2E0NjtcbiAgZm9udC13ZWlnaHQ6IDMwMFxufVxuXG4ubmF2YmFyLWRlZmF1bHQgLm5hdmJhci10b2dnbGUge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIGxlZnQ6IDA7XG4gIHRvcDogN3B4O1xuICBib3JkZXItY29sb3I6ICNmZmY7XG4gIGNvbG9yOiAjMjkzYTQ2O1xuICBtYXJnaW4tcmlnaHQ6IDBcbn1cblxuLm5hdmJhci1kZWZhdWx0IC5uYXZiYXItdG9nZ2xlOmhvdmVyLCAubmF2YmFyLWRlZmF1bHQgLm5hdmJhci10b2dnbGU6Zm9jdXMge1xuICBiYWNrZ3JvdW5kOiAjZjlmOWY5O1xuICBib3JkZXItY29sb3I6ICNmOWY5Zjlcbn1cblxuQG1lZGlhIChtaW4td2lkdGg6IDc2OHB4KSB7XG4gIC5uYXZiYXItZnVsbCAubmF2YmFyLWJyYW5kIHtcbiAgICBtYXJnaW4tbGVmdDogLTI1cHhcbiAgfVxuXG4gIC5uYXZiYXItdGFsbCB7XG4gICAgaGVpZ2h0OiAxMjVweFxuICB9XG5cbiAgLm5hdmJhci10YWxsIC5uYXZiYXItaGVhZGVyLCAubmF2YmFyLXRhbGwgLm5hdmJhci1uYXYge1xuICAgIGxpbmUtaGVpZ2h0OiAxMjVweDtcbiAgICB0ZXh0LWFsaWduOiBsZWZ0XG4gIH1cblxuICAubmF2YmFyLWJyYW5kIHtcbiAgICBmbG9hdDogbm9uZTtcbiAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gICAgdGV4dC1hbGlnbjogbGVmdDtcbiAgICBtYXJnaW46IDBcbiAgfVxuXG4gIC5uYXZiYXItbmF2ID4gbGkgPiBhIHtcbiAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gICAgbWFyZ2luLWxlZnQ6IDEzcHhcbiAgfVxuXG4gIC5uYXZiYXItbmF2ID4gbGk6Zmlyc3QtY2hpbGQgPiBhIHtcbiAgICBtYXJnaW4tbGVmdDogMFxuICB9XG5cbn1cblxuLnNjcmVlbnNob3Qge1xuICBkaXNwbGF5OiBibG9jaztcbiAgb3ZlcmZsb3c6IGhpZGRlbjtcbn1cblxuLnNjcmVlbnNob3QgPiBpbWcge1xuICB3aWR0aDogMTAwJVxufVxuXG4uc2NyZWVuc2hvdHMtZmFuIHtcbiAgbWFyZ2luLXRvcDogNTBweFxufVxuXG4uc2NyZWVuc2hvdHMtZmFuIC5zY3JlZW5zaG90IHtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xuICB3aWR0aDogYXV0bztcbiAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xuICB0ZXh0LWFsaWduOiBjZW50ZXI7XG59XG5cbi5zY3JlZW5zaG90cy1mYW4gLnNjcmVlbnNob3Q6bGFzdC1jaGlsZCwgLnNjcmVlbnNob3RzLWZhbiAuc2NyZWVuc2hvdDpmaXJzdC1jaGlsZCB7XG4gIHotaW5kZXg6IDJcbn1cblxuLnNjcmVlbnNob3RzLWZhbiAuc2NyZWVuc2hvdCB7XG4gIHotaW5kZXg6IDNcbn1cblxuQG1lZGlhIChtaW4td2lkdGg6IDc2OHB4KSB7XG4gIC5zY3JlZW5zaG90cy1mYW4ge1xuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgIG1hcmdpbi10b3A6IDYwcHg7XG4gICAgaGVpZ2h0OiAyMDBweFxuICB9XG5cbiAgLnNjcmVlbnNob3RzLWZhbiAuc2NyZWVuc2hvdCB7XG4gICAgaGVpZ2h0OiBhdXRvO1xuICAgIHRvcDogMTBweDtcbiAgICB3aWR0aDogMzUwcHhcbiAgfVxuXG4gIC5zY3JlZW5zaG90cy1mYW4gLnNjcmVlbnNob3Q6Zmlyc3QtY2hpbGQsIC5zY3JlZW5zaG90cy1mYW4gLnNjcmVlbnNob3Q6bGFzdC1jaGlsZCB7XG4gICAgd2lkdGg6IDI1MHB4O1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDY1cHhcbiAgfVxuXG4gIC5zY3JlZW5zaG90cy1mYW4gLnNjcmVlbnNob3Q6Zmlyc3QtY2hpbGQge1xuICAgIGxlZnQ6IDEwcHhcbiAgfVxuXG4gIC5zY3JlZW5zaG90cy1mYW4gLnNjcmVlbnNob3Q6bGFzdC1jaGlsZCB7XG4gICAgbGVmdDogYXV0bztcbiAgICByaWdodDogMTBweFxuICB9XG59XG5cbkBtZWRpYSAobWluLXdpZHRoOiA5OTJweCkge1xuICAuc2NyZWVuc2hvdHMtZmFuIHtcbiAgICBtYXJnaW4tdG9wOiA2MHB4O1xuICAgIGhlaWdodDogMjQwcHhcbiAgfVxuXG4gIC5zY3JlZW5zaG90cy1mYW4gLnNjcmVlbnNob3Qge1xuICAgIHdpZHRoOiA0MDBweFxuICB9XG5cbiAgLnNjcmVlbnNob3RzLWZhbiAuc2NyZWVuc2hvdDpmaXJzdC1jaGlsZCwgLnNjcmVlbnNob3RzLWZhbiAuc2NyZWVuc2hvdDpsYXN0LWNoaWxkIHtcbiAgICB3aWR0aDogMzAwcHhcbiAgfVxufVxuXG5AbWVkaWEgKG1pbi13aWR0aDogMTIwMHB4KSB7XG4gIC5zY3JlZW5zaG90cy1mYW4ge1xuICAgIG1hcmdpbi10b3A6IDgwcHg7XG4gICAgaGVpZ2h0OiAzODBweFxuICB9XG5cbiAgLnNjcmVlbnNob3RzLWZhbiAuc2NyZWVuc2hvdCB7XG4gICAgd2lkdGg6IDU1MHB4XG4gIH1cblxuICAuc2NyZWVuc2hvdHMtZmFuIC5zY3JlZW5zaG90OmZpcnN0LWNoaWxkLCAuc2NyZWVuc2hvdHMtZmFuIC5zY3JlZW5zaG90Omxhc3QtY2hpbGQge1xuICAgIHdpZHRoOiA0NTBweFxuICB9XG59XG5cbmJvZHkge1xuICBmb250LXNpemU6IDE2cHg7XG4gIGZvbnQtZmFtaWx5OiBSb2JvdG8sIHNhbnMtc2VyaWY7XG4gIGZvbnQtd2VpZ2h0OiAzMDA7XG4gIGxpbmUtaGVpZ2h0OiAxLjZcbn1cblxuaDEge1xuICBmb250LXNpemU6IDI2cHg7XG4gIGZvbnQtd2VpZ2h0OiAzMDBcbn1cblxuaDIge1xuICBmb250LXNpemU6IDE4cHg7XG4gIGZvbnQtd2VpZ2h0OiAzMDBcbn1cblxuaDMge1xuICBmb250LXNpemU6IDI2cHg7XG4gIGZvbnQtd2VpZ2h0OiAzMDBcbn1cblxuaDQge1xuICBmb250LXNpemU6IDE2cHg7XG4gIGZvbnQtd2VpZ2h0OiAzMDBcbn1cblxuaDUge1xuICBmb250LXNpemU6IDE2cHg7XG4gIGZvbnQtd2VpZ2h0OiA0MDBcbn1cblxuaDEsIGgyLCBoMywgaDQsIGg1IHtcbiAgbGluZS1oZWlnaHQ6IDEuNFxufVxuXG5oMSwgaDIge1xuICBtYXJnaW46IDEwcHggMFxufVxuXG5oNSB7XG4gIG1hcmdpbjogNnB4IDBcbn1cblxuQG1lZGlhIChtaW4td2lkdGg6IDc2OHB4KSB7XG4gIGJvZHkge1xuICAgIGZvbnQtc2l6ZTogMTZweDtcbiAgICBmb250LWZhbWlseTogUm9ib3RvLCBzYW5zLXNlcmlmO1xuICAgIGZvbnQtd2VpZ2h0OiAzMDA7XG4gICAgbGluZS1oZWlnaHQ6IDEuNlxuICB9XG5cbiAgaDEge1xuICAgIGZvbnQtc2l6ZTogMzhweDtcbiAgICBmb250LXdlaWdodDogMzAwXG4gIH1cblxuICBoMiB7XG4gICAgZm9udC1zaXplOiAyNnB4O1xuICAgIGZvbnQtd2VpZ2h0OiAzMDA7XG4gICAgbGluZS1oZWlnaHQ6IDEuNFxuICB9XG5cbiAgaDMge1xuICAgIGZvbnQtc2l6ZTogMjZweDtcbiAgICBmb250LXdlaWdodDogMzAwXG4gIH1cblxuICBoNCB7XG4gICAgZm9udC1zaXplOiAxOHB4O1xuICAgIGZvbnQtd2VpZ2h0OiAzMDBcbiAgfVxuXG4gIGg1IHtcbiAgICBmb250LXNpemU6IDE2cHg7XG4gICAgZm9udC13ZWlnaHQ6IDQwMFxuICB9XG59XG5cbmJvZHkge1xuICBjb2xvcjogIzI5M2E0Njtcbn1cblxuYSB7XG4gIHRleHQtZGVjb3JhdGlvbjogbm9uZTtcbiAgY29sb3I6IGluaGVyaXQ7XG59XG5cbmE6aG92ZXIsIGE6Zm9jdXMge1xuICB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTtcbn1cblxuLm5hdiBsaSBhIHtcbiAgdGV4dC1kZWNvcmF0aW9uOiBub25lO1xuICBjb2xvcjogaW5oZXJpdDtcbn1cblxuLm5hdiBsaSBhOmhvdmVyIHtcbiAgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7XG59XG5cbi50ZXh0LW11dGVkIHtcbiAgY29sb3I6ICM2OTcxNzZcbn1cblxuLnRlbXBsYXRlLWluZGV4IGgzIHtcbiAgZm9udC1zaXplOiAyMXB4O1xuICBtYXJnaW4tYm90dG9tOiAxMnB4XG59XG5cbi50ZW1wbGF0ZS1pbmRleCBoNCB7XG4gIGNvbG9yOiAjNjk3MTc2O1xuICBsaW5lLWhlaWdodDogMS42XG59XG5cbi50ZW1wbGF0ZS1pbmRleCBoNCBhLCAudGVtcGxhdGUtaW5kZXggcCBhIHtcbiAgY29sb3I6ICMyNkE2NUI7XG59XG5cbi50ZW1wbGF0ZS1pbmRleCBoNSB7XG4gIGZvbnQtc2l6ZTogMTdweDtcbiAgbWFyZ2luLWJvdHRvbTogOHB4XG59XG5cbi5ob21lcGFnZS10ZXJtaW5hbC1leGFtcGxlLCAuaG9tZXBhZ2UtY29kZS1leGFtcGxlIHtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xuICBmb250LWZhbWlseTogbW9ub3NwYWNlO1xuICBiYWNrZ3JvdW5kOiAjMjcyYjM4O1xuICBjb2xvcjogIzQ4ZDhhMDtcbiAgYm9yZGVyLXJhZGl1czogOHB4O1xuICBwYWRkaW5nOiAzMHB4XG59XG5cbi5ob21lcGFnZS10ZXJtaW5hbC1leGFtcGxlIC50ZXh0LW11dGVkLFxuLmhvbWVwYWdlLWNvZGUtZXhhbXBsZSAudGV4dC1tdXRlZCB7XG4gIGNvbG9yOiAjNmE3NDkwXG59XG5cbkBtZWRpYSAobWluLXdpZHRoOiA3NjhweCkge1xuICAuaG9tZXBhZ2UtdGVybWluYWwtZXhhbXBsZSB7XG4gICAgcGFkZGluZzogNTBweDtcbiAgfVxuXG4gIC5ob21lcGFnZS1jb2RlLWV4YW1wbGUge1xuICAgIHBhZGRpbmc6IDEwcHg7XG4gIH1cblxuICAuaG9tZXBhZ2UtY29kZS1leGFtcGxlID4gcCB7XG4gICAgbWFyZ2luOiAwO1xuICB9XG59XG5cbi5oZXJvLWdyZWVuIHtcbiAgY29sb3I6ICMyNkE2NUI7XG59XG5cbi5oZXJvLWJsYWNrIHtcbiAgY29sb3I6ICMzNTM1MzU7XG59XG5cbi5oZXJvLXJlZCB7XG4gIGNvbG9yOiAjQ0IyQzM3O1xufVxuXG4uc3ZnLWljb24tbGFyZ2Uge1xuICB3aWR0aDogNTBweDtcbiAgZGlzcGxheTogYmxvY2s7XG4gIG1hcmdpbjogMCBhdXRvO1xufVxuXG4uc3ZnLWljb24tbGFyZ2UgPiBzdmcge1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiBhdXRvO1xufVxuXG4ucm93LXBhZGRlZC1zbWFsbCB7XG4gIHBhZGRpbmc6IDQwcHggMDtcbn1cblxuKi51bnNlbGVjdGFibGUge1xuICAtd2Via2l0LXRvdWNoLWNhbGxvdXQ6IG5vbmU7XG4gIC13ZWJraXQtdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC1tb3otdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC1tcy11c2VyLXNlbGVjdDogbm9uZTtcbiAgdXNlci1zZWxlY3Q6IG5vbmU7XG59XG5cbi51cmwtZGlmZi1jb250YWluZXIge1xuICB3aWR0aDogOTgwcHg7XG59XG5cbi5kaWZmLXVybC13cmFwcGVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgd2lkdGg6IDEwMCU7XG59XG5cbi5kaWZmLXVybC1pbnB1dCB7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgbWFyZ2luLXJpZ2h0OiAxMHB4O1xuICBmbGV4LWdyb3c6IDE7XG4gIGhlaWdodDogMzFweDtcbn1cblxuLmRpZmYtdXJsLWJ0biB7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgZmxvYXQ6IHJpZ2h0O1xuICB3aWR0aDogNDhweDtcbn1cblxuLm9wdGlvbnMtbGFiZWwtdmFsdWUge1xuICBmb250LXdlaWdodDogbm9ybWFsO1xufVxuXG4uZGlmZi11cmwtb3B0aW9ucy1jb250YWluZXIgbGFiZWwgc2VsZWN0LFxuLmRpZmYtdXJsLW9wdGlvbnMtY29udGFpbmVyIGxhYmVsIGlucHV0IHtcbiAgZGlzcGxheTogYmxvY2s7XG59XG5cbi8qIDE1IGNvbHVtbnMgKi9cblxuLmNvbC1tZC0gKi5jb2wtbWQtMTUge1xuICB3aWR0aDogMjAlO1xufVxuIl19 */ +\ No newline at end of file +diff --git a/docs/main.min.css b/docs/main.min.css +deleted file mode 100644 +index 7e1fd93b..00000000 +--- a/docs/main.min.css ++++ /dev/null +@@ -1,4 +0,0 @@ +-/*! +- * Copyright Colossal 2015 +- * Adapted by @rtfpessoa +- */.template-index{width:100%}.template-index-min{min-width:700px}.container{width:100%;padding:0 8%}.m-b-md{margin-bottom:23px!important}.p-t{padding-top:15px!important}@media (min-width:768px){p.m-b{height:75px;overflow-y:hidden}}.btn{display:inline-block;color:#fff;background:#26a65b;font-weight:400}.btn:hover{color:#fff;background:#5dbe5d}.btn-clipboard{position:absolute;top:0;right:0;z-index:10;display:block;padding:5px 8px;font-size:12px;color:#fff;background-color:#767676;border-radius:0 4px 0 4px;cursor:pointer}.btn-clipboard:hover{color:#000;background-color:#dcdfe4}.footer{position:relative;padding:40px 0;text-align:center;font-size:14px;border-top:1px solid #dcdfe4}.footer p{margin-bottom:5px}.footer a{color:#26a65b}.container a{color:#26a65b}.container a.btn{color:#fff}.footer-list-item{display:inline-block}.footer-list-item:not(:last-child):after{content:"\b7"}.footer>ul{padding:0}@media (min-width:768px){.footer{padding:60px 0}}@media (min-width:768px){.row-centered{display:flex;align-items:center}}.row-bordered{position:relative}.row-bordered:before{content:'';display:block;width:80%;position:absolute;bottom:0;left:50%;margin-left:-40%;height:1px;background:radial-gradient(ellipse at center,rgba(0,0,0,.2) 0,rgba(255,255,255,0) 75%)}.hero{position:relative;text-align:center;padding:80px 0;border-bottom:1px solid #dcdfe4}.hero-booticon{font-family:Helvetica Neue,Helvetica,Arial,sans-serif;margin:0 auto 30px;width:100%;font-size:8vw;display:block;font-weight:500;text-align:center;cursor:default}.hero-homepage.hero{padding-top:0;padding-bottom:40px;overflow:hidden;border-bottom:0;border-bottom:1px solid #dcdfe4}.hero-homepage>.btn{margin-top:20px}.swag-line:before{content:'';position:fixed;display:block;top:0;left:0;right:0;height:5px;z-index:2;background-color:#26a65b;background:linear-gradient(45deg,#28a142,#26a65b)}.navbar{background-color:#fff;border:0 #fff}.navbar-header{text-align:center}.navbar-brand{height:auto;padding:19px 25px;font-size:16px;display:inline-block;float:none;text-align:center;margin:5px 0 0}.navbar-nav{margin-right:-15px}.navbar-nav>li>a{font-size:14px}.navbar-default .navbar-brand,.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover,.navbar-default .navbar-nav>li>a,.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{background:0 0;color:#293a46;font-weight:300}.navbar-default .navbar-toggle{position:absolute;left:0;top:7px;border-color:#fff;color:#293a46;margin-right:0}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background:#f9f9f9;border-color:#f9f9f9}@media (min-width:768px){.navbar-full .navbar-brand{margin-left:-25px}.navbar-tall{height:125px}.navbar-tall .navbar-header,.navbar-tall .navbar-nav{line-height:125px;text-align:left}.navbar-brand{float:none;display:inline-block;text-align:left;margin:0}.navbar-nav>li>a{display:inline-block;margin-left:13px}.navbar-nav>li:first-child>a{margin-left:0}}.screenshot{display:block;overflow:hidden}.screenshot>img{width:100%}.screenshots-fan{margin-top:50px}.screenshots-fan .screenshot{position:relative;width:auto;display:inline-block;text-align:center}.screenshots-fan .screenshot:first-child,.screenshots-fan .screenshot:last-child{z-index:2}.screenshots-fan .screenshot{z-index:3}@media (min-width:768px){.screenshots-fan{position:relative;overflow:hidden;margin-top:60px;height:200px}.screenshots-fan .screenshot{height:auto;top:10px;width:350px}.screenshots-fan .screenshot:first-child,.screenshots-fan .screenshot:last-child{width:250px;position:absolute;top:65px}.screenshots-fan .screenshot:first-child{left:10px}.screenshots-fan .screenshot:last-child{left:auto;right:10px}}@media (min-width:992px){.screenshots-fan{margin-top:60px;height:240px}.screenshots-fan .screenshot{width:400px}.screenshots-fan .screenshot:first-child,.screenshots-fan .screenshot:last-child{width:300px}}@media (min-width:1200px){.screenshots-fan{margin-top:80px;height:380px}.screenshots-fan .screenshot{width:550px}.screenshots-fan .screenshot:first-child,.screenshots-fan .screenshot:last-child{width:450px}}body{font-size:16px;font-family:Roboto,sans-serif;font-weight:300;line-height:1.6}h1{font-size:26px;font-weight:300}h2{font-size:18px;font-weight:300}h3{font-size:26px;font-weight:300}h4{font-size:16px;font-weight:300}h5{font-size:16px;font-weight:400}h1,h2,h3,h4,h5{line-height:1.4}h1,h2{margin:10px 0}h5{margin:6px 0}@media (min-width:768px){body{font-size:16px;font-family:Roboto,sans-serif;font-weight:300;line-height:1.6}h1{font-size:38px;font-weight:300}h2{font-size:26px;font-weight:300;line-height:1.4}h3{font-size:26px;font-weight:300}h4{font-size:18px;font-weight:300}h5{font-size:16px;font-weight:400}}body{color:#293a46}a{text-decoration:none;color:inherit}a:focus,a:hover{text-decoration:underline}.nav li a{text-decoration:none;color:inherit}.nav li a:hover{text-decoration:underline}.text-muted{color:#697176}.template-index h3{font-size:21px;margin-bottom:12px}.template-index h4{color:#697176;line-height:1.6}.template-index h4 a,.template-index p a{color:#26a65b}.template-index h5{font-size:17px;margin-bottom:8px}.homepage-code-example,.homepage-terminal-example{position:relative;font-family:monospace;background:#272b38;color:#48d8a0;border-radius:8px;padding:30px}.homepage-code-example .text-muted,.homepage-terminal-example .text-muted{color:#6a7490}@media (min-width:768px){.homepage-terminal-example{padding:50px}.homepage-code-example{padding:10px}.homepage-code-example>p{margin:0}}.hero-green{color:#26a65b}.hero-black{color:#353535}.hero-red{color:#cb2c37}.svg-icon-large{width:50px;display:block;margin:0 auto}.svg-icon-large>svg{width:100%;height:auto}.row-padded-small{padding:40px 0}.unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.url-diff-container{width:980px}.diff-url-wrapper{display:flex;width:100%}.diff-url-input{display:inline-block;margin-right:10px;flex-grow:1;height:31px}.diff-url-btn{display:inline-block;float:right;width:48px}.options-label-value{font-weight:400}.diff-url-options-container label input,.diff-url-options-container label select{display:block}.col-md- .col-md-15{width:20%} +\ No newline at end of file +diff --git a/docs/robots.txt b/docs/robots.txt +deleted file mode 100644 +index 4f9540ba..00000000 +--- a/docs/robots.txt ++++ /dev/null +@@ -1 +0,0 @@ +-User-agent: * +\ No newline at end of file +diff --git a/docs/sitemap.xml b/docs/sitemap.xml +deleted file mode 100644 +index 3f5fd623..00000000 +--- a/docs/sitemap.xml ++++ /dev/null +@@ -1,16 +0,0 @@ +- +- +- +- https://diff2html.xyz/ +- +- +- https://diff2html.xyz/index.html +- +- +- https://diff2html.xyz/demo.html +- +- +diff --git a/jest.config.js b/jest.config.js +new file mode 100644 +index 00000000..d3117139 +--- /dev/null ++++ b/jest.config.js +@@ -0,0 +1,15 @@ ++module.exports = { ++ verbose: true, ++ preset: "ts-jest", ++ testEnvironment: "node", ++ coverageDirectory: "./coverage", ++ coverageReporters: ["lcov", "text", "html"], ++ coverageThreshold: { ++ global: { ++ statements: 90, ++ branches: 85, ++ functions: 90, ++ lines: 90 ++ } ++ } ++}; +diff --git a/package.json b/package.json +index e7cb7710..cecef26c 100644 +--- a/package.json ++++ b/package.json +@@ -32,56 +32,101 @@ + "url": "https://www.github.com/rtfpessoa/diff2html/issues" + }, + "engines": { +- "node": ">=4" ++ "node": "8.* || >=10" + }, +- "preferGlobal": true, + "scripts": { +- "release": "./scripts/release.sh", +- "release-website": "./scripts/release-website.sh", +- "templates": "./scripts/hulk.js --wrapper node --variable 'browserTemplates' ./src/templates/*.mustache > ./src/templates/diff2html-templates.js", ++ "lint": "eslint '*/**/*.{js,jsx,ts,tsx}'", + "style": "yarn run lint", +- "lint": "eslint .", +- "coverage": "istanbul cover _mocha -- -u exports -R spec ./test/**/*", +- "check-coverage": "istanbul check-coverage --statements 90 --functions 90 --branches 85 --lines 90 ./coverage/coverage.json", +- "test": "yarn run coverage && yarn run check-coverage", ++ "test": "yarn run build-templates && jest", ++ "coverage": "jest --collectCoverage", ++ "coverage-html": "yarn run coverage && open ./coverage/index.html", + "codacy": "cat ./coverage/lcov.info | codacy-coverage", +- "preversion": "yarn run release && yarn run release-website && yarn run lint && yarn test", +- "version": "git add -A src dist docs package.json", ++ "build": "yarn run build-css && yarn run build-templates && yarn run build-es5 && yarn run build-esm && yarn run build-bundles && yarn run build-website", ++ "build-es5": "rm -rf lib; tsc -p tsconfig.json --outDir lib", ++ "build-esm": "rm -rf lib-esm; tsc -p tsconfig.json -m es6 --outDir lib-esm", ++ "build-bundles": "rm -rf ./bundles/js; NODE_ENV=production WEBPACK_MINIMIZE=true webpack --mode production --config webpack.bundles.ts", ++ "build-css": "rm -rf ./bundles/css; postcss --use autoprefixer postcss-import postcss-preset-env cssnano -o ./bundles/css/diff2html.min.css ./src/ui/css/diff2html.css", ++ "build-templates": "ts-node ./scripts/hulk.ts --wrapper ts --variable 'defaultTemplates' ./src/templates/*.mustache > ./src/diff2html-templates.ts", ++ "build-website": "rm -rf docs; NODE_ENV=production WEBPACK_MINIMIZE=true webpack --mode production --config webpack.website.ts", ++ "start-website": "WEBPACK_MINIFY=false NODE_ENV=dev webpack-dev-server --mode dev --config webpack.website.ts", ++ "preversion": "yarn run build && yarn run lint && yarn test", ++ "version": "git add -A package.json", + "postversion": "git push && git push --tags" + }, +- "main": "./src/diff2html.js", +- "browser": { +- "fs": false +- }, ++ "main": "./lib/diff2html.js", + "dependencies": { +- "diff": "^4.0.1", +- "hogan.js": "^3.0.2", +- "merge": "^1.2.1", +- "whatwg-fetch": "^3.0.0" ++ "diff": "4.0.1", ++ "hogan.js": "3.0.2" ++ }, ++ "optionalDependencies": { ++ "highlight.js": "9.16.2" + }, + "devDependencies": { +- "autoprefixer": "^9.6.0", +- "browserify": "^16.2.3", +- "clean-css-cli": "^4.3.0", +- "codacy-coverage": "^3.4.0", +- "eslint": "^5.16.0", +- "eslint-plugin-promise": "^4.1.1", +- "eslint-plugin-standard": "^4.0.0", +- "fast-html-parser": "^1.0.1", +- "istanbul": "^0.4.5", +- "mkdirp": "^0.5.1", +- "mocha": "5.2.0", +- "nopt": "^4.0.1", +- "postcss-cli": "^6.1.2", +- "uglify-js": "^3.6.0" ++ "@types/autoprefixer": "9.6.1", ++ "@types/clipboard": "2.0.1", ++ "@types/copy-webpack-plugin": "5.0.0", ++ "@types/diff": "4.0.2", ++ "@types/highlight.js": "9.12.3", ++ "@types/hogan.js": "3.0.0", ++ "@types/html-webpack-plugin": "3.2.1", ++ "@types/jest": "24.0.23", ++ "@types/mini-css-extract-plugin": "0.8.0", ++ "@types/mkdirp": "0.5.2", ++ "@types/node": "12.12.12", ++ "@types/nopt": "3.0.29", ++ "@types/webpack": "4.41.0", ++ "@typescript-eslint/eslint-plugin": "2.8.0", ++ "@typescript-eslint/parser": "2.8.0", ++ "autoprefixer": "9.7.2", ++ "bootstrap": "3.4.1", ++ "clipboard": "2.0.4", ++ "codacy-coverage": "3.4.0", ++ "copy-webpack-plugin": "5.0.5", ++ "css-loader": "3.2.0", ++ "cssnano": "4.1.10", ++ "eslint": "6.7.0", ++ "eslint-config-prettier": "6.7.0", ++ "eslint-config-standard": "14.1.0", ++ "eslint-plugin-import": "2.18.2", ++ "eslint-plugin-jest": "23.0.4", ++ "eslint-plugin-node": "10.0.0", ++ "eslint-plugin-prettier": "3.1.1", ++ "eslint-plugin-promise": "4.2.1", ++ "eslint-plugin-standard": "4.0.1", ++ "fast-html-parser": "1.0.1", ++ "file-loader": "4.3.0", ++ "handlebars": "4.5.3", ++ "handlebars-loader": "1.7.1", ++ "html-webpack-plugin": "3.2.0", ++ "image-webpack-loader": "6.0.0", ++ "jest": "24.9.0", ++ "mini-css-extract-plugin": "0.8.0", ++ "mkdirp": "0.5.1", ++ "nopt": "4.0.1", ++ "postcss-cli": "6.1.3", ++ "postcss-import": "12.0.1", ++ "postcss-loader": "3.0.0", ++ "postcss-normalize": "8.0.1", ++ "postcss-preset-env": "6.7.0", ++ "prettier": "1.19.1", ++ "style-loader": "1.0.0", ++ "ts-jest": "24.2.0", ++ "ts-loader": "6.2.1", ++ "ts-node": "8.5.2", ++ "typescript": "3.7.2", ++ "url-loader": "2.3.0", ++ "webpack": "4.41.2", ++ "webpack-cli": "3.3.10", ++ "webpack-dev-server": "3.9.0", ++ "whatwg-fetch": "3.0.0" + }, + "resolutions": { +- "lodash": "4.17.14" ++ "lodash": "4.17.15" + }, + "license": "MIT", + "files": [ +- "src", +- "dist", +- "typescript" ++ "bundles", ++ "lib", ++ "lib-esm" + ] + } +diff --git a/scripts/hulk.js b/scripts/hulk.js +deleted file mode 100755 +index a4b1a4d5..00000000 +--- a/scripts/hulk.js ++++ /dev/null +@@ -1,193 +0,0 @@ +-#!/usr/bin/env node +- +-/* +- * Copyright 2011 Twitter, Inc. +- * Licensed under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. +- * You may obtain a copy of the License at +- * +- * http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software +- * distributed under the License is distributed on an "AS IS" BASIS, +- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- * See the License for the specific language governing permissions and +- * limitations under the License. +- */ +- +-// dependencies +-var hogan = require('hogan.js'); +-var path = require('path'); +-var nopt = require('nopt'); +-var mkderp = require('mkdirp'); +-var fs = require('fs'); +- +-// locals +-var specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\']; +-var specialsRegExp = new RegExp('(\\' + specials.join('|\\') + ')', 'g'); +-var options = { +- 'namespace': String, +- 'outputdir': path, +- 'variable': String, +- 'wrapper': String, +- 'version': true, +- 'help': true +-}; +-var shortHand = { +- 'n': ['--namespace'], +- 'o': ['--outputdir'], +- 'vn': ['--variable'], +- 'w': ['--wrapper'], +- 'h': ['--help'], +- 'v': ['--version'] +-}; +-var templates; +- +-// options +-options = nopt(options, shortHand); +- +-// escape special regexp characters +-function esc(text) { +- return text.replace(specialsRegExp, '\\$1'); +-} +- +-// cyan function for rob +-function cyan(text) { +- return '\x1B[36m' + text + '\x1B[39m'; +-} +- +-// check for dirs and correct ext (<3 for windows) +-function extractFiles(args) { +- var usage = '\n' + +- cyan('USAGE:') + ' hulk [--wrapper wrapper] [--outputdir outputdir] ' + +- '[--namespace namespace] [--variable variable] FILES\n\n' + +- cyan('OPTIONS:') + ' [-w, --wrapper] :: wraps the template (i.e. amd)\n' + +- ' [-o, --outputdir] :: outputs the templates as individual files to a directory\n\n' + +- ' [-n, --namespace] :: prepend string to template names\n\n' + +- ' [-vn, --variable] :: variable name for non-amd wrapper\n\n' + +- cyan('EXAMPLE:') + ' hulk --wrapper amd ./templates/*.mustache\n\n' + +- cyan('NOTE:') + ' hulk supports the "*" wildcard and allows you to target specific extensions too\n'; +- var files = []; +- +- if (options.version) { +- console.log(require('../package.json').version); +- process.exit(0); +- } +- +- if (!args.length || options.help) { +- console.log(usage); +- process.exit(0); +- } +- +- args.forEach(function(arg) { +- if (/\*/.test(arg)) { +- arg = arg.split('*'); +- files = files.concat( +- fs.readdirSync(arg[0] || '.') +- .map(function(f) { +- var file = path.join(arg[0], f); +- return new RegExp(esc(arg[1]) + '$').test(f) && fs.statSync(file).isFile() && file; +- }) +- .filter(function(f) { +- return f; +- }) +- ); +- return files; +- } +- +- if (fs.statSync(arg).isFile()) files.push(arg); +- }); +- +- return files; +-} +- +-// remove utf-8 byte order mark, http://en.wikipedia.org/wiki/Byte_order_mark +-function removeByteOrderMark(text) { +- if (text.charCodeAt(0) === 0xfeff) { +- return text.substring(1); +- } +- return text; +-} +- +-// wrap templates +-function wrap(file, name, openedFile) { +- switch (options.wrapper) { +- case 'amd': +- return 'define(' + (!options.outputdir ? '"' + path.join(path.dirname(file), name) + '", ' : '') + +- '[ "hogan.js" ], function(Hogan){ return new Hogan.Template(' + +- hogan.compile(openedFile, {asString: 1}) + +- ');});'; +- case 'node': +- var globalObj = 'global.' + (options.variable || 'templates') + '["' + name + '"]'; +- var globalStmt = globalObj + ' = new Hogan.Template(' + hogan.compile(openedFile, {asString: 1}) + ');'; +- var nodeOutput = globalStmt; +- +- // if we have a template per file the export will expose the template directly +- if (options.outputdir) { +- nodeOutput = nodeOutput + '\n' + 'module.exports = ' + globalObj + ';'; +- } +- +- return nodeOutput; +- default: +- return (options.variable || 'templates') + +- '["' + name + '"] = new Hogan.Template(' + +- hogan.compile(openedFile, {asString: 1}) + +- ');'; +- } +-} +- +-function prepareOutput(content) { +- var variableName = options.variable || 'templates'; +- switch (options.wrapper) { +- case 'amd': +- return content; +- case 'node': +- var nodeExport = ''; +- +- // if we have aggregated templates the export will expose the template map +- if (!options.outputdir) { +- nodeExport = 'module.exports = global.' + variableName + ';\n'; +- } +- +- return '(function() {\n' + +- 'if (!!!global.' + variableName + ') global.' + variableName + ' = {};\n' + +- 'var Hogan = require("hogan.js");' + +- content + '\n' + +- nodeExport + +- '})();'; +- default: +- return 'if (!!!' + variableName + ') var ' + variableName + ' = {};\n' + content; +- } +-} +- +-// write the directory +-if (options.outputdir) { +- mkderp.sync(options.outputdir); +-} +- +-// Prepend namespace to template name +-function namespace(name) { +- return (options.namespace || '') + name; +-} +- +-// write a template foreach file that matches template extension +-templates = extractFiles(options.argv.remain) +- .map(function(file) { +- var openedFile = fs.readFileSync(file, 'utf-8').trim(); +- var name; +- if (!openedFile) return; +- name = namespace(path.basename(file).replace(/\..*$/, '')); +- openedFile = removeByteOrderMark(openedFile); +- openedFile = wrap(file, name, openedFile); +- if (!options.outputdir) return openedFile; +- fs.writeFileSync(path.join(options.outputdir, name + '.js') +- , prepareOutput(openedFile)); +- }) +- .filter(function(t) { +- return t; +- }); +- +-// output templates +-if (!templates.length || options.outputdir) process.exit(0); +- +-console.log(prepareOutput(templates.join('\n'))); +diff --git a/scripts/hulk.ts b/scripts/hulk.ts +new file mode 100755 +index 00000000..f3e4c4ac +--- /dev/null ++++ b/scripts/hulk.ts +@@ -0,0 +1,193 @@ ++#!/usr/bin/env node ++ ++/* ++ * Copyright 2011 Twitter, Inc. ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++import * as path from "path"; ++import * as fs from "fs"; ++ ++import * as hogan from "hogan.js"; ++import nopt from "nopt"; ++import * as mkderp from "mkdirp"; ++ ++const options = nopt( ++ { ++ namespace: String, ++ outputdir: path, ++ variable: String, ++ wrapper: String, ++ version: true, ++ help: true ++ }, ++ { ++ n: ["--namespace"], ++ o: ["--outputdir"], ++ vn: ["--variable"], ++ w: ["--wrapper"], ++ h: ["--help"], ++ v: ["--version"] ++ } ++); ++ ++const specials = ["/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\"]; ++const specialsRegExp = new RegExp("(\\" + specials.join("|\\") + ")", "g"); ++function escape(text: string): string { ++ return text.replace(specialsRegExp, "\\$1"); ++} ++ ++function cyan(text: string): string { ++ return "\x1B[36m" + text + "\x1B[39m"; ++} ++ ++function extractFiles(files: string[]): string[] { ++ const usage = `${cyan( ++ "USAGE:" ++ )} hulk [--wrapper wrapper] [--outputdir outputdir] [--namespace namespace] [--variable variable] FILES ++ ++ ${cyan("OPTIONS:")} [-w, --wrapper] :: wraps the template (i.e. amd) ++ [-o, --outputdir] :: outputs the templates as individual files to a directory ++ ++ [-n, --namespace] :: prepend string to template names ++ ++ [-vn, --variable] :: variable name for non-amd wrapper ++ ++ ${cyan("EXAMPLE:")} hulk --wrapper amd ./templates/*.mustache ++ ++ ${cyan("NOTE:")} hulk supports the "*" wildcard and allows you to target specific extensions too ++ `; ++ ++ if (options.version) { ++ console.log(require("../package.json").version); ++ process.exit(0); ++ } ++ ++ if (!files.length || options.help) { ++ console.log(usage); ++ process.exit(0); ++ } ++ ++ const templateFiles = files ++ .map((fileGlob: string) => { ++ if (/\*/.test(fileGlob)) { ++ const [fileGlobPrefix, fileGlobSuffix] = fileGlob.split("*"); ++ ++ const files = fs.readdirSync(fileGlobPrefix || ".").reduce((previousFiles, relativeFilePath) => { ++ const file = path.join(fileGlobPrefix, relativeFilePath); ++ if (new RegExp(`${escape(fileGlobSuffix)}$`).test(relativeFilePath) && fs.statSync(file).isFile()) { ++ previousFiles.push(file); ++ } ++ return previousFiles; ++ }, []); ++ ++ return files; ++ } else if (fs.statSync(fileGlob).isFile()) { ++ return [fileGlob]; ++ } else { ++ return []; ++ } ++ }) ++ .reduce((previous, current) => previous.concat(current), []); ++ ++ return templateFiles; ++} ++ ++// Remove utf-8 byte order mark, http://en.wikipedia.org/wiki/Byte_order_mark ++function removeByteOrderMark(text: string): string { ++ if (text.charCodeAt(0) === 0xfeff) { ++ return text.substring(1); ++ } ++ return text; ++} ++ ++// Wrap templates ++function wrap(file: string, name: string, openedFile: string): string { ++ const hoganTemplateString = `new Hogan.Template(${hogan.compile(openedFile, { asString: true })})`; ++ ++ const objectName = options.variable || "templates"; ++ const objectAccessor = `${objectName}["${name}"]`; ++ const objectStmt = `${objectAccessor} = ${hoganTemplateString};`; ++ ++ switch (options.wrapper) { ++ case "amd": ++ return `define(${ ++ !options.outputdir ? `"${path.join(path.dirname(file), name)}", ` : "" ++ }["hogan.js"], function(Hogan) { return ${hoganTemplateString}; });`; ++ ++ case "node": ++ // If we have a template per file the export will expose the template directly ++ return options.outputdir ? `global.${objectStmt};\nmodule.exports = ${objectAccessor};` : `global.${objectStmt}`; ++ ++ case "ts": ++ return `// @ts-ignore\n${objectStmt}`; ++ default: ++ return objectStmt; ++ } ++} ++ ++function prepareOutput(content: string): string { ++ const variableName = options.variable || "templates"; ++ switch (options.wrapper) { ++ case "amd": ++ return content; ++ case "node": ++ return `(function() { ++if (!!!global.${variableName}) global.${variableName} = {}; ++var Hogan = require("hogan.js"); ++${content} ++${!options.outputdir ? `module.exports = global.${variableName};\n` : ""})();`; ++ ++ case "ts": ++ return `import * as Hogan from "hogan.js"; ++type CompiledTemplates = { [name: string]: Hogan.Template }; ++export const ${variableName}: CompiledTemplates = {}; ++${content}`; ++ ++ default: ++ return "if (!!!" + variableName + ") var " + variableName + " = {};\n" + content; ++ } ++} ++ ++// Write the directory ++if (options.outputdir) { ++ mkderp.sync(options.outputdir); ++} ++ ++// Prepend namespace to template name ++function namespace(name: string): string { ++ return (options.namespace || "") + name; ++} ++ ++// Write a template foreach file that matches template extension ++const templates = extractFiles(options.argv.remain) ++ .map(file => { ++ const timmedFileContents = fs.readFileSync(file, "utf8").trim(); ++ ++ if (!timmedFileContents) return; ++ ++ const name = namespace(path.basename(file).replace(/\..*$/, "")); ++ const cleanFileContents = wrap(file, name, removeByteOrderMark(timmedFileContents)); ++ ++ if (!options.outputdir) return cleanFileContents; ++ ++ const fileExtension = options.wrapper === "ts" ? "ts" : "js"; ++ ++ return fs.writeFileSync(path.join(options.outputdir, `${name}.${fileExtension}`), prepareOutput(cleanFileContents)); ++ }) ++ .filter(templateContents => typeof templateContents !== "undefined"); ++ ++// Output templates ++if (!templates.length || options.outputdir) process.exit(0); ++ ++console.log(prepareOutput(templates.join("\n"))); +diff --git a/scripts/release-website.js b/scripts/release-website.js +deleted file mode 100644 +index 5e511320..00000000 +--- a/scripts/release-website.js ++++ /dev/null +@@ -1,69 +0,0 @@ +-var fs = require('fs'); +- +-var hogan = require('hogan.js'); +- +-var root = 'website/templates'; +-var pagesRoot = root + '/pages'; +- +-var websitePages = fs.readdirSync(root + '/pages'); +- +-var template = hogan.compile(readFile(root + '/template.mustache')); +- +-var options = { +- 'all': { +- 'demoUrl': 'demo.html?diff=https://github.com/rtfpessoa/diff2html/pull/106' +- }, +- 'demo': { +- 'extraClass': 'template-index-min' +- } +-}; +- +-websitePages.map(function(page) { +- var pagePartialTemplate = hogan.compile(readFile(pagesRoot + '/' + page + '/' + page + '.partial.mustache')); +- var pageAssetsTemplate = hogan.compile(readFile(pagesRoot + '/' + page + '/' + page + '-assets.partial.mustache')); +- var pageScriptsTemplate = hogan.compile(readFile(pagesRoot + '/' + page + '/' + page + '-scripts.partial.mustache')); +- +- var templateOptions = {}; +- +- var key; +- +- // Allow the pages to share common options +- var genericOptions = options['all'] || {}; +- for (key in genericOptions) { +- if (genericOptions.hasOwnProperty(key)) { +- templateOptions[key] = genericOptions[key]; +- } +- } +- +- // Allow each page to have custom options +- var pageOptions = options[page] || {}; +- for (key in pageOptions) { +- if (pageOptions.hasOwnProperty(key)) { +- templateOptions[key] = pageOptions[key]; +- } +- } +- +- var pagePartial = pagePartialTemplate.render(templateOptions); +- var pageAssets = pageAssetsTemplate.render(templateOptions); +- var pageScripts = pageScriptsTemplate.render(templateOptions); +- +- templateOptions.assets = pageAssets; +- templateOptions.scripts = pageScripts; +- templateOptions.content = pagePartial; +- +- var pageHtml = template.render(templateOptions); +- writeFile('docs/' + page + '.html', pageHtml); +-}); +- +-function readFile(filePath) { +- try { +- return fs.readFileSync(filePath, 'utf8'); +- } catch (_ignore) { +- } +- +- return ''; +-} +- +-function writeFile(filePath, content) { +- return fs.writeFileSync(filePath, content); +-} +diff --git a/scripts/release-website.sh b/scripts/release-website.sh +deleted file mode 100755 +index 841732ad..00000000 +--- a/scripts/release-website.sh ++++ /dev/null +@@ -1,49 +0,0 @@ +-#!/bin/bash +- +-# +-# diff2html website release script +-# by rtfpessoa +-# +- +-set -e +- +-INPUT_DIR=website +-INPUT_DEMO_JS=${INPUT_DIR}/templates/pages/demo/demo.js +-INPUT_CSS_FILE=${INPUT_DIR}/main.css +- +-OUTPUT_DIR=docs +-OUTPUT_DEMO_JS=${OUTPUT_DIR}/demo.js +-OUTPUT_DEMO_MIN_JS=${OUTPUT_DIR}/demo.min.js +-OUTPUT_CSS_FILE=${OUTPUT_DIR}/main.css +-OUTPUT_MIN_CSS_FILE=${OUTPUT_DIR}/main.min.css +- +-echo "Creating diff2html website release ..." +- +-echo "Cleaning previous versions ..." +-rm -rf ${OUTPUT_DIR} +-mkdir -p ${OUTPUT_DIR} +- +-echo "Minifying ${OUTPUT_CSS_FILE} to ${OUTPUT_MIN_CSS_FILE}" +-postcss --use autoprefixer -o ${OUTPUT_CSS_FILE} ${INPUT_CSS_FILE} +-cleancss --advanced --compatibility=ie8 -o ${OUTPUT_MIN_CSS_FILE} ${OUTPUT_CSS_FILE} +- +-echo "Generating website js aggregation file in ${OUTPUT_DEMO_JS}" +-browserify -e ${INPUT_DEMO_JS} -o ${OUTPUT_DEMO_JS} +- +-echo "Minifying ${OUTPUT_DEMO_JS} to ${OUTPUT_DEMO_MIN_JS}" +-uglifyjs ${OUTPUT_DEMO_JS} -c -o ${OUTPUT_DEMO_MIN_JS} +- +-echo "Generating HTMLs from templates ..." +-node ./scripts/release-website.js +- +-echo "Copying static files ..." +-cp -rf ${INPUT_DIR}/img ${OUTPUT_DIR}/ +-cp -f ${INPUT_DIR}/CNAME ${OUTPUT_DIR}/ +-cp -f ${INPUT_DIR}/favicon.ico ${OUTPUT_DIR}/ +-cp -f ${INPUT_DIR}/robots.txt ${OUTPUT_DIR}/ +-cp -f ${INPUT_DIR}/sitemap.xml ${OUTPUT_DIR}/ +- +-echo "Creating diff2html assets symlink ..." +-ln -s ../dist docs/assets +- +-echo "diff2html website release created successfully!" +diff --git a/scripts/release.sh b/scripts/release.sh +deleted file mode 100755 +index 0d891fb8..00000000 +--- a/scripts/release.sh ++++ /dev/null +@@ -1,57 +0,0 @@ +-#!/bin/bash +- +-# +-# diff2html release script +-# by rtfpessoa +-# +- +-set -e +- +-INPUT_DIR=src +-INTPUT_TEMPLATES_DIR=${INPUT_DIR}/templates +-INPUT_UI_DIR=${INPUT_DIR}/ui +-INPUT_JS_FILE=${INPUT_DIR}/diff2html.js +-INPUT_JS_UI_FILE=${INPUT_UI_DIR}/js/diff2html-ui.js +-INPUT_CSS_FILE=${INPUT_UI_DIR}/css/diff2html.css +-INPUT_TYPINGS_D_TS_FILE=${INPUT_DIR}/diff2html.d.ts +- +-GENERATED_TEMPLATES_FILE=${INTPUT_TEMPLATES_DIR}/diff2html-templates.js +- +-OUTPUT_DIR=dist +-OUTPUT_JS_FILE=${OUTPUT_DIR}/diff2html.js +-OUTPUT_MIN_JS_FILE=${OUTPUT_DIR}/diff2html.min.js +-OUTPUT_JS_UI_FILE=${OUTPUT_DIR}/diff2html-ui.js +-OUTPUT_MIN_JS_UI_FILE=${OUTPUT_DIR}/diff2html-ui.min.js +-OUTPUT_CSS_FILE=${OUTPUT_DIR}/diff2html.css +-OUTPUT_MIN_CSS_FILE=${OUTPUT_DIR}/diff2html.min.css +-OUTPUT_TYPINGS_D_TS_FILE=${OUTPUT_DIR}/diff2html.d.ts +- +-echo "Creating diff2html release ..." +- +-echo "Cleaning previous versions ..." +-rm -rf ${OUTPUT_DIR} +-mkdir -p ${OUTPUT_DIR} +- +-echo "Minifying ${OUTPUT_CSS_FILE} to ${OUTPUT_MIN_CSS_FILE}" +-postcss --use autoprefixer -o ${OUTPUT_CSS_FILE} ${INPUT_CSS_FILE} +-cleancss --advanced --compatibility=ie8 -o ${OUTPUT_MIN_CSS_FILE} ${OUTPUT_CSS_FILE} +- +-echo "Pre-compile hogan.js templates" +-yarn run templates +- +-echo "Generating js aggregation file in ${OUTPUT_JS_FILE}" +-browserify -e ${INPUT_JS_FILE} -o ${OUTPUT_JS_FILE} +- +-echo "Minifying ${OUTPUT_JS_FILE} to ${OUTPUT_MIN_JS_FILE}" +-uglifyjs ${OUTPUT_JS_FILE} -c -o ${OUTPUT_MIN_JS_FILE} +- +-echo "Generating js ui aggregation file in ${OUTPUT_JS_UI_FILE}" +-browserify -e ${INPUT_JS_UI_FILE} -o ${OUTPUT_JS_UI_FILE} +- +-echo "Minifying ${OUTPUT_JS_UI_FILE} to ${OUTPUT_MIN_JS_UI_FILE}" +-uglifyjs ${OUTPUT_JS_UI_FILE} -c -o ${OUTPUT_MIN_JS_UI_FILE} +- +-echo "Copying types ${INPUT_TYPINGS_D_TS_FILE} to ${OUTPUT_TYPINGS_D_TS_FILE}" +-cp -f ${INPUT_TYPINGS_D_TS_FILE} ${OUTPUT_TYPINGS_D_TS_FILE} +- +-echo "diff2html release created successfully!" +diff --git a/src/__tests__/diff-parser-tests.ts b/src/__tests__/diff-parser-tests.ts +new file mode 100644 +index 00000000..594a8976 +--- /dev/null ++++ b/src/__tests__/diff-parser-tests.ts +@@ -0,0 +1,732 @@ ++import { parse } from "../diff-parser"; ++ ++function checkDiffSample(diff: string): void { ++ const result = parse(diff); ++ const file1 = result[0]; ++ expect(result.length).toEqual(1); ++ expect(file1.addedLines).toEqual(1); ++ expect(file1.deletedLines).toEqual(1); ++ expect(file1.oldName).toEqual("sample"); ++ expect(file1.newName).toEqual("sample"); ++ expect(file1.blocks.length).toEqual(1); ++} ++ ++describe("DiffParser", () => { ++ describe("generateDiffJson", () => { ++ // eslint-disable-next-line jest/expect-expect ++ it("should parse unix with \n diff", () => { ++ const diff = ++ "diff --git a/sample b/sample\n" + ++ "index 0000001..0ddf2ba\n" + ++ "--- a/sample\n" + ++ "+++ b/sample\n" + ++ "@@ -1 +1 @@\n" + ++ "-test\n" + ++ "+test1r\n"; ++ checkDiffSample(diff); ++ }); ++ ++ // eslint-disable-next-line jest/expect-expect ++ it("should parse windows with \r\n diff", () => { ++ const diff = ++ "diff --git a/sample b/sample\r\n" + ++ "index 0000001..0ddf2ba\r\n" + ++ "--- a/sample\r\n" + ++ "+++ b/sample\r\n" + ++ "@@ -1 +1 @@\r\n" + ++ "-test\r\n" + ++ "+test1r\r\n"; ++ checkDiffSample(diff); ++ }); ++ ++ // eslint-disable-next-line jest/expect-expect ++ it("should parse old os x with \r diff", () => { ++ const diff = ++ "diff --git a/sample b/sample\r" + ++ "index 0000001..0ddf2ba\r" + ++ "--- a/sample\r" + ++ "+++ b/sample\r" + ++ "@@ -1 +1 @@\r" + ++ "-test\r" + ++ "+test1r\r"; ++ checkDiffSample(diff); ++ }); ++ ++ // eslint-disable-next-line jest/expect-expect ++ it("should parse mixed eols diff", () => { ++ const diff = ++ "diff --git a/sample b/sample\n" + ++ "index 0000001..0ddf2ba\r\n" + ++ "--- a/sample\r" + ++ "+++ b/sample\r\n" + ++ "@@ -1 +1 @@\n" + ++ "-test\r" + ++ "+test1r\n"; ++ checkDiffSample(diff); ++ }); ++ ++ it("should parse diff with special characters", () => { ++ const diff = ++ 'diff --git "a/bla with \ttab.scala" "b/bla with \ttab.scala"\n' + ++ "index 4c679d7..e9bd385 100644\n" + ++ '--- "a/bla with \ttab.scala"\n' + ++ '+++ "b/bla with \ttab.scala"\n' + ++ "@@ -1 +1,2 @@\n" + ++ "-cenas\n" + ++ "+cenas com ananas\n" + ++ "+bananas"; ++ ++ const result = parse(diff); ++ const file1 = result[0]; ++ expect(result.length).toEqual(1); ++ expect(file1.addedLines).toEqual(2); ++ expect(file1.deletedLines).toEqual(1); ++ expect(file1.oldName).toEqual("bla with \ttab.scala"); ++ expect(file1.newName).toEqual("bla with \ttab.scala"); ++ expect(file1.blocks.length).toEqual(1); ++ }); ++ ++ it("should parse diff with prefix", () => { ++ const diff = ++ 'diff --git "\tbla with \ttab.scala" "\tbla with \ttab.scala"\n' + ++ "index 4c679d7..e9bd385 100644\n" + ++ '--- "\tbla with \ttab.scala"\n' + ++ '+++ "\tbla with \ttab.scala"\n' + ++ "@@ -1 +1,2 @@\n" + ++ "-cenas\n" + ++ "+cenas com ananas\n" + ++ "+bananas"; ++ ++ const result = parse(diff, { srcPrefix: "\t", dstPrefix: "\t" }); ++ const file1 = result[0]; ++ expect(result.length).toEqual(1); ++ expect(file1.addedLines).toEqual(2); ++ expect(file1.deletedLines).toEqual(1); ++ expect(file1.oldName).toEqual("bla with \ttab.scala"); ++ expect(file1.newName).toEqual("bla with \ttab.scala"); ++ expect(file1.blocks.length).toEqual(1); ++ }); ++ ++ it("should parse diff with deleted file", () => { ++ const diff = ++ "diff --git a/src/var/strundefined.js b/src/var/strundefined.js\n" + ++ "deleted file mode 100644\n" + ++ "index 04e16b0..0000000\n" + ++ "--- a/src/var/strundefined.js\n" + ++ "+++ /dev/null\n" + ++ "@@ -1,3 +0,0 @@\n" + ++ "-define(() => {\n" + ++ "- return typeof undefined;\n" + ++ "-});\n"; ++ ++ const result = parse(diff); ++ expect(result.length).toEqual(1); ++ ++ const file1 = result[0]; ++ expect(file1.isCombined).toEqual(false); ++ expect(file1.addedLines).toEqual(0); ++ expect(file1.deletedLines).toEqual(3); ++ expect(file1.oldName).toEqual("src/var/strundefined.js"); ++ expect(file1.newName).toEqual("/dev/null"); ++ expect(file1.blocks.length).toEqual(1); ++ expect(file1.isDeleted).toEqual(true); ++ expect(file1.checksumBefore).toEqual("04e16b0"); ++ expect(file1.checksumAfter).toEqual("0000000"); ++ }); ++ ++ it("should parse diff with new file", () => { ++ const diff = ++ "diff --git a/test.js b/test.js\n" + ++ "new file mode 100644\n" + ++ "index 0000000..e1e22ec\n" + ++ "--- /dev/null\n" + ++ "+++ b/test.js\n" + ++ "@@ -0,0 +1,5 @@\n" + ++ "+var parser = require('./source/git-parser');\n" + ++ "+\n" + ++ "+var patchLineList = [ false, false, false, false ];\n" + ++ "+\n" + ++ "+console.log(parser.parsePatchDiffResult(text, patchLineList));\n"; ++ ++ const result = parse(diff); ++ expect(result.length).toEqual(1); ++ ++ const file1 = result[0]; ++ expect(file1.isCombined).toEqual(false); ++ expect(file1.addedLines).toEqual(5); ++ expect(file1.deletedLines).toEqual(0); ++ expect(file1.oldName).toEqual("/dev/null"); ++ expect(file1.newName).toEqual("test.js"); ++ expect(file1.blocks.length).toEqual(1); ++ expect(file1.isNew).toEqual(true); ++ expect(file1.newFileMode).toEqual("100644"); ++ expect(file1.checksumBefore).toEqual("0000000"); ++ expect(file1.checksumAfter).toEqual("e1e22ec"); ++ }); ++ ++ it("should parse diff with nested diff", () => { ++ const diff = ++ "diff --git a/src/offset.js b/src/offset.js\n" + ++ "index cc6ffb4..fa51f18 100644\n" + ++ "--- a/src/offset.js\n" + ++ "+++ b/src/offset.js\n" + ++ "@@ -1,6 +1,5 @@\n" + ++ "+var parser = require('./source/git-parser');\n" + ++ "+\n" + ++ "+var text = 'diff --git a/components/app/app.html b/components/app/app.html\\nindex ecb7a95..027bd9b 100644\\n--- a/components/app/app.html\\n+++ b/components/app/app.html\\n@@ -52,0 +53,3 @@\\n+\\n+\\n+\\n@@ -56,0 +60,3 @@\\n+\\n+\\n+\\n'\n" + ++ "+var patchLineList = [ false, false, false, false ];\n" + ++ "+\n" + ++ "+console.log(parser.parsePatchDiffResult(text, patchLineList));\n"; ++ ++ const result = parse(diff); ++ expect(result.length).toEqual(1); ++ ++ const file1 = result[0]; ++ expect(file1.isCombined).toEqual(false); ++ expect(file1.addedLines).toEqual(6); ++ expect(file1.deletedLines).toEqual(0); ++ expect(file1.oldName).toEqual("src/offset.js"); ++ expect(file1.newName).toEqual("src/offset.js"); ++ expect(file1.blocks.length).toEqual(1); ++ expect(file1.blocks[0].lines.length).toEqual(6); ++ expect(file1.checksumBefore).toEqual("cc6ffb4"); ++ expect(file1.checksumAfter).toEqual("fa51f18"); ++ }); ++ ++ it("should parse diff with multiple blocks", () => { ++ const diff = ++ "diff --git a/src/attributes/classes.js b/src/attributes/classes.js\n" + ++ "index c617824..c8d1393 100644\n" + ++ "--- a/src/attributes/classes.js\n" + ++ "+++ b/src/attributes/classes.js\n" + ++ "@@ -1,10 +1,9 @@\n" + ++ " define([\n" + ++ ' "../core",\n' + ++ ' "../var/rnotwhite",\n' + ++ '- "../var/strundefined",\n' + ++ ' "../data/var/dataPriv",\n' + ++ ' "../core/init"\n' + ++ "-], function( jQuery, rnotwhite, strundefined, dataPriv ) {\n" + ++ "+], function( jQuery, rnotwhite, dataPriv ) {\n" + ++ " \n" + ++ " var rclass = /[\\t\\r\\n\\f]/g;\n" + ++ " \n" + ++ "@@ -128,7 +127,7 @@ jQuery.fn.extend({\n" + ++ " }\n" + ++ " \n" + ++ " // Toggle whole class name\n" + ++ '- } else if ( type === strundefined || type === "boolean" ) {\n' + ++ '+ } else if ( value === undefined || type === "boolean" ) {\n' + ++ " if ( this.className ) {\n" + ++ " // store className if set\n" + ++ ' dataPriv.set( this, "__className__", this.className );\n'; ++ ++ const result = parse(diff); ++ expect(result.length).toEqual(1); ++ ++ const file1 = result[0]; ++ expect(file1.isCombined).toEqual(false); ++ expect(file1.addedLines).toEqual(2); ++ expect(file1.deletedLines).toEqual(3); ++ expect(file1.oldName).toEqual("src/attributes/classes.js"); ++ expect(file1.newName).toEqual("src/attributes/classes.js"); ++ expect(file1.blocks.length).toEqual(2); ++ expect(file1.blocks[0].lines.length).toEqual(11); ++ expect(file1.blocks[1].lines.length).toEqual(8); ++ expect(file1.checksumBefore).toEqual("c617824"); ++ expect(file1.checksumAfter).toEqual("c8d1393"); ++ }); ++ ++ it("should parse diff with multiple files", () => { ++ const diff = ++ "diff --git a/src/core/init.js b/src/core/init.js\n" + ++ "index e49196a..50f310c 100644\n" + ++ "--- a/src/core/init.js\n" + ++ "+++ b/src/core/init.js\n" + ++ "@@ -101,7 +101,7 @@ var rootjQuery,\n" + ++ " // HANDLE: $(function)\n" + ++ " // Shortcut for document ready\n" + ++ " } else if ( jQuery.isFunction( selector ) ) {\n" + ++ '- return typeof rootjQuery.ready !== "undefined" ?\n' + ++ "+ return rootjQuery.ready !== undefined ?\n" + ++ " rootjQuery.ready( selector ) :\n" + ++ " // Execute immediately if ready is not present\n" + ++ " selector( jQuery );\n" + ++ "diff --git a/src/event.js b/src/event.js\n" + ++ "index 7336f4d..6183f70 100644\n" + ++ "--- a/src/event.js\n" + ++ "+++ b/src/event.js\n" + ++ "@@ -1,6 +1,5 @@\n" + ++ " define([\n" + ++ ' "./core",\n' + ++ '- "./var/strundefined",\n' + ++ ' "./var/rnotwhite",\n' + ++ ' "./var/hasOwn",\n' + ++ ' "./var/slice",\n'; ++ ++ const result = parse(diff); ++ expect(result.length).toEqual(2); ++ ++ const file1 = result[0]; ++ expect(file1.isCombined).toEqual(false); ++ expect(file1.addedLines).toEqual(1); ++ expect(file1.deletedLines).toEqual(1); ++ expect(file1.oldName).toEqual("src/core/init.js"); ++ expect(file1.newName).toEqual("src/core/init.js"); ++ expect(file1.blocks.length).toEqual(1); ++ expect(file1.blocks[0].lines.length).toEqual(8); ++ expect(file1.checksumBefore).toEqual("e49196a"); ++ expect(file1.checksumAfter).toEqual("50f310c"); ++ ++ const file2 = result[1]; ++ expect(file2.isCombined).toEqual(false); ++ expect(file2.addedLines).toEqual(0); ++ expect(file2.deletedLines).toEqual(1); ++ expect(file2.oldName).toEqual("src/event.js"); ++ expect(file2.newName).toEqual("src/event.js"); ++ expect(file2.blocks.length).toEqual(1); ++ expect(file2.blocks[0].lines.length).toEqual(6); ++ expect(file2.checksumBefore).toEqual("7336f4d"); ++ expect(file2.checksumAfter).toEqual("6183f70"); ++ }); ++ ++ it("should parse combined diff", () => { ++ const diff = ++ "diff --combined describe.c\n" + ++ "index fabadb8,cc95eb0..4866510\n" + ++ "--- a/describe.c\n" + ++ "+++ b/describe.c\n" + ++ "@@@ -98,20 -98,12 +98,20 @@@\n" + ++ " return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;\n" + ++ " }\n" + ++ " \n" + ++ "- static void describe(char *arg)\n" + ++ " -static void describe(struct commit *cmit, int last_one)\n" + ++ "++static void describe(char *arg, int last_one)\n" + ++ " {\n" + ++ " + unsigned char sha1[20];\n" + ++ " + struct commit *cmit;\n" + ++ " struct commit_list *list;\n" + ++ " static int initialized = 0;\n" + ++ " struct commit_name *n;\n" + ++ " \n" + ++ " + if (get_sha1(arg, sha1) < 0)\n" + ++ " + usage(describe_usage);\n" + ++ " + cmit = lookup_commit_reference(sha1);\n" + ++ " + if (!cmit)\n" + ++ " + usage(describe_usage);\n" + ++ " +\n" + ++ " if (!initialized) {\n" + ++ " initialized = 1;\n" + ++ " for_each_ref(get_name);\n"; ++ ++ const result = parse(diff); ++ expect(result.length).toEqual(1); ++ ++ const file1 = result[0]; ++ expect(file1.isCombined).toEqual(true); ++ expect(9).toEqual(file1.addedLines); ++ expect(2).toEqual(file1.deletedLines); ++ expect(file1.oldName).toEqual("describe.c"); ++ expect(file1.newName).toEqual("describe.c"); ++ expect(file1.blocks.length).toEqual(1); ++ expect(file1.blocks[0].lines.length).toEqual(22); ++ expect(file1.checksumBefore).toEqual(["cc95eb0", "4866510"]); ++ expect(file1.checksumAfter).toEqual("fabadb8"); ++ }); ++ ++ it("should parse diffs with copied files", () => { ++ const diff = ++ "diff --git a/index.js b/more-index.js\n" + ++ "dissimilarity index 5%\n" + ++ "copy from index.js\n" + ++ "copy to more-index.js\n"; ++ ++ const result = parse(diff); ++ expect(result.length).toEqual(1); ++ ++ const file1 = result[0]; ++ expect(file1.addedLines).toEqual(0); ++ expect(file1.deletedLines).toEqual(0); ++ expect(file1.oldName).toEqual("index.js"); ++ expect(file1.newName).toEqual("more-index.js"); ++ expect(file1.blocks.length).toEqual(0); ++ expect(file1.isCopy).toEqual(true); ++ expect(file1.changedPercentage).toEqual(5); ++ }); ++ ++ it("should parse diffs with moved files", () => { ++ const diff = ++ "diff --git a/more-index.js b/other-index.js\n" + ++ "similarity index 86%\n" + ++ "rename from more-index.js\n" + ++ "rename to other-index.js\n"; ++ ++ const result = parse(diff); ++ expect(result.length).toEqual(1); ++ ++ const file1 = result[0]; ++ expect(file1.addedLines).toEqual(0); ++ expect(file1.deletedLines).toEqual(0); ++ expect(file1.oldName).toEqual("more-index.js"); ++ expect(file1.newName).toEqual("other-index.js"); ++ expect(file1.blocks.length).toEqual(0); ++ expect(file1.isRename).toEqual(true); ++ expect(file1.unchangedPercentage).toEqual(86); ++ }); ++ ++ it("should parse diffs correct line numbers", () => { ++ const diff = ++ "diff --git a/sample b/sample\n" + ++ "index 0000001..0ddf2ba\n" + ++ "--- a/sample\n" + ++ "+++ b/sample\n" + ++ "@@ -1 +1,2 @@\n" + ++ "-test\n" + ++ "+test1r\n"; ++ ++ const result = parse(diff); ++ expect(result.length).toEqual(1); ++ ++ const file1 = result[0]; ++ expect(file1.addedLines).toEqual(1); ++ expect(file1.deletedLines).toEqual(1); ++ expect(file1.oldName).toEqual("sample"); ++ expect(file1.newName).toEqual("sample"); ++ expect(file1.blocks.length).toEqual(1); ++ expect(file1.blocks[0].lines.length).toEqual(2); ++ expect(file1.blocks[0].lines[0].oldNumber).toEqual(1); ++ expect(file1.blocks[0].lines[0].newNumber).toBeUndefined(); ++ expect(file1.blocks[0].lines[1].oldNumber).toBeUndefined(); ++ expect(file1.blocks[0].lines[1].newNumber).toEqual(1); ++ }); ++ ++ it("should parse unified non git diff and strip timestamps off the headers", () => { ++ const diffs = [ ++ // 2 hours ahead of GMT ++ "--- a/sample.js 2016-10-25 11:37:14.000000000 +0200\n" + ++ "+++ b/sample.js 2016-10-25 11:37:14.000000000 +0200\n" + ++ "@@ -1 +1,2 @@\n" + ++ "-test\n" + ++ "+test1r\n" + ++ "+test2r\n", ++ // 2 hours behind GMT ++ "--- a/sample.js 2016-10-25 11:37:14.000000000 -0200\n" + ++ "+++ b/sample.js 2016-10-25 11:37:14.000000000 -0200\n" + ++ "@@ -1 +1,2 @@\n" + ++ "-test\n" + ++ "+test1r\n" + ++ "+test2r\n" ++ ]; ++ ++ diffs.forEach(diff => { ++ const result = parse(diff); ++ const file1 = result[0]; ++ expect(result.length).toEqual(1); ++ expect(file1.addedLines).toEqual(2); ++ expect(file1.deletedLines).toEqual(1); ++ expect(file1.oldName).toEqual("sample.js"); ++ expect(file1.newName).toEqual("sample.js"); ++ expect(file1.blocks.length).toEqual(1); ++ ++ const linesContent = file1.blocks[0].lines.map(line => { ++ return line.content; ++ }); ++ expect(["-test", "+test1r", "+test2r"]).toEqual(linesContent); ++ }); ++ }); ++ ++ it("should parse unified non git diff", () => { ++ const diff = ++ "--- a/sample.js\n" + "+++ b/sample.js\n" + "@@ -1 +1,2 @@\n" + "-test\n" + "+test1r\n" + "+test2r\n"; ++ ++ const result = parse(diff); ++ const file1 = result[0]; ++ expect(result.length).toEqual(1); ++ expect(file1.addedLines).toEqual(2); ++ expect(file1.deletedLines).toEqual(1); ++ expect(file1.oldName).toEqual("sample.js"); ++ expect(file1.newName).toEqual("sample.js"); ++ expect(file1.blocks.length).toEqual(1); ++ ++ const linesContent = file1.blocks[0].lines.map(line => { ++ return line.content; ++ }); ++ expect(["-test", "+test1r", "+test2r"]).toEqual(linesContent); ++ }); ++ ++ it("should parse unified diff with multiple hunks and files", () => { ++ const diff = ++ "--- sample.js\n" + ++ "+++ sample.js\n" + ++ "@@ -1 +1,2 @@\n" + ++ "-test\n" + ++ "@@ -10 +20,2 @@\n" + ++ "+test\n" + ++ "--- sample1.js\n" + ++ "+++ sample1.js\n" + ++ "@@ -1 +1,2 @@\n" + ++ "+test1"; ++ ++ const result = parse(diff); ++ expect(result.length).toEqual(2); ++ ++ const file1 = result[0]; ++ expect(file1.addedLines).toEqual(1); ++ expect(file1.deletedLines).toEqual(1); ++ expect(file1.oldName).toEqual("sample.js"); ++ expect(file1.newName).toEqual("sample.js"); ++ expect(file1.blocks.length).toEqual(2); ++ ++ const linesContent1 = file1.blocks[0].lines.map(line => { ++ return line.content; ++ }); ++ expect(["-test"]).toEqual(linesContent1); ++ ++ const linesContent2 = file1.blocks[1].lines.map(line => { ++ return line.content; ++ }); ++ expect(["+test"]).toEqual(linesContent2); ++ ++ const file2 = result[1]; ++ expect(file2.addedLines).toEqual(1); ++ expect(file2.deletedLines).toEqual(0); ++ expect(file2.oldName).toEqual("sample1.js"); ++ expect(file2.newName).toEqual("sample1.js"); ++ expect(file2.blocks.length).toEqual(1); ++ ++ const linesContent = file2.blocks[0].lines.map(line => { ++ return line.content; ++ }); ++ expect(["+test1"]).toEqual(linesContent); ++ }); ++ ++ it("should parse diff with --- and +++ in the context lines", () => { ++ const diff = ++ "--- sample.js\n" + ++ "+++ sample.js\n" + ++ "@@ -1,8 +1,8 @@\n" + ++ " test\n" + ++ " \n" + ++ "-- 1\n" + ++ "--- 1\n" + ++ "---- 1\n" + ++ " \n" + ++ "++ 2\n" + ++ "+++ 2\n" + ++ "++++ 2"; ++ ++ const result = parse(diff); ++ const file1 = result[0]; ++ expect(result.length).toEqual(1); ++ expect(file1.addedLines).toEqual(3); ++ expect(file1.deletedLines).toEqual(3); ++ expect(file1.oldName).toEqual("sample.js"); ++ expect(file1.newName).toEqual("sample.js"); ++ expect(file1.blocks.length).toEqual(1); ++ ++ const linesContent = file1.blocks[0].lines.map(line => { ++ return line.content; ++ }); ++ expect([" test", " ", "-- 1", "--- 1", "---- 1", " ", "++ 2", "+++ 2", "++++ 2"]).toEqual(linesContent); ++ }); ++ ++ it("should parse diff without proper hunk headers", () => { ++ const diff = "--- sample.js\n" + "+++ sample.js\n" + "@@ @@\n" + " test"; ++ ++ const result = parse(diff); ++ const file1 = result[0]; ++ expect(result.length).toEqual(1); ++ expect(file1.addedLines).toEqual(0); ++ expect(file1.deletedLines).toEqual(0); ++ expect(file1.oldName).toEqual("sample.js"); ++ expect(file1.newName).toEqual("sample.js"); ++ expect(file1.blocks.length).toEqual(1); ++ ++ const linesContent = file1.blocks[0].lines.map(line => { ++ return line.content; ++ }); ++ expect([" test"]).toEqual(linesContent); ++ }); ++ ++ it("should parse binary file diff", () => { ++ const diff = ++ "diff --git a/last-changes-config.png b/last-changes-config.png\n" + ++ "index 322248b..56fc1f2 100644\n" + ++ "--- a/last-changes-config.png\n" + ++ "+++ b/last-changes-config.png\n" + ++ "Binary files differ"; ++ ++ const result = parse(diff); ++ const file1 = result[0]; ++ expect(result.length).toEqual(1); ++ expect(file1.addedLines).toEqual(0); ++ expect(file1.deletedLines).toEqual(0); ++ expect(file1.oldName).toEqual("last-changes-config.png"); ++ expect(file1.newName).toEqual("last-changes-config.png"); ++ expect(file1.blocks.length).toEqual(1); ++ expect(file1.blocks[0].lines.length).toEqual(0); ++ expect(file1.blocks[0].header).toEqual("Binary files differ"); ++ }); ++ ++ it("should parse diff with --find-renames", () => { ++ const diff = ++ "diff --git a/src/test-bar.js b/src/test-baz.js\n" + ++ "similarity index 98%\n" + ++ "rename from src/test-bar.js\n" + ++ "rename to src/test-baz.js\n" + ++ "index e01513b..f14a870 100644\n" + ++ "--- a/src/test-bar.js\n" + ++ "+++ b/src/test-baz.js\n" + ++ "@@ -1,4 +1,32 @@\n" + ++ " function foo() {\n" + ++ '-var bar = "Whoops!";\n' + ++ '+var baz = "Whoops!";\n' + ++ " }\n" + ++ " "; ++ ++ const result = parse(diff); ++ const file1 = result[0]; ++ expect(result.length).toEqual(1); ++ expect(file1.addedLines).toEqual(1); ++ expect(file1.deletedLines).toEqual(1); ++ expect(file1.oldName).toEqual("src/test-bar.js"); ++ expect(file1.newName).toEqual("src/test-baz.js"); ++ expect(file1.blocks.length).toEqual(1); ++ expect(file1.blocks[0].lines.length).toEqual(5); ++ const linesContent = file1.blocks[0].lines.map(line => { ++ return line.content; ++ }); ++ expect([" function foo() {", '-var bar = "Whoops!";', '+var baz = "Whoops!";', " }", " "]).toEqual(linesContent); ++ }); ++ ++ it("should parse diff with prefix 2", () => { ++ const diff = ++ 'diff --git "\tTest.scala" "\tScalaTest.scala"\n' + ++ "similarity index 88%\n" + ++ "rename from Test.scala\n" + ++ "rename to ScalaTest.scala\n" + ++ "index 7d1f9bf..8b13271 100644\n" + ++ '--- "\tTest.scala"\n' + ++ '+++ "\tScalaTest.scala"\n' + ++ "@@ -1,6 +1,8 @@\n" + ++ " class Test {\n" + ++ " \n" + ++ " def method1 = ???\n" + ++ "+\n" + ++ "+ def method2 = ???\n" + ++ " \n" + ++ " def myMethod = ???\n" + ++ " \n" + ++ "@@ -10,7 +12,6 @@ class Test {\n" + ++ " \n" + ++ " def + = ???\n" + ++ " \n" + ++ "- def |> = ???\n" + ++ " \n" + ++ " }\n" + ++ " \n" + ++ 'diff --git "\ttardis.png" "\ttardis.png"\n' + ++ "new file mode 100644\n" + ++ "index 0000000..d503a29\n" + ++ 'Binary files /dev/null and "\ttardis.png" differ\n' + ++ "diff --git a/src/test-bar.js b/src/test-baz.js\n" + ++ "similarity index 98%\n" + ++ "rename from src/test-bar.js\n" + ++ "rename to src/test-baz.js\n" + ++ "index e01513b..f14a870 100644\n" + ++ "--- a/src/test-bar.js\n" + ++ "+++ b/src/test-baz.js\n" + ++ "@@ -1,4 +1,32 @@\n" + ++ " function foo() {\n" + ++ '-var bar = "Whoops!";\n' + ++ '+var baz = "Whoops!";\n' + ++ " }\n" + ++ " "; ++ ++ const result = parse(diff, { srcPrefix: "\t", dstPrefix: "\t" }); ++ expect(result.length).toEqual(3); ++ ++ const file1 = result[0]; ++ expect(file1.addedLines).toEqual(2); ++ expect(file1.deletedLines).toEqual(1); ++ expect(file1.oldName).toEqual("Test.scala"); ++ expect(file1.newName).toEqual("ScalaTest.scala"); ++ expect(file1.blocks.length).toEqual(2); ++ expect(file1.blocks[0].lines.length).toEqual(8); ++ expect(file1.blocks[1].lines.length).toEqual(7); ++ ++ const file2 = result[1]; ++ expect(file2.oldName).toEqual("/dev/null"); ++ expect(file2.newName).toEqual("tardis.png"); ++ ++ const file3 = result[2]; ++ expect(file3.addedLines).toEqual(1); ++ expect(file3.deletedLines).toEqual(1); ++ expect(file3.oldName).toEqual("src/test-bar.js"); ++ expect(file3.newName).toEqual("src/test-baz.js"); ++ expect(file3.blocks.length).toEqual(1); ++ expect(file3.blocks[0].lines.length).toEqual(5); ++ const linesContent = file3.blocks[0].lines.map(line => { ++ return line.content; ++ }); ++ expect([" function foo() {", '-var bar = "Whoops!";', '+var baz = "Whoops!";', " }", " "]).toEqual(linesContent); ++ }); ++ ++ it("should parse binary with content", () => { ++ const diff = ++ "diff --git a/favicon.png b/favicon.png\n" + ++ "deleted file mode 100644\n" + ++ "index 2a9d516a5647205d7be510dd0dff93a3663eff6f..0000000000000000000000000000000000000000\n" + ++ "GIT binary patch\n" + ++ "literal 0\n" + ++ "HcmV?d00001\n" + ++ "\n" + ++ "literal 471\n" + ++ "zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ\n" + ++ "za0`JjqPVOAS4ANVKzqmCp=Cty@U^(7zk!jHsvT~YI{F^=Ex6g|gox78w\n" + ++ "z+Sn2Du3GS9U7qU`1*NYYlJi3u-!-_B#8k9H0\n" + ++ "zGl{FnZs<2$wz5^=Q2h-1XI^s{LQL1#T4epqNPC%Orl(tD_@!*EY++~^Lt2<2&!&%=\n" + ++ "z`m>(TYj6uS7jDdt=eH>iOyQg(QMR<-Fw8)Dk^ZG)XQTuzEgl{`GpS?Cfq9818R9~=\n" + ++ "z{&h9@9n8F^?|qusoPy{k#%tVHzu7H$t26CR`BJZk*Ixf&u36WuS=?6m2^ho-p00i_\n" + ++ "I>zopr0Nz-&lmGw#\n" + ++ "diff --git a/src/test-bar.js b/src/test-baz.js\n" + ++ "similarity index 98%\n" + ++ "rename from src/test-bar.js\n" + ++ "rename to src/test-baz.js\n" + ++ "index e01513b..f14a870 100644\n" + ++ "--- a/src/test-bar.js\n" + ++ "+++ b/src/test-baz.js\n" + ++ "@@ -1,4 +1,32 @@\n" + ++ " function foo() {\n" + ++ '-var bar = "Whoops!";\n' + ++ '+var baz = "Whoops!";\n' + ++ " }\n" + ++ " "; ++ ++ const result = parse(diff); ++ expect(result.length).toEqual(2); ++ ++ const file1 = result[0]; ++ expect(file1.oldName).toEqual("favicon.png"); ++ expect(file1.newName).toEqual("favicon.png"); ++ expect(file1.blocks.length).toEqual(1); ++ expect(file1.blocks[0].lines.length).toEqual(0); ++ ++ const file2 = result[1]; ++ expect(file2.addedLines).toEqual(1); ++ expect(file2.deletedLines).toEqual(1); ++ expect(file2.oldName).toEqual("src/test-bar.js"); ++ expect(file2.newName).toEqual("src/test-baz.js"); ++ expect(file2.blocks.length).toEqual(1); ++ expect(file2.blocks[0].lines.length).toEqual(5); ++ const linesContent = file2.blocks[0].lines.map(line => { ++ return line.content; ++ }); ++ expect([" function foo() {", '-var bar = "Whoops!";', '+var baz = "Whoops!";', " }", " "]).toEqual(linesContent); ++ }); ++ }); ++}); +diff --git a/test/diff2html-tests.js b/src/__tests__/diff2html-tests.ts +similarity index 55% +rename from test/diff2html-tests.js +rename to src/__tests__/diff2html-tests.ts +index af9914ca..b0971487 100644 +--- a/test/diff2html-tests.js ++++ b/src/__tests__/diff2html-tests.ts +@@ -1,59 +1,58 @@ +-var assert = require('assert'); ++import { parse, html } from "../diff2html"; ++import { DiffFile, LineType, OutputFormatType } from "../types"; + +-var Diff2Html = require('../src/diff2html.js').Diff2Html; ++const diffExample1 = ++ "diff --git a/sample b/sample\n" + ++ "index 0000001..0ddf2ba\n" + ++ "--- a/sample\n" + ++ "+++ b/sample\n" + ++ "@@ -1 +1 @@\n" + ++ "-test\n" + ++ "+test1\n"; + +-var diffExample1 = +- 'diff --git a/sample b/sample\n' + +- 'index 0000001..0ddf2ba\n' + +- '--- a/sample\n' + +- '+++ b/sample\n' + +- '@@ -1 +1 @@\n' + +- '-test\n' + +- '+test1\n'; ++const jsonExample1: DiffFile[] = [ ++ { ++ blocks: [ ++ { ++ lines: [ ++ { ++ content: "-test", ++ type: LineType.DELETE, ++ oldNumber: 1, ++ newNumber: undefined ++ }, ++ { ++ content: "+test1", ++ type: LineType.INSERT, ++ oldNumber: undefined, ++ newNumber: 1 ++ } ++ ], ++ oldStartLine: 1, ++ oldStartLine2: undefined, ++ newStartLine: 1, ++ header: "@@ -1 +1 @@" ++ } ++ ], ++ deletedLines: 1, ++ addedLines: 1, ++ checksumBefore: "0000001", ++ checksumAfter: "0ddf2ba", ++ oldName: "sample", ++ newName: "sample", ++ language: "", ++ isCombined: false, ++ isGitDiff: true ++ } ++]; + +-var jsonExample1 = +- [ +- { +- blocks: [ +- { +- lines: [ +- { +- content: '-test', +- type: 'd2h-del', +- oldNumber: 1, +- newNumber: null +- }, +- { +- content: '+test1', +- type: 'd2h-ins', +- oldNumber: null, +- newNumber: 1 +- } +- ], +- oldStartLine: '1', +- oldStartLine2: null, +- newStartLine: '1', +- header: '@@ -1 +1 @@' +- } +- ], +- deletedLines: 1, +- addedLines: 1, +- checksumBefore: '0000001', +- checksumAfter: '0ddf2ba', +- oldName: 'sample', +- language: undefined, +- newName: 'sample', +- isCombined: false +- } +- ]; +- +-var filesExample1 = ++const filesExample1 = + '
\n' + + '
\n' + + ' Files changed (1)\n' + + ' hide\n' + + ' show\n' + +- '
\n' + ++ "
\n" + + '
    \n' + + '
  1. \n' + + ' \n' + +@@ -64,13 +63,13 @@ var filesExample1 = + ' \n' + + ' +1\n' + + ' -1\n' + +- ' \n' + +- ' \n' + +- '
  2. \n' + +- '
\n' + +- ''; ++ " \n" + ++ " \n" + ++ "\n" + ++ " \n" + ++ ""; + +-var htmlLineExample1 = ++const htmlLineExample1 = + '
\n' + + '
\n' + + '
\n' + +@@ -79,49 +78,49 @@ var htmlLineExample1 = + ' \n' + + ' sample\n' + + ' CHANGED\n' + +- '
\n' + ++ "
\n" + + '
\n' + + '
\n' + + ' \n' + + ' \n' + +- ' \n' + ++ " \n" + + ' \n' + + ' \n' + +- '\n' + +- ' \n" + ++ "\n" + ++ ' \n' + +- ' \n" + ++ ' \n' + +- '\n' + +- ' \n" + ++ "\n" + ++ ' \n' + +- ' \n" + ++ ' \n' + +- '\n' + +- ' \n' + +- '
\n' + + '
@@ -1 +1 @@
\n' + +- '
\n' + ++ "
\n' + + '
1
\n' + + '
\n' + +- '
\n' + +- '
\n' + ++ "
\n' + ++ '
\n' + + ' -\n' + + ' test\n' + +- '
\n' + +- '
\n' + ++ " \n" + ++ "
\n' + + '
\n' + + '
1
\n' + +- '
\n' + +- '
\n' + ++ "
\n' + ++ '
\n' + + ' +\n' + + ' test1\n' + +- '
\n' + +- '
\n' + +- '
\n' + +- '
\n' + +- '
\n' + +- ''; ++ " \n" + ++ " \n" + ++ "\n" + ++ " \n" + ++ " \n" + ++ " \n" + ++ " \n" + ++ "\n" + ++ ""; + +-var htmlLineExample1WithFilesSummary = filesExample1 + htmlLineExample1; ++const htmlLineExample1WithFilesSummary = filesExample1 + htmlLineExample1; + +-var htmlSideExample1 = ++const htmlSideExample1 = + '
\n' + + '
\n' + + '
\n' + +@@ -130,187 +129,189 @@ var htmlSideExample1 = + ' \n' + + ' sample\n' + + ' CHANGED\n' + +- '
\n' + ++ "
\n" + + '
\n' + + '
\n' + + '
\n' + + ' \n' + + ' \n' + +- ' \n' + ++ " \n" + + ' \n' + + ' \n' + +- '\n' + +- ' \n' + +- ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n' + +- '\n' + +- ' \n' + +- '
\n' + + '
@@ -1 +1 @@
\n' + +- '
\n' + +- ' 1\n' + +- ' \n' + +- '
\n' + ++ "
\n' + ++ " 1\n" + ++ " \n' + ++ '
\n' + + ' -\n' + + ' test\n' + +- '
\n' + +- '
\n' + +- '
\n' + +- '
\n' + ++ "
\n" + ++ " \n" + ++ "\n" + ++ " \n" + ++ " \n" + ++ "
\n" + ++ " \n" + + '
\n' + + '
\n' + + ' \n' + + ' \n' + +- ' \n' + ++ " \n" + + ' \n' + + ' \n' + +- '\n' + +- ' \n' + +- ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n' + +- '\n' + +- ' \n' + +- '
\n' + + '
\n' + +- '
\n' + +- ' 1\n' + +- ' \n' + +- '
\n' + ++ "
\n' + ++ " 1\n" + ++ " \n' + ++ '
\n' + + ' +\n' + + ' test1\n' + +- '
\n' + +- '
\n' + +- '
\n' + +- '
\n' + +- ' \n' + +- '\n' + +- ''; ++ " \n" + ++ " \n" + ++ "\n" + ++ " \n" + ++ " \n" + ++ " \n" + ++ " \n" + ++ " \n" + ++ "\n" + ++ ""; + +-var htmlSideExample1WithFilesSummary = filesExample1 + htmlSideExample1; ++const htmlSideExample1WithFilesSummary = filesExample1 + htmlSideExample1; + +-describe('Diff2Html', function() { +- describe('getJsonFromDiff', function() { +- it('should parse simple diff to json', function() { +- var diff = +- 'diff --git a/sample b/sample\n' + +- 'index 0000001..0ddf2ba\n' + +- '--- a/sample\n' + +- '+++ b/sample\n' + +- '@@ -1 +1 @@\n' + +- '-test\n' + +- '+test1\n'; +- var result = Diff2Html.getJsonFromDiff(diff); ++describe("Diff2Html", () => { ++ describe("getJsonFromDiff", () => { ++ it("should parse simple diff to json", () => { ++ const diff = ++ "diff --git a/sample b/sample\n" + ++ "index 0000001..0ddf2ba\n" + ++ "--- a/sample\n" + ++ "+++ b/sample\n" + ++ "@@ -1 +1 @@\n" + ++ "-test\n" + ++ "+test1\n"; ++ const result = parse(diff); + +- var file1 = result[0]; +- assert.equal(1, result.length); +- assert.equal(1, file1.addedLines); +- assert.equal(1, file1.deletedLines); +- assert.equal('sample', file1.oldName); +- assert.equal('sample', file1.newName); +- assert.equal(1, file1.blocks.length); ++ const file1 = result[0]; ++ expect(result.length).toEqual(1); ++ expect(file1.addedLines).toEqual(1); ++ expect(file1.deletedLines).toEqual(1); ++ expect(file1.oldName).toEqual("sample"); ++ expect(file1.newName).toEqual("sample"); ++ expect(file1.blocks.length).toEqual(1); + }); + + // Test case for issue #49 +- it('should parse diff with added EOF', function() { +- var diff = +- 'diff --git a/sample.scala b/sample.scala\n' + +- 'index b583263..8b2fc3e 100644\n' + +- '--- a/b583263..8b2fc3e\n' + +- '+++ b/8b2fc3e\n' + +- '@@ -50,5 +50,7 @@ case class Response[+A](value: Option[A],\n' + +- ' object ResponseErrorCode extends JsonEnumeration {\n' + +- ' val NoError, ServiceError, JsonError,\n' + +- ' InvalidPermissions, MissingPermissions, GenericError,\n' + +- '- TokenRevoked, MissingToken = Value\n' + +- '-}\n' + +- '\\ No newline at end of file\n' + +- '+ TokenRevoked, MissingToken,\n' + +- '+ IndexLock, RepositoryError, NotValidRepo, PullRequestNotMergeable, BranchError,\n' + +- '+ PluginError, CodeParserError, EngineError = Value\n' + +- '+}\n'; +- var result = Diff2Html.getJsonFromDiff(diff); ++ it("should parse diff with added EOF", () => { ++ const diff = ++ "diff --git a/sample.scala b/sample.scala\n" + ++ "index b583263..8b2fc3e 100644\n" + ++ "--- a/b583263..8b2fc3e\n" + ++ "+++ b/8b2fc3e\n" + ++ "@@ -50,5 +50,7 @@ case class Response[+A](value: Option[A],\n" + ++ " object ResponseErrorCode extends JsonEnumeration {\n" + ++ " val NoError, ServiceError, JsonError,\n" + ++ " InvalidPermissions, MissingPermissions, GenericError,\n" + ++ "- TokenRevoked, MissingToken = Value\n" + ++ "-}\n" + ++ "\\ No newline at end of file\n" + ++ "+ TokenRevoked, MissingToken,\n" + ++ "+ IndexLock, RepositoryError, NotValidRepo, PullRequestNotMergeable, BranchError,\n" + ++ "+ PluginError, CodeParserError, EngineError = Value\n" + ++ "+}\n"; ++ const result = parse(diff); + +- assert.equal(50, result[0].blocks[0].lines[0].oldNumber); +- assert.equal(50, result[0].blocks[0].lines[0].newNumber); ++ expect(result[0].blocks[0].lines[0].oldNumber).toEqual(50); ++ expect(result[0].blocks[0].lines[0].newNumber).toEqual(50); + +- assert.equal(51, result[0].blocks[0].lines[1].oldNumber); +- assert.equal(51, result[0].blocks[0].lines[1].newNumber); ++ expect(result[0].blocks[0].lines[1].oldNumber).toEqual(51); ++ expect(result[0].blocks[0].lines[1].newNumber).toEqual(51); + +- assert.equal(52, result[0].blocks[0].lines[2].oldNumber); +- assert.equal(52, result[0].blocks[0].lines[2].newNumber); ++ expect(result[0].blocks[0].lines[2].oldNumber).toEqual(52); ++ expect(result[0].blocks[0].lines[2].newNumber).toEqual(52); + +- assert.equal(53, result[0].blocks[0].lines[3].oldNumber); +- assert.equal(null, result[0].blocks[0].lines[3].newNumber); ++ expect(result[0].blocks[0].lines[3].oldNumber).toEqual(53); ++ expect(result[0].blocks[0].lines[3].newNumber).toBeUndefined(); + +- assert.equal(54, result[0].blocks[0].lines[4].oldNumber); +- assert.equal(null, result[0].blocks[0].lines[4].newNumber); ++ expect(result[0].blocks[0].lines[4].oldNumber).toEqual(54); ++ expect(result[0].blocks[0].lines[4].newNumber).toBeUndefined(); + +- assert.equal(null, result[0].blocks[0].lines[5].oldNumber); +- assert.equal(53, result[0].blocks[0].lines[5].newNumber); ++ expect(result[0].blocks[0].lines[5].oldNumber).toBeUndefined(); ++ expect(result[0].blocks[0].lines[5].newNumber).toEqual(53); + +- assert.equal(null, result[0].blocks[0].lines[6].oldNumber); +- assert.equal(54, result[0].blocks[0].lines[6].newNumber); ++ expect(result[0].blocks[0].lines[6].oldNumber).toBeUndefined(); ++ expect(result[0].blocks[0].lines[6].newNumber).toEqual(54); + +- assert.equal(null, result[0].blocks[0].lines[7].oldNumber); +- assert.equal(55, result[0].blocks[0].lines[7].newNumber); ++ expect(result[0].blocks[0].lines[7].oldNumber).toBeUndefined(); ++ expect(result[0].blocks[0].lines[7].newNumber).toEqual(55); + +- assert.equal(null, result[0].blocks[0].lines[8].oldNumber); +- assert.equal(56, result[0].blocks[0].lines[8].newNumber); ++ expect(result[0].blocks[0].lines[8].oldNumber).toBeUndefined(); ++ expect(result[0].blocks[0].lines[8].newNumber).toEqual(56); + }); + +- it('should generate pretty line by line html from diff', function() { +- var result = Diff2Html.getPrettyHtmlFromDiff(diffExample1); +- assert.equal(htmlLineExample1, result); ++ it("should generate pretty line by line html from diff", () => { ++ const result = html(diffExample1, { drawFileList: false }); ++ expect(result).toEqual(htmlLineExample1); + }); + +- it('should generate pretty line by line html from json', function() { +- var result = Diff2Html.getPrettyHtmlFromJson(jsonExample1); +- assert.equal(htmlLineExample1, result); ++ it("should generate pretty line by line html from json", () => { ++ const result = html(jsonExample1, { drawFileList: false }); ++ expect(result).toEqual(htmlLineExample1); + }); + +- it('should generate pretty diff with files summary', function() { +- var result = Diff2Html.getPrettyHtmlFromDiff(diffExample1, {showFiles: true}); +- assert.equal(htmlLineExample1WithFilesSummary, result); ++ it("should generate pretty diff with files summary", () => { ++ const result = html(diffExample1, { drawFileList: true }); ++ expect(result).toEqual(htmlLineExample1WithFilesSummary); + }); + +- it('should generate pretty side by side html from diff', function() { +- var result = Diff2Html.getPrettySideBySideHtmlFromDiff(diffExample1); +- assert.equal(htmlSideExample1, result); ++ it("should generate pretty side by side html from diff", () => { ++ const result = html(diffExample1, { outputFormat: OutputFormatType.SIDE_BY_SIDE, drawFileList: false }); ++ expect(result).toEqual(htmlSideExample1); + }); + +- it('should generate pretty side by side html from json', function() { +- var result = Diff2Html.getPrettySideBySideHtmlFromJson(jsonExample1); +- assert.equal(htmlSideExample1, result); ++ it("should generate pretty side by side html from json", () => { ++ const result = html(jsonExample1, { outputFormat: OutputFormatType.SIDE_BY_SIDE, drawFileList: false }); ++ expect(result).toEqual(htmlSideExample1); + }); + +- it('should generate pretty side by side html from diff', function() { +- var result = Diff2Html.getPrettySideBySideHtmlFromDiff(diffExample1, {showFiles: true}); +- assert.equal(htmlSideExample1WithFilesSummary, result); ++ it("should generate pretty side by side html from diff 2", () => { ++ const result = html(diffExample1, { outputFormat: OutputFormatType.SIDE_BY_SIDE, drawFileList: true }); ++ expect(result).toEqual(htmlSideExample1WithFilesSummary); + }); + +- it('should generate pretty side by side html from diff with html on headers', function() { +- var diffExample2 = 'diff --git a/CHANGELOG.md b/CHANGELOG.md\n' + +- 'index fc3e3f4..b486d10 100644\n' + +- '--- a/CHANGELOG.md\n' + +- '+++ b/CHANGELOG.md\n' + +- '@@ -1,7 +1,6 @@\n' + +- ' # Change Log\n' + +- ' All notable changes to this project will be documented in this file.\n' + +- ' This project adheres to [Semantic Versioning](http://semver.org/).\n' + ++ it("should generate pretty side by side html from diff with html on headers", () => { ++ const diffExample2 = ++ "diff --git a/CHANGELOG.md b/CHANGELOG.md\n" + ++ "index fc3e3f4..b486d10 100644\n" + ++ "--- a/CHANGELOG.md\n" + ++ "+++ b/CHANGELOG.md\n" + ++ "@@ -1,7 +1,6 @@\n" + ++ " # Change Log\n" + ++ " All notable changes to this project will be documented in this file.\n" + ++ " This project adheres to [Semantic Versioning](http://semver.org/).\n" + + '-$a="\n" + ++ ' \n" + ++ ' \n" + ++ "", ++ right: ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "" ++ }; ++ ++ expect(html).toEqual(expected); ++ }); ++ }); ++}); +diff --git a/src/__tests__/utils-tests.ts b/src/__tests__/utils-tests.ts +new file mode 100644 +index 00000000..9023c265 +--- /dev/null ++++ b/src/__tests__/utils-tests.ts +@@ -0,0 +1,31 @@ ++import { escapeForRegExp, unifyPath, hashCode } from "../utils"; ++ ++describe("Utils", () => { ++ describe("escapeForRegExp", () => { ++ it("should escape markdown link text", () => { ++ const result = escapeForRegExp("[Link](https://diff2html.xyz)"); ++ expect(result).toEqual("\\[Link\\]\\(https:\\/\\/diff2html\\.xyz\\)"); ++ }); ++ it("should escape all dangerous characters", () => { ++ const result = escapeForRegExp("-[]/{}()*+?.\\^$|"); ++ expect(result).toEqual("\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|"); ++ }); ++ }); ++ ++ describe("unifyPath", () => { ++ it("should unify windows style path", () => { ++ const result = unifyPath("\\Users\\Downloads\\diff.html"); ++ expect(result).toEqual("/Users/Downloads/diff.html"); ++ }); ++ }); ++ ++ describe("hashCode", () => { ++ it("should create consistent hash for a text piece", () => { ++ const string = "/home/diff2html/diff.html"; ++ expect(hashCode(string)).toEqual(hashCode(string)); ++ }); ++ it("should create different hash for different text pieces", () => { ++ expect(hashCode("/home/diff2html/diff1.html")).not.toEqual(hashCode("/home/diff2html/diff2.html")); ++ }); ++ }); ++}); +diff --git a/src/diff-parser.js b/src/diff-parser.js +deleted file mode 100644 +index 57892cb8..00000000 +--- a/src/diff-parser.js ++++ /dev/null +@@ -1,445 +0,0 @@ +-/* +- * +- * Diff Parser (diff-parser.js) +- * Author: rtfpessoa +- * +- */ +- +-(function() { +- var utils = require('./utils.js').Utils; +- +- var LINE_TYPE = { +- INSERTS: 'd2h-ins', +- DELETES: 'd2h-del', +- INSERT_CHANGES: 'd2h-ins d2h-change', +- DELETE_CHANGES: 'd2h-del d2h-change', +- CONTEXT: 'd2h-cntx', +- INFO: 'd2h-info' +- }; +- +- function DiffParser() { +- } +- +- DiffParser.prototype.LINE_TYPE = LINE_TYPE; +- +- DiffParser.prototype.generateDiffJson = function(diffInput, configuration) { +- var config = configuration || {}; +- +- var files = []; +- var currentFile = null; +- var currentBlock = null; +- var oldLine = null; +- var oldLine2 = null; // Used for combined diff +- var newLine = null; +- +- var possibleOldName; +- var possibleNewName; +- +- /* Diff Header */ +- var oldFileNameHeader = '--- '; +- var newFileNameHeader = '+++ '; +- var hunkHeaderPrefix = '@@'; +- +- /* Add previous block(if exists) before start a new file */ +- function saveBlock() { +- if (currentBlock) { +- currentFile.blocks.push(currentBlock); +- currentBlock = null; +- } +- } +- +- /* +- * Add previous file(if exists) before start a new one +- * if it has name (to avoid binary files errors) +- */ +- function saveFile() { +- if (currentFile) { +- if (!currentFile.oldName) { +- currentFile.oldName = possibleOldName; +- } +- +- if (!currentFile.newName) { +- currentFile.newName = possibleNewName; +- } +- +- if (currentFile.newName) { +- files.push(currentFile); +- currentFile = null; +- } +- } +- +- possibleOldName = undefined; +- possibleNewName = undefined; +- } +- +- /* Create file structure */ +- function startFile() { +- saveBlock(); +- saveFile(); +- +- currentFile = {}; +- currentFile.blocks = []; +- currentFile.deletedLines = 0; +- currentFile.addedLines = 0; +- } +- +- function startBlock(line) { +- saveBlock(); +- +- var values; +- +- /** +- * From Range: +- * -[,] +- * +- * To Range: +- * +[,] +- * +- * @@ from-file-range to-file-range @@ +- * +- * @@@ from-file-range from-file-range to-file-range @@@ +- * +- * number of lines is optional, if omited consider 0 +- */ +- +- if ((values = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@.*/.exec(line))) { +- currentFile.isCombined = false; +- oldLine = values[1]; +- newLine = values[2]; +- } else if ((values = /^@@@ -(\d+)(?:,\d+)? -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@@.*/.exec(line))) { +- currentFile.isCombined = true; +- oldLine = values[1]; +- oldLine2 = values[2]; +- newLine = values[3]; +- } else { +- if (utils.startsWith(line, hunkHeaderPrefix)) { +- console.error('Failed to parse lines, starting in 0!'); +- } +- +- oldLine = 0; +- newLine = 0; +- currentFile.isCombined = false; +- } +- +- /* Create block metadata */ +- currentBlock = {}; +- currentBlock.lines = []; +- currentBlock.oldStartLine = oldLine; +- currentBlock.oldStartLine2 = oldLine2; +- currentBlock.newStartLine = newLine; +- currentBlock.header = line; +- } +- +- function createLine(line) { +- var currentLine = {}; +- currentLine.content = line; +- +- var newLinePrefixes = !currentFile.isCombined ? ['+'] : ['+', ' +']; +- var delLinePrefixes = !currentFile.isCombined ? ['-'] : ['-', ' -']; +- +- /* Fill the line data */ +- if (utils.startsWith(line, newLinePrefixes)) { +- currentFile.addedLines++; +- +- currentLine.type = LINE_TYPE.INSERTS; +- currentLine.oldNumber = null; +- currentLine.newNumber = newLine++; +- +- currentBlock.lines.push(currentLine); +- } else if (utils.startsWith(line, delLinePrefixes)) { +- currentFile.deletedLines++; +- +- currentLine.type = LINE_TYPE.DELETES; +- currentLine.oldNumber = oldLine++; +- currentLine.newNumber = null; +- +- currentBlock.lines.push(currentLine); +- } else { +- currentLine.type = LINE_TYPE.CONTEXT; +- currentLine.oldNumber = oldLine++; +- currentLine.newNumber = newLine++; +- +- currentBlock.lines.push(currentLine); +- } +- } +- +- /* +- * Checks if there is a hunk header coming before a new file starts +- * +- * Hunk header is a group of three lines started by ( `--- ` , `+++ ` , `@@` ) +- */ +- function existHunkHeader(line, lineIdx) { +- var idx = lineIdx; +- +- while (idx < diffLines.length - 3) { +- if (utils.startsWith(line, 'diff')) { +- return false; +- } +- +- if ( +- utils.startsWith(diffLines[idx], oldFileNameHeader) && +- utils.startsWith(diffLines[idx + 1], newFileNameHeader) && +- utils.startsWith(diffLines[idx + 2], hunkHeaderPrefix) +- ) { +- return true; +- } +- +- idx++; +- } +- +- return false; +- } +- +- var diffLines = +- diffInput.replace(/\\ No newline at end of file/g, '') +- .replace(/\r\n?/g, '\n') +- .split('\n'); +- +- /* Diff */ +- var oldMode = /^old mode (\d{6})/; +- var newMode = /^new mode (\d{6})/; +- var deletedFileMode = /^deleted file mode (\d{6})/; +- var newFileMode = /^new file mode (\d{6})/; +- +- var copyFrom = /^copy from "?(.+)"?/; +- var copyTo = /^copy to "?(.+)"?/; +- +- var renameFrom = /^rename from "?(.+)"?/; +- var renameTo = /^rename to "?(.+)"?/; +- +- var similarityIndex = /^similarity index (\d+)%/; +- var dissimilarityIndex = /^dissimilarity index (\d+)%/; +- var index = /^index ([0-9a-z]+)\.\.([0-9a-z]+)\s*(\d{6})?/; +- +- var binaryFiles = /^Binary files (.*) and (.*) differ/; +- var binaryDiff = /^GIT binary patch/; +- +- /* Combined Diff */ +- var combinedIndex = /^index ([0-9a-z]+),([0-9a-z]+)\.\.([0-9a-z]+)/; +- var combinedMode = /^mode (\d{6}),(\d{6})\.\.(\d{6})/; +- var combinedNewFile = /^new file mode (\d{6})/; +- var combinedDeletedFile = /^deleted file mode (\d{6}),(\d{6})/; +- +- diffLines.forEach(function(line, lineIndex) { +- // Unmerged paths, and possibly other non-diffable files +- // https://github.com/scottgonzalez/pretty-diff/issues/11 +- // Also, remove some useless lines +- if (!line || utils.startsWith(line, '*')) { +- return; +- } +- +- // Used to store regex capture groups +- var values; +- +- var prevLine = diffLines[lineIndex - 1]; +- var nxtLine = diffLines[lineIndex + 1]; +- var afterNxtLine = diffLines[lineIndex + 2]; +- +- if (utils.startsWith(line, 'diff')) { +- startFile(); +- +- // diff --git a/blocked_delta_results.png b/blocked_delta_results.png +- var gitDiffStart = /^diff --git "?(.+)"? "?(.+)"?/; +- if ((values = gitDiffStart.exec(line))) { +- possibleOldName = _getFilename(null, values[1], config.dstPrefix); +- possibleNewName = _getFilename(null, values[2], config.srcPrefix); +- } +- +- currentFile.isGitDiff = true; +- return; +- } +- +- if (!currentFile || // If we do not have a file yet, we should crete one +- ( +- !currentFile.isGitDiff && currentFile && // If we already have some file in progress and +- ( +- utils.startsWith(line, oldFileNameHeader) && // If we get to an old file path header line +- // And is followed by the new file path header line and the hunk header line +- utils.startsWith(nxtLine, newFileNameHeader) && utils.startsWith(afterNxtLine, hunkHeaderPrefix) +- ) +- ) +- ) { +- startFile(); +- } +- +- /* +- * We need to make sure that we have the three lines of the header. +- * This avoids cases like the ones described in: +- * - https://github.com/rtfpessoa/diff2html/issues/87 +- */ +- if ( +- (utils.startsWith(line, oldFileNameHeader) && +- utils.startsWith(nxtLine, newFileNameHeader)) || +- +- (utils.startsWith(line, newFileNameHeader) && +- utils.startsWith(prevLine, oldFileNameHeader)) +- ) { +- /* +- * --- Date Timestamp[FractionalSeconds] TimeZone +- * --- 2002-02-21 23:30:39.942229878 -0800 +- */ +- if (currentFile && !currentFile.oldName && +- utils.startsWith(line, '--- ') && (values = getSrcFilename(line, config))) { +- currentFile.oldName = values; +- currentFile.language = getExtension(currentFile.oldName, currentFile.language); +- return; +- } +- +- /* +- * +++ Date Timestamp[FractionalSeconds] TimeZone +- * +++ 2002-02-21 23:30:39.942229878 -0800 +- */ +- if (currentFile && !currentFile.newName && +- utils.startsWith(line, '+++ ') && (values = getDstFilename(line, config))) { +- currentFile.newName = values; +- currentFile.language = getExtension(currentFile.newName, currentFile.language); +- return; +- } +- } +- +- if ( +- (currentFile && utils.startsWith(line, hunkHeaderPrefix)) || +- (currentFile.isGitDiff && currentFile && currentFile.oldName && currentFile.newName && !currentBlock) +- ) { +- startBlock(line); +- return; +- } +- +- /* +- * There are three types of diff lines. These lines are defined by the way they start. +- * 1. New line starts with: + +- * 2. Old line starts with: - +- * 3. Context line starts with: +- */ +- if (currentBlock && (utils.startsWith(line, '+') || utils.startsWith(line, '-') || utils.startsWith(line, ' '))) { +- createLine(line); +- return; +- } +- +- var doesNotExistHunkHeader = !existHunkHeader(line, lineIndex); +- +- /* +- * Git diffs provide more information regarding files modes, renames, copies, +- * commits between changes and similarity indexes +- */ +- if ((values = oldMode.exec(line))) { +- currentFile.oldMode = values[1]; +- } else if ((values = newMode.exec(line))) { +- currentFile.newMode = values[1]; +- } else if ((values = deletedFileMode.exec(line))) { +- currentFile.deletedFileMode = values[1]; +- currentFile.isDeleted = true; +- } else if ((values = newFileMode.exec(line))) { +- currentFile.newFileMode = values[1]; +- currentFile.isNew = true; +- } else if ((values = copyFrom.exec(line))) { +- if (doesNotExistHunkHeader) { +- currentFile.oldName = values[1]; +- } +- currentFile.isCopy = true; +- } else if ((values = copyTo.exec(line))) { +- if (doesNotExistHunkHeader) { +- currentFile.newName = values[1]; +- } +- currentFile.isCopy = true; +- } else if ((values = renameFrom.exec(line))) { +- if (doesNotExistHunkHeader) { +- currentFile.oldName = values[1]; +- } +- currentFile.isRename = true; +- } else if ((values = renameTo.exec(line))) { +- if (doesNotExistHunkHeader) { +- currentFile.newName = values[1]; +- } +- currentFile.isRename = true; +- } else if ((values = binaryFiles.exec(line))) { +- currentFile.isBinary = true; +- currentFile.oldName = _getFilename(null, values[1], config.srcPrefix); +- currentFile.newName = _getFilename(null, values[2], config.dstPrefix); +- startBlock('Binary file'); +- } else if ((values = binaryDiff.exec(line))) { +- currentFile.isBinary = true; +- startBlock(line); +- } else if ((values = similarityIndex.exec(line))) { +- currentFile.unchangedPercentage = values[1]; +- } else if ((values = dissimilarityIndex.exec(line))) { +- currentFile.changedPercentage = values[1]; +- } else if ((values = index.exec(line))) { +- currentFile.checksumBefore = values[1]; +- currentFile.checksumAfter = values[2]; +- values[3] && (currentFile.mode = values[3]); +- } else if ((values = combinedIndex.exec(line))) { +- currentFile.checksumBefore = [values[2], values[3]]; +- currentFile.checksumAfter = values[1]; +- } else if ((values = combinedMode.exec(line))) { +- currentFile.oldMode = [values[2], values[3]]; +- currentFile.newMode = values[1]; +- } else if ((values = combinedNewFile.exec(line))) { +- currentFile.newFileMode = values[1]; +- currentFile.isNew = true; +- } else if ((values = combinedDeletedFile.exec(line))) { +- currentFile.deletedFileMode = values[1]; +- currentFile.isDeleted = true; +- } +- }); +- +- saveBlock(); +- saveFile(); +- +- return files; +- }; +- +- function getExtension(filename, language) { +- var nameSplit = filename.split('.'); +- if (nameSplit.length > 1) { +- return nameSplit[nameSplit.length - 1]; +- } +- +- return language; +- } +- +- function getSrcFilename(line, cfg) { +- return _getFilename('---', line, cfg.srcPrefix); +- } +- +- function getDstFilename(line, cfg) { +- return _getFilename('\\+\\+\\+', line, cfg.dstPrefix); +- } +- +- function _getFilename(linePrefix, line, extraPrefix) { +- var prefixes = ['a/', 'b/', 'i/', 'w/', 'c/', 'o/']; +- if (extraPrefix) { +- prefixes.push(extraPrefix); +- } +- +- var FilenameRegExp; +- if (linePrefix) { +- FilenameRegExp = new RegExp('^' + linePrefix + ' "?(.+?)"?$'); +- } else { +- FilenameRegExp = new RegExp('^"?(.+?)"?$'); +- } +- +- var filename; +- var values = FilenameRegExp.exec(line); +- if (values && values[1]) { +- filename = values[1]; +- var matchingPrefixes = prefixes.filter(function(p) { +- return filename.indexOf(p) === 0; +- }); +- +- if (matchingPrefixes[0]) { +- // Remove prefix if exists +- filename = filename.slice(matchingPrefixes[0].length); +- } +- +- // Cleanup timestamps generated by the unified diff (diff command) as specified in +- // https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html +- // Ie: 2016-10-25 11:37:14.000000000 +0200 +- filename = filename.replace(/\s+\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)? [-+]\d{4}.*$/, ''); +- } +- +- return filename; +- } +- +- module.exports.DiffParser = new DiffParser(); +-})(); +diff --git a/src/diff-parser.ts b/src/diff-parser.ts +new file mode 100644 +index 00000000..7a5fc5d5 +--- /dev/null ++++ b/src/diff-parser.ts +@@ -0,0 +1,433 @@ ++import { DiffFile, DiffBlock, DiffLine, LineType } from "./types"; ++import { escapeForRegExp } from "./utils"; ++ ++export interface DiffParserConfig { ++ srcPrefix?: string; ++ dstPrefix?: string; ++} ++ ++function getExtension(filename: string, language: string): string { ++ const filenameParts = filename.split("."); ++ return filenameParts.length > 1 ? filenameParts[filenameParts.length - 1] : language; ++} ++ ++function startsWithAny(str: string, prefixes: string[]): boolean { ++ return prefixes.reduce((startsWith, prefix) => startsWith || str.startsWith(prefix), false); ++} ++ ++const baseDiffFilenamePrefixes = ["a/", "b/", "i/", "w/", "c/", "o/"]; ++function getFilename(line: string, linePrefix?: string, extraPrefix?: string): string { ++ const prefixes = extraPrefix !== undefined ? [...baseDiffFilenamePrefixes, extraPrefix] : baseDiffFilenamePrefixes; ++ ++ const FilenameRegExp = linePrefix ++ ? new RegExp(`^${escapeForRegExp(linePrefix)} "?(.+?)"?$`) ++ : new RegExp('^"?(.+?)"?$'); ++ ++ const [, filename = ""] = FilenameRegExp.exec(line) || []; ++ const matchingPrefix = prefixes.find(p => filename.indexOf(p) === 0); ++ const fnameWithoutPrefix = matchingPrefix ? filename.slice(matchingPrefix.length) : filename; ++ ++ // Cleanup timestamps generated by the unified diff (diff command) as specified in ++ // https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html ++ // Ie: 2016-10-25 11:37:14.000000000 +0200 ++ return fnameWithoutPrefix.replace(/\s+\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)? [-+]\d{4}.*$/, ""); ++} ++ ++function getSrcFilename(line: string, srcPrefix?: string): string | undefined { ++ return getFilename(line, "---", srcPrefix); ++} ++ ++function getDstFilename(line: string, dstPrefix?: string): string | undefined { ++ return getFilename(line, "+++", dstPrefix); ++} ++ ++/** ++ * ++ * Docs: ++ * - Unified: https://www.gnu.org/software/diffutils/manual/html_node/Unified-Format.html ++ * - Git Diff: https://git-scm.com/docs/git-diff-tree#_raw_output_format ++ * - Git Combined Diff: https://git-scm.com/docs/git-diff-tree#_combined_diff_format ++ * ++ */ ++export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFile[] { ++ const files: DiffFile[] = []; ++ let currentFile: DiffFile | null = null; ++ let currentBlock: DiffBlock | null = null; ++ let oldLine: number | null = null; ++ let oldLine2: number | null = null; // Used for combined diff ++ let newLine: number | null = null; ++ ++ let possibleOldName: string | null = null; ++ let possibleNewName: string | null = null; ++ ++ /* Diff Header */ ++ const oldFileNameHeader = "--- "; ++ const newFileNameHeader = "+++ "; ++ const hunkHeaderPrefix = "@@"; ++ ++ /* Diff */ ++ const oldMode = /^old mode (\d{6})/; ++ const newMode = /^new mode (\d{6})/; ++ const deletedFileMode = /^deleted file mode (\d{6})/; ++ const newFileMode = /^new file mode (\d{6})/; ++ ++ const copyFrom = /^copy from "?(.+)"?/; ++ const copyTo = /^copy to "?(.+)"?/; ++ ++ const renameFrom = /^rename from "?(.+)"?/; ++ const renameTo = /^rename to "?(.+)"?/; ++ ++ const similarityIndex = /^similarity index (\d+)%/; ++ const dissimilarityIndex = /^dissimilarity index (\d+)%/; ++ const index = /^index ([0-9a-z]+)\.\.([0-9a-z]+)\s*(\d{6})?/; ++ ++ const binaryFiles = /^Binary files (.*) and (.*) differ/; ++ const binaryDiff = /^GIT binary patch/; ++ ++ /* Combined Diff */ ++ const combinedIndex = /^index ([0-9a-z]+),([0-9a-z]+)\.\.([0-9a-z]+)/; ++ const combinedMode = /^mode (\d{6}),(\d{6})\.\.(\d{6})/; ++ const combinedNewFile = /^new file mode (\d{6})/; ++ const combinedDeletedFile = /^deleted file mode (\d{6}),(\d{6})/; ++ ++ const diffLines = diffInput ++ .replace(/\\ No newline at end of file/g, "") ++ .replace(/\r\n?/g, "\n") ++ .split("\n"); ++ ++ /* Add previous block(if exists) before start a new file */ ++ function saveBlock(): void { ++ if (currentBlock !== null && currentFile !== null) { ++ currentFile.blocks.push(currentBlock); ++ currentBlock = null; ++ } ++ } ++ ++ /* ++ * Add previous file(if exists) before start a new one ++ * if it has name (to avoid binary files errors) ++ */ ++ function saveFile(): void { ++ if (currentFile !== null) { ++ if (!currentFile.oldName && possibleOldName !== null) { ++ currentFile.oldName = possibleOldName; ++ } ++ ++ if (!currentFile.newName && possibleNewName !== null) { ++ currentFile.newName = possibleNewName; ++ } ++ ++ if (currentFile.newName) { ++ files.push(currentFile); ++ currentFile = null; ++ } ++ } ++ ++ possibleOldName = null; ++ possibleNewName = null; ++ } ++ ++ /* Create file structure */ ++ function startFile(): void { ++ saveBlock(); ++ saveFile(); ++ ++ // eslint-disable-next-line ++ // @ts-ignore ++ currentFile = { ++ blocks: [], ++ deletedLines: 0, ++ addedLines: 0 ++ }; ++ } ++ ++ function startBlock(line: string): void { ++ saveBlock(); ++ ++ let values; ++ ++ /** ++ * From Range: ++ * -[,] ++ * ++ * To Range: ++ * +[,] ++ * ++ * @@ from-file-range to-file-range @@ ++ * ++ * @@@ from-file-range from-file-range to-file-range @@@ ++ * ++ * number of lines is optional, if omited consider 0 ++ */ ++ ++ if (currentFile !== null) { ++ if ((values = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@.*/.exec(line))) { ++ currentFile.isCombined = false; ++ oldLine = parseInt(values[1], 10); ++ newLine = parseInt(values[2], 10); ++ } else if ((values = /^@@@ -(\d+)(?:,\d+)? -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@@.*/.exec(line))) { ++ currentFile.isCombined = true; ++ oldLine = parseInt(values[1], 10); ++ oldLine2 = parseInt(values[2], 10); ++ newLine = parseInt(values[3], 10); ++ } else { ++ if (line.startsWith(hunkHeaderPrefix)) { ++ console.error("Failed to parse lines, starting in 0!"); ++ } ++ ++ oldLine = 0; ++ newLine = 0; ++ currentFile.isCombined = false; ++ } ++ } ++ ++ /* Create block metadata */ ++ // eslint-disable-next-line ++ // @ts-ignore ++ currentBlock = { ++ lines: [], ++ oldStartLine: oldLine, ++ oldStartLine2: oldLine2, ++ newStartLine: newLine, ++ header: line ++ }; ++ } ++ ++ function createLine(line: string): void { ++ if (currentFile === null || currentBlock === null || oldLine === null || newLine === null) return; ++ ++ // eslint-disable-next-line ++ // @ts-ignore ++ const currentLine: DiffLine = { ++ content: line ++ }; ++ ++ const addedPrefixes = currentFile.isCombined ? ["+ ", " +", "++"] : ["+"]; ++ const deletedPrefixes = currentFile.isCombined ? ["- ", " -", "--"] : ["-"]; ++ ++ if (startsWithAny(line, addedPrefixes)) { ++ currentFile.addedLines++; ++ currentLine.type = LineType.INSERT; ++ currentLine.oldNumber = undefined; ++ currentLine.newNumber = newLine++; ++ } else if (startsWithAny(line, deletedPrefixes)) { ++ currentFile.deletedLines++; ++ currentLine.type = LineType.DELETE; ++ currentLine.oldNumber = oldLine++; ++ currentLine.newNumber = undefined; ++ } else { ++ currentLine.type = LineType.CONTEXT; ++ currentLine.oldNumber = oldLine++; ++ currentLine.newNumber = newLine++; ++ } ++ currentBlock.lines.push(currentLine); ++ } ++ ++ /* ++ * Checks if there is a hunk header coming before a new file starts ++ * ++ * Hunk header is a group of three lines started by ( `--- ` , `+++ ` , `@@` ) ++ */ ++ function existHunkHeader(line: string, lineIdx: number): boolean { ++ let idx = lineIdx; ++ ++ while (idx < diffLines.length - 3) { ++ if (line.startsWith("diff")) { ++ return false; ++ } ++ ++ if ( ++ diffLines[idx].startsWith(oldFileNameHeader) && ++ diffLines[idx + 1].startsWith(newFileNameHeader) && ++ diffLines[idx + 2].startsWith(hunkHeaderPrefix) ++ ) { ++ return true; ++ } ++ ++ idx++; ++ } ++ ++ return false; ++ } ++ ++ diffLines.forEach((line, lineIndex) => { ++ // Unmerged paths, and possibly other non-diffable files ++ // https://github.com/scottgonzalez/pretty-diff/issues/11 ++ // Also, remove some useless lines ++ if (!line || line.startsWith("*")) { ++ return; ++ } ++ ++ // Used to store regex capture groups ++ let values; ++ ++ const prevLine = diffLines[lineIndex - 1]; ++ const nxtLine = diffLines[lineIndex + 1]; ++ const afterNxtLine = diffLines[lineIndex + 2]; ++ ++ if (line.startsWith("diff")) { ++ startFile(); ++ ++ // diff --git a/blocked_delta_results.png b/blocked_delta_results.png ++ const gitDiffStart = /^diff --git "?(.+)"? "?(.+)"?/; ++ if ((values = gitDiffStart.exec(line))) { ++ possibleOldName = getFilename(values[1], undefined, config.dstPrefix); ++ possibleNewName = getFilename(values[2], undefined, config.srcPrefix); ++ } ++ ++ if (currentFile === null) { ++ throw new Error("Where is my file !!!"); ++ } ++ ++ currentFile.isGitDiff = true; ++ return; ++ } ++ ++ if ( ++ !currentFile || // If we do not have a file yet, we should crete one ++ (!currentFile.isGitDiff && ++ currentFile && // If we already have some file in progress and ++ line.startsWith(oldFileNameHeader) && // If we get to an old file path header line ++ // And is followed by the new file path header line and the hunk header line ++ nxtLine.startsWith(newFileNameHeader) && ++ afterNxtLine.startsWith(hunkHeaderPrefix)) ++ ) { ++ startFile(); ++ } ++ ++ /* ++ * We need to make sure that we have the three lines of the header. ++ * This avoids cases like the ones described in: ++ * - https://github.com/rtfpessoa/diff2html/issues/87 ++ */ ++ if ( ++ (line.startsWith(oldFileNameHeader) && nxtLine.startsWith(newFileNameHeader)) || ++ (line.startsWith(newFileNameHeader) && prevLine.startsWith(oldFileNameHeader)) ++ ) { ++ /* ++ * --- Date Timestamp[FractionalSeconds] TimeZone ++ * --- 2002-02-21 23:30:39.942229878 -0800 ++ */ ++ if ( ++ currentFile && ++ !currentFile.oldName && ++ line.startsWith("--- ") && ++ (values = getSrcFilename(line, config.srcPrefix)) ++ ) { ++ currentFile.oldName = values; ++ currentFile.language = getExtension(currentFile.oldName, currentFile.language); ++ return; ++ } ++ ++ /* ++ * +++ Date Timestamp[FractionalSeconds] TimeZone ++ * +++ 2002-02-21 23:30:39.942229878 -0800 ++ */ ++ if ( ++ currentFile && ++ !currentFile.newName && ++ line.startsWith("+++ ") && ++ (values = getDstFilename(line, config.dstPrefix)) ++ ) { ++ currentFile.newName = values; ++ currentFile.language = getExtension(currentFile.newName, currentFile.language); ++ return; ++ } ++ } ++ ++ if ( ++ currentFile && ++ (line.startsWith(hunkHeaderPrefix) || ++ (currentFile.isGitDiff && currentFile.oldName && currentFile.newName && !currentBlock)) ++ ) { ++ startBlock(line); ++ return; ++ } ++ ++ /* ++ * There are three types of diff lines. These lines are defined by the way they start. ++ * 1. New line starts with: + ++ * 2. Old line starts with: - ++ * 3. Context line starts with: ++ */ ++ if (currentBlock && (line.startsWith("+") || line.startsWith("-") || line.startsWith(" "))) { ++ createLine(line); ++ return; ++ } ++ ++ const doesNotExistHunkHeader = !existHunkHeader(line, lineIndex); ++ ++ if (currentFile === null) { ++ throw new Error("Where is my file !!!"); ++ } ++ ++ /* ++ * Git diffs provide more information regarding files modes, renames, copies, ++ * commits between changes and similarity indexes ++ */ ++ if ((values = oldMode.exec(line))) { ++ currentFile.oldMode = values[1]; ++ } else if ((values = newMode.exec(line))) { ++ currentFile.newMode = values[1]; ++ } else if ((values = deletedFileMode.exec(line))) { ++ currentFile.deletedFileMode = values[1]; ++ currentFile.isDeleted = true; ++ } else if ((values = newFileMode.exec(line))) { ++ currentFile.newFileMode = values[1]; ++ currentFile.isNew = true; ++ } else if ((values = copyFrom.exec(line))) { ++ if (doesNotExistHunkHeader) { ++ currentFile.oldName = values[1]; ++ } ++ currentFile.isCopy = true; ++ } else if ((values = copyTo.exec(line))) { ++ if (doesNotExistHunkHeader) { ++ currentFile.newName = values[1]; ++ } ++ currentFile.isCopy = true; ++ } else if ((values = renameFrom.exec(line))) { ++ if (doesNotExistHunkHeader) { ++ currentFile.oldName = values[1]; ++ } ++ currentFile.isRename = true; ++ } else if ((values = renameTo.exec(line))) { ++ if (doesNotExistHunkHeader) { ++ currentFile.newName = values[1]; ++ } ++ currentFile.isRename = true; ++ } else if ((values = binaryFiles.exec(line))) { ++ currentFile.isBinary = true; ++ currentFile.oldName = getFilename(values[1], undefined, config.srcPrefix); ++ currentFile.newName = getFilename(values[2], undefined, config.dstPrefix); ++ startBlock("Binary file"); ++ } else if (binaryDiff.test(line)) { ++ currentFile.isBinary = true; ++ startBlock(line); ++ } else if ((values = similarityIndex.exec(line))) { ++ currentFile.unchangedPercentage = parseInt(values[1], 10); ++ } else if ((values = dissimilarityIndex.exec(line))) { ++ currentFile.changedPercentage = parseInt(values[1], 10); ++ } else if ((values = index.exec(line))) { ++ currentFile.checksumBefore = values[1]; ++ currentFile.checksumAfter = values[2]; ++ values[3] && (currentFile.mode = values[3]); ++ } else if ((values = combinedIndex.exec(line))) { ++ currentFile.checksumBefore = [values[2], values[3]]; ++ currentFile.checksumAfter = values[1]; ++ } else if ((values = combinedMode.exec(line))) { ++ currentFile.oldMode = [values[2], values[3]]; ++ currentFile.newMode = values[1]; ++ } else if ((values = combinedNewFile.exec(line))) { ++ currentFile.newFileMode = values[1]; ++ currentFile.isNew = true; ++ } else if ((values = combinedDeletedFile.exec(line))) { ++ currentFile.deletedFileMode = values[1]; ++ currentFile.isDeleted = true; ++ } ++ }); ++ ++ saveBlock(); ++ saveFile(); ++ ++ return files; ++} +diff --git a/src/diff2html.d.ts b/src/diff2html.d.ts +deleted file mode 100644 +index cea93f6f..00000000 +--- a/src/diff2html.d.ts ++++ /dev/null +@@ -1,71 +0,0 @@ +-// Type definitions for diff2html +-// Project: https://github.com/rtfpessoa/diff2html +-// Definitions by: rtfpessoa +-// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +- +-declare namespace Diff2Html { +- +- export interface Options { +- inputFormat?: 'diff' | 'json'; +- outputFormat?: 'line-by-line' | 'side-by-side'; +- showFiles?: boolean; +- diffStyle?: 'word' | 'char'; +- matching?: 'lines' | 'words' | 'none'; +- matchWordsThreshold?: number; +- matchingMaxComparisons?: number; +- maxLineSizeInBlockForComparison?: number; +- maxLineLengthHighlight?: number; +- templates?: object; +- rawTemplates?: object; +- renderNothingWhenEmpty?: boolean; +- } +- +- export interface Line { +- content: string; +- type: string; +- oldNumber: number; +- newNumber: number; +- } +- +- export interface Block { +- oldStartLine: number; +- oldStartLine2?: number; +- newStartLine: number; +- header: string; +- lines: Line[]; +- } +- +- export interface Result { +- addedLines: number; +- deletedLines: number; +- isCombined: boolean; +- isGitDiff: boolean; +- oldName: string; +- newName: string; +- language: string; +- blocks: Block[]; +- oldMode?: string; +- newMode?: string; +- deletedFileMode?: string; +- newFileMode?: string; +- isDeleted?: boolean; +- isNew?: boolean; +- isCopy?: boolean; +- isRename?: boolean; +- unchangedPercentage?: number; +- changedPercentage?: number; +- checksumBefore?: string; +- checksumAfter?: string; +- mode?: string; +- } +- +- export interface Diff2Html { +- getJsonFromDiff(input: string, configuration?: Options): Result[]; +- getPrettyHtml(input: any, configuration?: Options): string; +- } +-} +- +-declare module "diff2html" { +- var d2h: { "Diff2Html": Diff2Html.Diff2Html }; +- export = d2h; +-} +diff --git a/src/diff2html.js b/src/diff2html.js +deleted file mode 100644 +index 4d4155db..00000000 +--- a/src/diff2html.js ++++ /dev/null +@@ -1,114 +0,0 @@ +-/* +- * +- * Diff to HTML (diff2html.js) +- * Author: rtfpessoa +- * +- */ +- +-(function() { +- var diffParser = require('./diff-parser.js').DiffParser; +- var htmlPrinter = require('./html-printer.js').HtmlPrinter; +- var utils = require('./utils.js').Utils; +- +- function Diff2Html() { +- } +- +- var defaultConfig = { +- inputFormat: 'diff', +- outputFormat: 'line-by-line', +- showFiles: false, +- diffStyle: 'word', +- matching: 'none', +- matchWordsThreshold: 0.25, +- matchingMaxComparisons: 2500, +- maxLineSizeInBlockForComparison: 200, +- maxLineLengthHighlight: 10000, +- templates: {}, +- rawTemplates: {}, +- renderNothingWhenEmpty: false +- }; +- +- /* +- * Generates json object from string diff input +- */ +- Diff2Html.prototype.getJsonFromDiff = function(diffInput, config) { +- var cfg = utils.safeConfig(config, defaultConfig); +- return diffParser.generateDiffJson(diffInput, cfg); +- }; +- +- /* +- * Generates the html diff. The config parameter configures the output/input formats and other options +- */ +- Diff2Html.prototype.getPrettyHtml = function(diffInput, config) { +- var cfg = utils.safeConfig(config, defaultConfig); +- +- var diffJson = diffInput; +- if (!cfg.inputFormat || cfg.inputFormat === 'diff') { +- diffJson = diffParser.generateDiffJson(diffInput, cfg); +- } +- +- var fileList = ''; +- if (cfg.showFiles === true) { +- fileList = htmlPrinter.generateFileListSummary(diffJson, cfg); +- } +- +- var diffOutput = ''; +- if (cfg.outputFormat === 'side-by-side') { +- diffOutput = htmlPrinter.generateSideBySideJsonHtml(diffJson, cfg); +- } else { +- diffOutput = htmlPrinter.generateLineByLineJsonHtml(diffJson, cfg); +- } +- +- return fileList + diffOutput; +- }; +- +- /* +- * Deprecated methods - The following methods exist only to maintain compatibility with previous versions +- */ +- +- /* +- * Generates pretty html from string diff input +- */ +- Diff2Html.prototype.getPrettyHtmlFromDiff = function(diffInput, config) { +- var cfg = utils.safeConfig(config, defaultConfig); +- cfg.inputFormat = 'diff'; +- cfg.outputFormat = 'line-by-line'; +- return this.getPrettyHtml(diffInput, cfg); +- }; +- +- /* +- * Generates pretty html from a json object +- */ +- Diff2Html.prototype.getPrettyHtmlFromJson = function(diffJson, config) { +- var cfg = utils.safeConfig(config, defaultConfig); +- cfg.inputFormat = 'json'; +- cfg.outputFormat = 'line-by-line'; +- return this.getPrettyHtml(diffJson, cfg); +- }; +- +- /* +- * Generates pretty side by side html from string diff input +- */ +- Diff2Html.prototype.getPrettySideBySideHtmlFromDiff = function(diffInput, config) { +- var cfg = utils.safeConfig(config, defaultConfig); +- cfg.inputFormat = 'diff'; +- cfg.outputFormat = 'side-by-side'; +- return this.getPrettyHtml(diffInput, cfg); +- }; +- +- /* +- * Generates pretty side by side html from a json object +- */ +- Diff2Html.prototype.getPrettySideBySideHtmlFromJson = function(diffJson, config) { +- var cfg = utils.safeConfig(config, defaultConfig); +- cfg.inputFormat = 'json'; +- cfg.outputFormat = 'side-by-side'; +- return this.getPrettyHtml(diffJson, cfg); +- }; +- +- var diffObject = new Diff2Html(); +- module.exports.Diff2Html = diffObject; +- +- // Expose diff2html in the browser +- global.Diff2Html = diffObject; +-})(); +diff --git a/src/diff2html.ts b/src/diff2html.ts +new file mode 100644 +index 00000000..1275eebb +--- /dev/null ++++ b/src/diff2html.ts +@@ -0,0 +1,43 @@ ++import * as DiffParser from "./diff-parser"; ++import * as fileListPrinter from "./file-list-renderer"; ++import LineByLineRenderer, { LineByLineRendererConfig, defaultLineByLineRendererConfig } from "./line-by-line-renderer"; ++import SideBySideRenderer, { SideBySideRendererConfig, defaultSideBySideRendererConfig } from "./side-by-side-renderer"; ++import { DiffFile, OutputFormatType } from "./types"; ++import HoganJsUtils, { HoganJsUtilsConfig } from "./hoganjs-utils"; ++ ++export interface Diff2HtmlConfig ++ extends DiffParser.DiffParserConfig, ++ LineByLineRendererConfig, ++ SideBySideRendererConfig, ++ HoganJsUtilsConfig { ++ outputFormat?: OutputFormatType; ++ drawFileList?: boolean; ++} ++ ++export const defaultDiff2HtmlConfig = { ++ ...defaultLineByLineRendererConfig, ++ ...defaultSideBySideRendererConfig, ++ outputFormat: OutputFormatType.LINE_BY_LINE, ++ drawFileList: true ++}; ++ ++export function parse(diffInput: string, configuration: Diff2HtmlConfig = {}): DiffFile[] { ++ return DiffParser.parse(diffInput, { ...defaultDiff2HtmlConfig, ...configuration }); ++} ++ ++export function html(diffInput: string | DiffFile[], configuration: Diff2HtmlConfig = {}): string { ++ const config = { ...defaultDiff2HtmlConfig, ...configuration }; ++ ++ const diffJson = typeof diffInput === "string" ? DiffParser.parse(diffInput, config) : diffInput; ++ ++ const hoganUtils = new HoganJsUtils(config); ++ ++ const fileList = config.drawFileList ? fileListPrinter.render(diffJson, hoganUtils) : ""; ++ ++ const diffOutput = ++ config.outputFormat === "side-by-side" ++ ? new SideBySideRenderer(hoganUtils, config).render(diffJson) ++ : new LineByLineRenderer(hoganUtils, config).render(diffJson); ++ ++ return fileList + diffOutput; ++} +diff --git a/src/file-list-printer.js b/src/file-list-printer.js +deleted file mode 100644 +index da371c91..00000000 +--- a/src/file-list-printer.js ++++ /dev/null +@@ -1,49 +0,0 @@ +-/* +- * +- * FileListPrinter (file-list-printer.js) +- * Author: nmatpt +- * +- */ +- +-(function() { +- var printerUtils = require('./printer-utils.js').PrinterUtils; +- +- var hoganUtils; +- +- var baseTemplatesPath = 'file-summary'; +- var iconsBaseTemplatesPath = 'icon'; +- +- function FileListPrinter(config) { +- this.config = config; +- +- var HoganJsUtils = require('./hoganjs-utils.js').HoganJsUtils; +- hoganUtils = new HoganJsUtils(config); +- } +- +- FileListPrinter.prototype.generateFileList = function(diffFiles) { +- var lineTemplate = hoganUtils.template(baseTemplatesPath, 'line'); +- +- var files = diffFiles.map(function(file) { +- var fileTypeName = printerUtils.getFileTypeIcon(file); +- var iconTemplate = hoganUtils.template(iconsBaseTemplatesPath, fileTypeName); +- +- return lineTemplate.render({ +- fileHtmlId: printerUtils.getHtmlId(file), +- oldName: file.oldName, +- newName: file.newName, +- fileName: printerUtils.getDiffName(file), +- deletedLines: '-' + file.deletedLines, +- addedLines: '+' + file.addedLines +- }, { +- fileIcon: iconTemplate +- }); +- }).join('\n'); +- +- return hoganUtils.render(baseTemplatesPath, 'wrapper', { +- filesNumber: diffFiles.length, +- files: files +- }); +- }; +- +- module.exports.FileListPrinter = FileListPrinter; +-})(); +diff --git a/src/file-list-renderer.ts b/src/file-list-renderer.ts +new file mode 100644 +index 00000000..8d2b2d89 +--- /dev/null ++++ b/src/file-list-renderer.ts +@@ -0,0 +1,33 @@ ++import * as renderUtils from "./render-utils"; ++import HoganJsUtils from "./hoganjs-utils"; ++import { DiffFile } from "./types"; ++ ++const baseTemplatesPath = "file-summary"; ++const iconsBaseTemplatesPath = "icon"; ++ ++export function render(diffFiles: DiffFile[], hoganUtils: HoganJsUtils): string { ++ const files = diffFiles ++ .map(file => ++ hoganUtils.render( ++ baseTemplatesPath, ++ "line", ++ { ++ fileHtmlId: renderUtils.getHtmlId(file), ++ oldName: file.oldName, ++ newName: file.newName, ++ fileName: renderUtils.filenameDiff(file), ++ deletedLines: "-" + file.deletedLines, ++ addedLines: "+" + file.addedLines ++ }, ++ { ++ fileIcon: hoganUtils.template(iconsBaseTemplatesPath, renderUtils.getFileIcon(file)) ++ } ++ ) ++ ) ++ .join("\n"); ++ ++ return hoganUtils.render(baseTemplatesPath, "wrapper", { ++ filesNumber: diffFiles.length, ++ files: files ++ }); ++} +diff --git a/src/hoganjs-utils.js b/src/hoganjs-utils.js +deleted file mode 100644 +index b2e9c275..00000000 +--- a/src/hoganjs-utils.js ++++ /dev/null +@@ -1,89 +0,0 @@ +-/* +- * +- * Utils (hoganjs-utils.js) +- * Author: rtfpessoa +- * +- */ +- +-(function() { +- var fs = require('fs'); +- var path = require('path'); +- var hogan = require('hogan.js'); +- +- var hoganTemplates = require('./templates/diff2html-templates.js'); +- +- var extraTemplates; +- +- function HoganJsUtils(configuration) { +- this.config = configuration || {}; +- extraTemplates = this.config.templates || {}; +- +- var rawTemplates = this.config.rawTemplates || {}; +- for (var templateName in rawTemplates) { +- if (rawTemplates.hasOwnProperty(templateName)) { +- if (!extraTemplates[templateName]) extraTemplates[templateName] = this.compile(rawTemplates[templateName]); +- } +- } +- } +- +- HoganJsUtils.prototype.render = function(namespace, view, params) { +- var template = this.template(namespace, view); +- if (template) { +- return template.render(params); +- } +- +- return null; +- }; +- +- HoganJsUtils.prototype.template = function(namespace, view) { +- var templateKey = this._templateKey(namespace, view); +- +- return this._getTemplate(templateKey); +- }; +- +- HoganJsUtils.prototype._getTemplate = function(templateKey) { +- var template; +- +- if (!this.config.noCache) { +- template = this._readFromCache(templateKey); +- } +- +- if (!template) { +- template = this._loadTemplate(templateKey); +- } +- +- return template; +- }; +- +- HoganJsUtils.prototype._loadTemplate = function(templateKey) { +- var template; +- +- try { +- if (fs.readFileSync) { +- var templatesPath = path.resolve(__dirname, 'templates'); +- var templatePath = path.join(templatesPath, templateKey); +- var templateContent = fs.readFileSync(templatePath + '.mustache', 'utf8'); +- template = hogan.compile(templateContent); +- hoganTemplates[templateKey] = template; +- } +- } catch (e) { +- console.error('Failed to read (template: ' + templateKey + ') from fs: ' + e.message); +- } +- +- return template; +- }; +- +- HoganJsUtils.prototype._readFromCache = function(templateKey) { +- return extraTemplates[templateKey] || hoganTemplates[templateKey]; +- }; +- +- HoganJsUtils.prototype._templateKey = function(namespace, view) { +- return namespace + '-' + view; +- }; +- +- HoganJsUtils.prototype.compile = function(templateStr) { +- return hogan.compile(templateStr); +- }; +- +- module.exports.HoganJsUtils = HoganJsUtils; +-})(); +diff --git a/src/hoganjs-utils.ts b/src/hoganjs-utils.ts +new file mode 100644 +index 00000000..4ae987dc +--- /dev/null ++++ b/src/hoganjs-utils.ts +@@ -0,0 +1,54 @@ ++import * as Hogan from "hogan.js"; ++ ++import { defaultTemplates } from "./diff2html-templates"; ++ ++export interface RawTemplates { ++ [name: string]: string; ++} ++ ++export interface CompiledTemplates { ++ [name: string]: Hogan.Template; ++} ++ ++export interface HoganJsUtilsConfig { ++ compiledTemplates?: CompiledTemplates; ++ rawTemplates?: RawTemplates; ++} ++ ++export default class HoganJsUtils { ++ private preCompiledTemplates: CompiledTemplates; ++ ++ constructor({ compiledTemplates = {}, rawTemplates = {} }: HoganJsUtilsConfig) { ++ const compiledRawTemplates = Object.entries(rawTemplates).reduce( ++ (previousTemplates, [name, templateString]) => { ++ const compiledTemplate: Hogan.Template = Hogan.compile(templateString, { asString: false }); ++ return { ...previousTemplates, [name]: compiledTemplate }; ++ }, ++ {} ++ ); ++ ++ this.preCompiledTemplates = { ...defaultTemplates, ...compiledTemplates, ...compiledRawTemplates }; ++ } ++ ++ static compile(templateString: string): Hogan.Template { ++ return Hogan.compile(templateString, { asString: false }); ++ } ++ ++ render(namespace: string, view: string, params: Hogan.Context, partials?: Hogan.Partials, indent?: string): string { ++ const templateKey = this.templateKey(namespace, view); ++ try { ++ const template = this.preCompiledTemplates[templateKey]; ++ return template.render(params, partials, indent); ++ } catch (e) { ++ throw new Error(`Could not find template to render '${templateKey}'`); ++ } ++ } ++ ++ template(namespace: string, view: string): Hogan.Template { ++ return this.preCompiledTemplates[this.templateKey(namespace, view)]; ++ } ++ ++ private templateKey(namespace: string, view: string): string { ++ return `${namespace}-${view}`; ++ } ++} +diff --git a/src/html-printer.js b/src/html-printer.js +deleted file mode 100644 +index 13f83047..00000000 +--- a/src/html-printer.js ++++ /dev/null +@@ -1,32 +0,0 @@ +-/* +- * +- * HtmlPrinter (html-printer.js) +- * Author: rtfpessoa +- * +- */ +- +-(function() { +- var LineByLinePrinter = require('./line-by-line-printer.js').LineByLinePrinter; +- var SideBySidePrinter = require('./side-by-side-printer.js').SideBySidePrinter; +- var FileListPrinter = require('./file-list-printer.js').FileListPrinter; +- +- function HtmlPrinter() { +- } +- +- HtmlPrinter.prototype.generateLineByLineJsonHtml = function(diffFiles, config) { +- var lineByLinePrinter = new LineByLinePrinter(config); +- return lineByLinePrinter.generateLineByLineJsonHtml(diffFiles); +- }; +- +- HtmlPrinter.prototype.generateSideBySideJsonHtml = function(diffFiles, config) { +- var sideBySidePrinter = new SideBySidePrinter(config); +- return sideBySidePrinter.generateSideBySideJsonHtml(diffFiles); +- }; +- +- HtmlPrinter.prototype.generateFileListSummary = function(diffJson, config) { +- var fileListPrinter = new FileListPrinter(config); +- return fileListPrinter.generateFileList(diffJson); +- }; +- +- module.exports.HtmlPrinter = new HtmlPrinter(); +-})(); +diff --git a/src/line-by-line-printer.js b/src/line-by-line-printer.js +deleted file mode 100644 +index 49f183fc..00000000 +--- a/src/line-by-line-printer.js ++++ /dev/null +@@ -1,237 +0,0 @@ +-/* +- * +- * LineByLinePrinter (line-by-line-printer.js) +- * Author: rtfpessoa +- * +- */ +- +-(function() { +- var diffParser = require('./diff-parser.js').DiffParser; +- var printerUtils = require('./printer-utils.js').PrinterUtils; +- var utils = require('./utils.js').Utils; +- var Rematch = require('./rematch.js').Rematch; +- +- var hoganUtils; +- +- var genericTemplatesPath = 'generic'; +- var baseTemplatesPath = 'line-by-line'; +- var iconsBaseTemplatesPath = 'icon'; +- var tagsBaseTemplatesPath = 'tag'; +- +- function LineByLinePrinter(config) { +- this.config = config; +- +- var HoganJsUtils = require('./hoganjs-utils.js').HoganJsUtils; +- hoganUtils = new HoganJsUtils(config); +- } +- +- LineByLinePrinter.prototype.makeFileDiffHtml = function(file, diffs) { +- if (this.config.renderNothingWhenEmpty && file.blocks && !file.blocks.length) return ''; +- +- var fileDiffTemplate = hoganUtils.template(baseTemplatesPath, 'file-diff'); +- var filePathTemplate = hoganUtils.template(genericTemplatesPath, 'file-path'); +- var fileIconTemplate = hoganUtils.template(iconsBaseTemplatesPath, 'file'); +- var fileTagTemplate = hoganUtils.template(tagsBaseTemplatesPath, printerUtils.getFileTypeIcon(file)); +- +- return fileDiffTemplate.render({ +- file: file, +- fileHtmlId: printerUtils.getHtmlId(file), +- diffs: diffs, +- filePath: filePathTemplate.render({ +- fileDiffName: printerUtils.getDiffName(file) +- }, { +- fileIcon: fileIconTemplate, +- fileTag: fileTagTemplate +- }) +- }); +- }; +- +- LineByLinePrinter.prototype.makeLineByLineHtmlWrapper = function(content) { +- return hoganUtils.render(genericTemplatesPath, 'wrapper', {'content': content}); +- }; +- +- LineByLinePrinter.prototype.generateLineByLineJsonHtml = function(diffFiles) { +- var that = this; +- var htmlDiffs = diffFiles.map(function(file) { +- var diffs; +- if (file.blocks.length) { +- diffs = that._generateFileHtml(file); +- } else { +- diffs = that._generateEmptyDiff(); +- } +- return that.makeFileDiffHtml(file, diffs); +- }); +- +- return this.makeLineByLineHtmlWrapper(htmlDiffs.join('\n')); +- }; +- +- var matcher = Rematch.rematch(function(a, b) { +- var amod = a.content.substr(1); +- var bmod = b.content.substr(1); +- +- return Rematch.distance(amod, bmod); +- }); +- +- LineByLinePrinter.prototype.makeColumnLineNumberHtml = function(block) { +- return hoganUtils.render(genericTemplatesPath, 'column-line-number', { +- diffParser: diffParser, +- blockHeader: utils.escape(block.header), +- lineClass: 'd2h-code-linenumber', +- contentClass: 'd2h-code-line' +- }); +- }; +- +- LineByLinePrinter.prototype._generateFileHtml = function(file) { +- var that = this; +- return file.blocks.map(function(block) { +- var lines = that.makeColumnLineNumberHtml(block); +- var oldLines = []; +- var newLines = []; +- +- function processChangeBlock() { +- var matches; +- var insertType; +- var deleteType; +- +- var comparisons = oldLines.length * newLines.length; +- +- var maxLineSizeInBlock = Math.max.apply(null, +- [0].concat((oldLines.concat(newLines)).map( +- function(elem) { +- return elem.content.length; +- } +- ))); +- +- var doMatching = comparisons < that.config.matchingMaxComparisons && +- maxLineSizeInBlock < that.config.maxLineSizeInBlockForComparison && +- (that.config.matching === 'lines' || that.config.matching === 'words'); +- +- if (doMatching) { +- matches = matcher(oldLines, newLines); +- insertType = diffParser.LINE_TYPE.INSERT_CHANGES; +- deleteType = diffParser.LINE_TYPE.DELETE_CHANGES; +- } else { +- matches = [[oldLines, newLines]]; +- insertType = diffParser.LINE_TYPE.INSERTS; +- deleteType = diffParser.LINE_TYPE.DELETES; +- } +- +- matches.forEach(function(match) { +- oldLines = match[0]; +- newLines = match[1]; +- +- var processedOldLines = []; +- var processedNewLines = []; +- +- var common = Math.min(oldLines.length, newLines.length); +- +- var oldLine, newLine; +- for (var j = 0; j < common; j++) { +- oldLine = oldLines[j]; +- newLine = newLines[j]; +- +- that.config.isCombined = file.isCombined; +- var diff = printerUtils.diffHighlight(oldLine.content, newLine.content, that.config); +- +- processedOldLines += +- that.makeLineHtml(file.isCombined, deleteType, oldLine.oldNumber, oldLine.newNumber, +- diff.first.line, diff.first.prefix); +- processedNewLines += +- that.makeLineHtml(file.isCombined, insertType, newLine.oldNumber, newLine.newNumber, +- diff.second.line, diff.second.prefix); +- } +- +- lines += processedOldLines + processedNewLines; +- lines += that._processLines(file.isCombined, oldLines.slice(common), newLines.slice(common)); +- }); +- +- oldLines = []; +- newLines = []; +- } +- +- for (var i = 0; i < block.lines.length; i++) { +- var line = block.lines[i]; +- var escapedLine = utils.escape(line.content); +- +- if (line.type !== diffParser.LINE_TYPE.INSERTS && +- (newLines.length > 0 || (line.type !== diffParser.LINE_TYPE.DELETES && oldLines.length > 0))) { +- processChangeBlock(); +- } +- +- if (line.type === diffParser.LINE_TYPE.CONTEXT) { +- lines += that.makeLineHtml(file.isCombined, line.type, line.oldNumber, line.newNumber, escapedLine); +- } else if (line.type === diffParser.LINE_TYPE.INSERTS && !oldLines.length) { +- lines += that.makeLineHtml(file.isCombined, line.type, line.oldNumber, line.newNumber, escapedLine); +- } else if (line.type === diffParser.LINE_TYPE.DELETES) { +- oldLines.push(line); +- } else if (line.type === diffParser.LINE_TYPE.INSERTS && Boolean(oldLines.length)) { +- newLines.push(line); +- } else { +- console.error('Unknown state in html line-by-line generator'); +- processChangeBlock(); +- } +- } +- +- processChangeBlock(); +- +- return lines; +- }).join('\n'); +- }; +- +- LineByLinePrinter.prototype._processLines = function(isCombined, oldLines, newLines) { +- var lines = ''; +- +- for (var i = 0; i < oldLines.length; i++) { +- var oldLine = oldLines[i]; +- var oldEscapedLine = utils.escape(oldLine.content); +- lines += this.makeLineHtml(isCombined, oldLine.type, oldLine.oldNumber, oldLine.newNumber, oldEscapedLine); +- } +- +- for (var j = 0; j < newLines.length; j++) { +- var newLine = newLines[j]; +- var newEscapedLine = utils.escape(newLine.content); +- lines += this.makeLineHtml(isCombined, newLine.type, newLine.oldNumber, newLine.newNumber, newEscapedLine); +- } +- +- return lines; +- }; +- +- LineByLinePrinter.prototype.makeLineHtml = function(isCombined, type, oldNumber, newNumber, content, possiblePrefix) { +- var lineNumberTemplate = hoganUtils.render(baseTemplatesPath, 'numbers', { +- oldNumber: utils.valueOrEmpty(oldNumber), +- newNumber: utils.valueOrEmpty(newNumber) +- }); +- +- var lineWithoutPrefix = content; +- var prefix = possiblePrefix; +- +- if (!prefix) { +- var lineWithPrefix = printerUtils.separatePrefix(isCombined, content); +- prefix = lineWithPrefix.prefix; +- lineWithoutPrefix = lineWithPrefix.line; +- } +- +- if (prefix === ' ') { +- prefix = ' '; +- } +- +- return hoganUtils.render(genericTemplatesPath, 'line', +- { +- type: type, +- lineClass: 'd2h-code-linenumber', +- contentClass: 'd2h-code-line', +- prefix: prefix, +- content: lineWithoutPrefix, +- lineNumber: lineNumberTemplate +- }); +- }; +- +- LineByLinePrinter.prototype._generateEmptyDiff = function() { +- return hoganUtils.render(genericTemplatesPath, 'empty-diff', { +- contentClass: 'd2h-code-line', +- diffParser: diffParser +- }); +- }; +- +- module.exports.LineByLinePrinter = LineByLinePrinter; +-})(); +diff --git a/src/line-by-line-renderer.ts b/src/line-by-line-renderer.ts +new file mode 100644 +index 00000000..02fd731f +--- /dev/null ++++ b/src/line-by-line-renderer.ts +@@ -0,0 +1,296 @@ ++import HoganJsUtils from "./hoganjs-utils"; ++import * as Rematch from "./rematch"; ++import * as renderUtils from "./render-utils"; ++import { ++ DiffFile, ++ DiffLine, ++ LineType, ++ DiffBlock, ++ DiffLineDeleted, ++ DiffLineContent, ++ DiffLineContext, ++ DiffLineInserted ++} from "./types"; ++ ++export interface LineByLineRendererConfig extends renderUtils.RenderConfig { ++ renderNothingWhenEmpty?: boolean; ++ matchingMaxComparisons?: number; ++ maxLineSizeInBlockForComparison?: number; ++} ++ ++export const defaultLineByLineRendererConfig = { ++ ...renderUtils.defaultRenderConfig, ++ renderNothingWhenEmpty: false, ++ matchingMaxComparisons: 2500, ++ maxLineSizeInBlockForComparison: 200 ++}; ++ ++const genericTemplatesPath = "generic"; ++const baseTemplatesPath = "line-by-line"; ++const iconsBaseTemplatesPath = "icon"; ++const tagsBaseTemplatesPath = "tag"; ++ ++export default class LineByLineRenderer { ++ private readonly hoganUtils: HoganJsUtils; ++ private readonly config: typeof defaultLineByLineRendererConfig; ++ ++ constructor(hoganUtils: HoganJsUtils, config: LineByLineRendererConfig = {}) { ++ this.hoganUtils = hoganUtils; ++ this.config = { ...defaultLineByLineRendererConfig, ...config }; ++ } ++ ++ render(diffFiles: DiffFile[]): string { ++ const diffsHtml = diffFiles ++ .map(file => { ++ let diffs; ++ if (file.blocks.length) { ++ diffs = this.generateFileHtml(file); ++ } else { ++ diffs = this.generateEmptyDiff(); ++ } ++ return this.makeFileDiffHtml(file, diffs); ++ }) ++ .join("\n"); ++ ++ return this.hoganUtils.render(genericTemplatesPath, "wrapper", { content: diffsHtml }); ++ } ++ ++ makeFileDiffHtml(file: DiffFile, diffs: string): string { ++ if (this.config.renderNothingWhenEmpty && Array.isArray(file.blocks) && file.blocks.length === 0) return ""; ++ ++ const fileDiffTemplate = this.hoganUtils.template(baseTemplatesPath, "file-diff"); ++ const filePathTemplate = this.hoganUtils.template(genericTemplatesPath, "file-path"); ++ const fileIconTemplate = this.hoganUtils.template(iconsBaseTemplatesPath, "file"); ++ const fileTagTemplate = this.hoganUtils.template(tagsBaseTemplatesPath, renderUtils.getFileIcon(file)); ++ ++ return fileDiffTemplate.render({ ++ file: file, ++ fileHtmlId: renderUtils.getHtmlId(file), ++ diffs: diffs, ++ filePath: filePathTemplate.render( ++ { ++ fileDiffName: renderUtils.filenameDiff(file) ++ }, ++ { ++ fileIcon: fileIconTemplate, ++ fileTag: fileTagTemplate ++ } ++ ) ++ }); ++ } ++ ++ generateEmptyDiff(): string { ++ return this.hoganUtils.render(genericTemplatesPath, "empty-diff", { ++ contentClass: "d2h-code-line", ++ CSSLineClass: renderUtils.CSSLineClass ++ }); ++ } ++ ++ generateFileHtml(file: DiffFile): string { ++ const matcher = Rematch.newMatcherFn( ++ Rematch.newDistanceFn((e: DiffLine) => renderUtils.deconstructLine(e.content, file.isCombined).content) ++ ); ++ ++ return file.blocks ++ .map(block => { ++ let lines = this.hoganUtils.render(genericTemplatesPath, "block-header", { ++ CSSLineClass: renderUtils.CSSLineClass, ++ blockHeader: block.header, ++ lineClass: "d2h-code-linenumber", ++ contentClass: "d2h-code-line" ++ }); ++ ++ this.applyLineGroupping(block).forEach(([contextLines, oldLines, newLines]) => { ++ if (oldLines.length && newLines.length && !contextLines.length) { ++ this.applyRematchMatching(oldLines, newLines, matcher).map(([oldLines, newLines]) => { ++ const { left, right } = this.processChangedLines(file.isCombined, oldLines, newLines); ++ lines += left; ++ lines += right; ++ }); ++ } else if (contextLines.length) { ++ contextLines.forEach(line => { ++ const { prefix, content } = renderUtils.deconstructLine(line.content, file.isCombined); ++ lines += this.generateSingleLineHtml({ ++ type: renderUtils.CSSLineClass.CONTEXT, ++ prefix: prefix, ++ content: content, ++ oldNumber: line.oldNumber, ++ newNumber: line.newNumber ++ }); ++ }); ++ } else if (oldLines.length || newLines.length) { ++ const { left, right } = this.processChangedLines(file.isCombined, oldLines, newLines); ++ lines += left; ++ lines += right; ++ } else { ++ console.error("Unknown state reached while processing groups of lines", contextLines, oldLines, newLines); ++ } ++ }); ++ ++ return lines; ++ }) ++ .join("\n"); ++ } ++ ++ applyLineGroupping(block: DiffBlock): DiffLineGroups { ++ const blockLinesGroups: DiffLineGroups = []; ++ ++ let oldLines: (DiffLineDeleted & DiffLineContent)[] = []; ++ let newLines: (DiffLineInserted & DiffLineContent)[] = []; ++ ++ for (let i = 0; i < block.lines.length; i++) { ++ const diffLine = block.lines[i]; ++ ++ if ( ++ (diffLine.type !== LineType.INSERT && newLines.length) || ++ (diffLine.type === LineType.CONTEXT && oldLines.length > 0) ++ ) { ++ blockLinesGroups.push([[], oldLines, newLines]); ++ oldLines = []; ++ newLines = []; ++ } ++ ++ if (diffLine.type === LineType.CONTEXT) { ++ blockLinesGroups.push([[diffLine], [], []]); ++ } else if (diffLine.type === LineType.INSERT && oldLines.length === 0) { ++ blockLinesGroups.push([[], [], [diffLine]]); ++ } else if (diffLine.type === LineType.INSERT && oldLines.length > 0) { ++ newLines.push(diffLine); ++ } else if (diffLine.type === LineType.DELETE) { ++ oldLines.push(diffLine); ++ } ++ } ++ ++ if (oldLines.length || newLines.length) { ++ blockLinesGroups.push([[], oldLines, newLines]); ++ oldLines = []; ++ newLines = []; ++ } ++ ++ return blockLinesGroups; ++ } ++ ++ applyRematchMatching( ++ oldLines: DiffLine[], ++ newLines: DiffLine[], ++ matcher: Rematch.MatcherFn ++ ): DiffLine[][][] { ++ const comparisons = oldLines.length * newLines.length; ++ const maxLineSizeInBlock = Math.max.apply( ++ null, ++ [0].concat(oldLines.concat(newLines).map(elem => elem.content.length)) ++ ); ++ const doMatching = ++ comparisons < this.config.matchingMaxComparisons && ++ maxLineSizeInBlock < this.config.maxLineSizeInBlockForComparison && ++ (this.config.matching === "lines" || this.config.matching === "words"); ++ ++ const matches = doMatching ? matcher(oldLines, newLines) : [[oldLines, newLines]]; ++ ++ return matches; ++ } ++ ++ processChangedLines(isCombined: boolean, oldLines: DiffLine[], newLines: DiffLine[]): FileHtml { ++ const fileHtml = { ++ right: "", ++ left: "" ++ }; ++ ++ const maxLinesNumber = Math.max(oldLines.length, newLines.length); ++ for (let i = 0; i < maxLinesNumber; i++) { ++ const oldLine = oldLines[i]; ++ const newLine = newLines[i]; ++ ++ const diff = ++ oldLine !== undefined && newLine !== undefined ++ ? renderUtils.diffHighlight(oldLine.content, newLine.content, isCombined, this.config) ++ : undefined; ++ ++ const preparedOldLine = ++ oldLine !== undefined && oldLine.oldNumber !== undefined ++ ? { ++ ...(diff !== undefined ++ ? { ++ prefix: diff.oldLine.prefix, ++ content: diff.oldLine.content, ++ type: renderUtils.CSSLineClass.DELETE_CHANGES ++ } ++ : { ++ ...renderUtils.deconstructLine(oldLine.content, isCombined), ++ type: renderUtils.toCSSClass(oldLine.type) ++ }), ++ oldNumber: oldLine.oldNumber, ++ newNumber: oldLine.newNumber ++ } ++ : undefined; ++ ++ const preparedNewLine = ++ newLine !== undefined && newLine.newNumber !== undefined ++ ? { ++ ...(diff !== undefined ++ ? { ++ prefix: diff.newLine.prefix, ++ content: diff.newLine.content, ++ type: renderUtils.CSSLineClass.INSERT_CHANGES ++ } ++ : { ++ ...renderUtils.deconstructLine(newLine.content, isCombined), ++ type: renderUtils.toCSSClass(newLine.type) ++ }), ++ oldNumber: newLine.oldNumber, ++ newNumber: newLine.newNumber ++ } ++ : undefined; ++ ++ const { left, right } = this.generateLineHtml(preparedOldLine, preparedNewLine); ++ fileHtml.left += left; ++ fileHtml.right += right; ++ } ++ ++ return fileHtml; ++ } ++ ++ generateLineHtml(oldLine?: DiffPreparedLine, newLine?: DiffPreparedLine): FileHtml { ++ return { ++ left: this.generateSingleLineHtml(oldLine), ++ right: this.generateSingleLineHtml(newLine) ++ }; ++ } ++ ++ generateSingleLineHtml(line?: DiffPreparedLine): string { ++ if (line === undefined) return ""; ++ ++ const lineNumberHtml = this.hoganUtils.render(baseTemplatesPath, "numbers", { ++ oldNumber: line.oldNumber || "", ++ newNumber: line.newNumber || "" ++ }); ++ ++ return this.hoganUtils.render(genericTemplatesPath, "line", { ++ type: line.type, ++ lineClass: "d2h-code-linenumber", ++ contentClass: "d2h-code-line", ++ prefix: line.prefix === " " ? " " : line.prefix, ++ content: line.content, ++ lineNumber: lineNumberHtml ++ }); ++ } ++} ++ ++type DiffLineGroups = [ ++ (DiffLineContext & DiffLineContent)[], ++ (DiffLineDeleted & DiffLineContent)[], ++ (DiffLineInserted & DiffLineContent)[] ++][]; ++ ++type DiffPreparedLine = { ++ type: renderUtils.CSSLineClass; ++ prefix: string; ++ content: string; ++ oldNumber?: number; ++ newNumber?: number; ++}; ++ ++type FileHtml = { ++ left: string; ++ right: string; ++}; +diff --git a/src/printer-utils.js b/src/printer-utils.js +deleted file mode 100644 +index d4a61be7..00000000 +--- a/src/printer-utils.js ++++ /dev/null +@@ -1,250 +0,0 @@ +-/* +- * +- * PrinterUtils (printer-utils.js) +- * Author: rtfpessoa +- * +- */ +- +-(function() { +- var jsDiff = require('diff'); +- var utils = require('./utils.js').Utils; +- var Rematch = require('./rematch.js').Rematch; +- +- var separator = '/'; +- +- function PrinterUtils() { +- } +- +- PrinterUtils.prototype.separatePrefix = function(isCombined, line) { +- var prefix; +- var lineWithoutPrefix; +- +- if (isCombined) { +- prefix = line.substring(0, 2); +- lineWithoutPrefix = line.substring(2); +- } else { +- prefix = line.substring(0, 1); +- lineWithoutPrefix = line.substring(1); +- } +- +- return { +- 'prefix': prefix, +- 'line': lineWithoutPrefix +- }; +- }; +- +- PrinterUtils.prototype.getHtmlId = function(file) { +- var hashCode = function(text) { +- var i, chr, len; +- var hash = 0; +- +- for (i = 0, len = text.length; i < len; i++) { +- chr = text.charCodeAt(i); +- hash = ((hash << 5) - hash) + chr; +- hash |= 0; // Convert to 32bit integer +- } +- +- return hash; +- }; +- +- return 'd2h-' + hashCode(this.getDiffName(file)).toString().slice(-6); +- }; +- +- PrinterUtils.prototype.getDiffName = function(file) { +- var oldFilename = unifyPath(file.oldName); +- var newFilename = unifyPath(file.newName); +- +- if (oldFilename && newFilename && oldFilename !== newFilename && !isDevNullName(oldFilename) && !isDevNullName(newFilename)) { +- var prefixPaths = []; +- var suffixPaths = []; +- +- var oldFilenameParts = oldFilename.split(separator); +- var newFilenameParts = newFilename.split(separator); +- +- var oldFilenamePartsSize = oldFilenameParts.length; +- var newFilenamePartsSize = newFilenameParts.length; +- +- var i = 0; +- var j = oldFilenamePartsSize - 1; +- var k = newFilenamePartsSize - 1; +- +- while (i < j && i < k) { +- if (oldFilenameParts[i] === newFilenameParts[i]) { +- prefixPaths.push(newFilenameParts[i]); +- i += 1; +- } else { +- break; +- } +- } +- +- while (j > i && k > i) { +- if (oldFilenameParts[j] === newFilenameParts[k]) { +- suffixPaths.unshift(newFilenameParts[k]); +- j -= 1; +- k -= 1; +- } else { +- break; +- } +- } +- +- var finalPrefix = prefixPaths.join(separator); +- var finalSuffix = suffixPaths.join(separator); +- +- var oldRemainingPath = oldFilenameParts.slice(i, j + 1).join(separator); +- var newRemainingPath = newFilenameParts.slice(i, k + 1).join(separator); +- +- if (finalPrefix.length && finalSuffix.length) { +- return finalPrefix + separator + '{' + oldRemainingPath + ' → ' + newRemainingPath + '}' + separator + finalSuffix; +- } else if (finalPrefix.length) { +- return finalPrefix + separator + '{' + oldRemainingPath + ' → ' + newRemainingPath + '}'; +- } else if (finalSuffix.length) { +- return '{' + oldRemainingPath + ' → ' + newRemainingPath + '}' + separator + finalSuffix; +- } +- +- return oldFilename + ' → ' + newFilename; +- } else if (newFilename && !isDevNullName(newFilename)) { +- return newFilename; +- } else if (oldFilename) { +- return oldFilename; +- } +- +- return 'unknown/file/path'; +- }; +- +- PrinterUtils.prototype.getFileTypeIcon = function(file) { +- var templateName = 'file-changed'; +- +- if (file.isRename) { +- templateName = 'file-renamed'; +- } else if (file.isCopy) { +- templateName = 'file-renamed'; +- } else if (file.isNew) { +- templateName = 'file-added'; +- } else if (file.isDeleted) { +- templateName = 'file-deleted'; +- } else if (file.newName !== file.oldName) { +- // If file is not Added, not Deleted and the names changed it must be a rename :) +- templateName = 'file-renamed'; +- } +- +- return templateName; +- }; +- +- PrinterUtils.prototype.diffHighlight = function(diffLine1, diffLine2, config) { +- var linePrefix1, linePrefix2, unprefixedLine1, unprefixedLine2; +- +- var prefixSize = 1; +- +- if (config.isCombined) { +- prefixSize = 2; +- } +- +- linePrefix1 = diffLine1.substr(0, prefixSize); +- linePrefix2 = diffLine2.substr(0, prefixSize); +- unprefixedLine1 = diffLine1.substr(prefixSize); +- unprefixedLine2 = diffLine2.substr(prefixSize); +- +- if (unprefixedLine1.length > config.maxLineLengthHighlight || +- unprefixedLine2.length > config.maxLineLengthHighlight) { +- return { +- first: { +- prefix: linePrefix1, +- line: utils.escape(unprefixedLine1) +- }, +- second: { +- prefix: linePrefix2, +- line: utils.escape(unprefixedLine2) +- } +- }; +- } +- +- var diff; +- if (config.diffStyle === 'char') { +- diff = jsDiff.diffChars(unprefixedLine1, unprefixedLine2); +- } else { +- diff = jsDiff.diffWordsWithSpace(unprefixedLine1, unprefixedLine2); +- } +- +- var highlightedLine = ''; +- +- var changedWords = []; +- if (config.diffStyle === 'word' && config.matching === 'words') { +- var treshold = 0.25; +- +- if (typeof (config.matchWordsThreshold) !== 'undefined') { +- treshold = config.matchWordsThreshold; +- } +- +- var matcher = Rematch.rematch(function(a, b) { +- var amod = a.value; +- var bmod = b.value; +- +- return Rematch.distance(amod, bmod); +- }); +- +- var removed = diff.filter(function isRemoved(element) { +- return element.removed; +- }); +- +- var added = diff.filter(function isAdded(element) { +- return element.added; +- }); +- +- var chunks = matcher(added, removed); +- chunks.forEach(function(chunk) { +- if (chunk[0].length === 1 && chunk[1].length === 1) { +- var dist = Rematch.distance(chunk[0][0].value, chunk[1][0].value); +- if (dist < treshold) { +- changedWords.push(chunk[0][0]); +- changedWords.push(chunk[1][0]); +- } +- } +- }); +- } +- +- diff.forEach(function(part) { +- var addClass = changedWords.indexOf(part) > -1 ? ' class="d2h-change"' : ''; +- var elemType = part.added ? 'ins' : part.removed ? 'del' : null; +- var escapedValue = utils.escape(part.value); +- +- if (elemType !== null) { +- highlightedLine += '<' + elemType + addClass + '>' + escapedValue + ''; +- } else { +- highlightedLine += escapedValue; +- } +- }); +- +- return { +- first: { +- prefix: linePrefix1, +- line: removeIns(highlightedLine) +- }, +- second: { +- prefix: linePrefix2, +- line: removeDel(highlightedLine) +- } +- }; +- }; +- +- function unifyPath(path) { +- if (path) { +- return path.replace('\\', '/'); +- } +- +- return path; +- } +- +- function isDevNullName(name) { +- return name.indexOf('dev/null') !== -1; +- } +- +- function removeIns(line) { +- return line.replace(/(]*>((.|\n)*?)<\/ins>)/g, ''); +- } +- +- function removeDel(line) { +- return line.replace(/(]*>((.|\n)*?)<\/del>)/g, ''); +- } +- +- module.exports.PrinterUtils = new PrinterUtils(); +-})(); +diff --git a/src/rematch.js b/src/rematch.js +deleted file mode 100644 +index bad56659..00000000 +--- a/src/rematch.js ++++ /dev/null +@@ -1,141 +0,0 @@ +-/* +- * +- * Rematch (rematch.js) +- * Matching two sequences of objects by similarity +- * Author: W. Illmeyer, Nexxar GmbH +- * +- */ +- +-(function() { +- var Rematch = {}; +- +- /* +- Copyright (c) 2011 Andrei Mackenzie +- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +- documentation files (the "Software"), to deal in the Software without restriction, including without limitation +- the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +- and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +- THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +- */ +- function levenshtein(a, b) { +- if (a.length === 0) { +- return b.length; +- } +- if (b.length === 0) { +- return a.length; +- } +- +- var matrix = []; +- +- // Increment along the first column of each row +- var i; +- for (i = 0; i <= b.length; i++) { +- matrix[i] = [i]; +- } +- +- // Increment each column in the first row +- var j; +- for (j = 0; j <= a.length; j++) { +- matrix[0][j] = j; +- } +- +- // Fill in the rest of the matrix +- for (i = 1; i <= b.length; i++) { +- for (j = 1; j <= a.length; j++) { +- if (b.charAt(i - 1) === a.charAt(j - 1)) { +- matrix[i][j] = matrix[i - 1][j - 1]; +- } else { +- matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // Substitution +- Math.min(matrix[i][j - 1] + 1, // Insertion +- matrix[i - 1][j] + 1)); // Deletion +- } +- } +- } +- +- return matrix[b.length][a.length]; +- } +- +- Rematch.levenshtein = levenshtein; +- +- Rematch.distance = function distance(x, y) { +- x = x.trim(); +- y = y.trim(); +- var lev = levenshtein(x, y); +- var score = lev / (x.length + y.length); +- +- return score; +- }; +- +- Rematch.rematch = function rematch(distanceFunction) { +- function findBestMatch(a, b, cache) { +- var bestMatchDist = Infinity; +- var bestMatch; +- for (var i = 0; i < a.length; ++i) { +- for (var j = 0; j < b.length; ++j) { +- var cacheKey = JSON.stringify([a[i], b[j]]); +- var md; +- if (cache.hasOwnProperty(cacheKey)) { +- md = cache[cacheKey]; +- } else { +- md = distanceFunction(a[i], b[j]); +- cache[cacheKey] = md; +- } +- if (md < bestMatchDist) { +- bestMatchDist = md; +- bestMatch = {indexA: i, indexB: j, score: bestMatchDist}; +- } +- } +- } +- +- return bestMatch; +- } +- +- function group(a, b, level, cache) { +- if (typeof (cache) === 'undefined') { +- cache = {}; +- } +- +- var bm = findBestMatch(a, b, cache); +- +- if (!level) { +- level = 0; +- } +- +- if (!bm || (a.length + b.length < 3)) { +- return [[a, b]]; +- } +- +- var a1 = a.slice(0, bm.indexA); +- var b1 = b.slice(0, bm.indexB); +- var aMatch = [a[bm.indexA]]; +- var bMatch = [b[bm.indexB]]; +- var tailA = bm.indexA + 1; +- var tailB = bm.indexB + 1; +- var a2 = a.slice(tailA); +- var b2 = b.slice(tailB); +- +- var group1 = group(a1, b1, level + 1, cache); +- var groupMatch = group(aMatch, bMatch, level + 1, cache); +- var group2 = group(a2, b2, level + 1, cache); +- var result = groupMatch; +- +- if (bm.indexA > 0 || bm.indexB > 0) { +- result = group1.concat(result); +- } +- +- if (a.length > tailA || b.length > tailB) { +- result = result.concat(group2); +- } +- +- return result; +- } +- +- return group; +- }; +- +- module.exports.Rematch = Rematch; +-})(); +diff --git a/src/rematch.ts b/src/rematch.ts +new file mode 100644 +index 00000000..5e7ea3b6 +--- /dev/null ++++ b/src/rematch.ts +@@ -0,0 +1,137 @@ ++/* ++ * Matching two sequences of objects by similarity ++ * Author: W. Illmeyer, Nexxar GmbH ++ */ ++ ++export type BestMatch = { ++ indexA: number; ++ indexB: number; ++ score: number; ++}; ++ ++/* ++ Copyright (c) 2011 Andrei Mackenzie ++ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated ++ documentation files (the "Software"), to deal in the Software without restriction, including without limitation ++ the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, ++ and to permit persons to whom the Software is furnished to do so, subject to the following conditions: ++ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ++ THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ++ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++export function levenshtein(a: string, b: string): number { ++ if (a.length === 0) { ++ return b.length; ++ } ++ if (b.length === 0) { ++ return a.length; ++ } ++ ++ const matrix = []; ++ ++ // Increment along the first column of each row ++ let i; ++ for (i = 0; i <= b.length; i++) { ++ matrix[i] = [i]; ++ } ++ ++ // Increment each column in the first row ++ let j; ++ for (j = 0; j <= a.length; j++) { ++ matrix[0][j] = j; ++ } ++ ++ // Fill in the rest of the matrix ++ for (i = 1; i <= b.length; i++) { ++ for (j = 1; j <= a.length; j++) { ++ if (b.charAt(i - 1) === a.charAt(j - 1)) { ++ matrix[i][j] = matrix[i - 1][j - 1]; ++ } else { ++ matrix[i][j] = Math.min( ++ matrix[i - 1][j - 1] + 1, // Substitution ++ Math.min( ++ matrix[i][j - 1] + 1, // Insertion ++ matrix[i - 1][j] + 1 ++ ) ++ ); // Deletion ++ } ++ } ++ } ++ ++ return matrix[b.length][a.length]; ++} ++ ++export type DistanceFn = (x: T, y: T) => number; ++ ++export function newDistanceFn(str: (value: T) => string): DistanceFn { ++ return (x: T, y: T): number => { ++ const xValue = str(x).trim(); ++ const yValue = str(y).trim(); ++ const lev = levenshtein(xValue, yValue); ++ const score = lev / (xValue.length + yValue.length); ++ ++ return score; ++ }; ++} ++ ++export type MatcherFn = (a: T[], b: T[], level?: number, cache?: Map) => T[][][]; ++ ++export function newMatcherFn(distance: (x: T, y: T) => number): MatcherFn { ++ function findBestMatch(a: T[], b: T[], cache: Map = new Map()): BestMatch | undefined { ++ let bestMatchDist = Infinity; ++ let bestMatch; ++ ++ for (let i = 0; i < a.length; ++i) { ++ for (let j = 0; j < b.length; ++j) { ++ const cacheKey = JSON.stringify([a[i], b[j]]); ++ let md; ++ if (!(cache.has(cacheKey) && (md = cache.get(cacheKey)))) { ++ md = distance(a[i], b[j]); ++ cache.set(cacheKey, md); ++ } ++ if (md < bestMatchDist) { ++ bestMatchDist = md; ++ bestMatch = { indexA: i, indexB: j, score: bestMatchDist }; ++ } ++ } ++ } ++ ++ return bestMatch; ++ } ++ ++ function group(a: T[], b: T[], level = 0, cache: Map = new Map()): T[][][] { ++ const bm = findBestMatch(a, b, cache); ++ ++ if (!bm || a.length + b.length < 3) { ++ return [[a, b]]; ++ } ++ ++ const a1 = a.slice(0, bm.indexA); ++ const b1 = b.slice(0, bm.indexB); ++ const aMatch = [a[bm.indexA]]; ++ const bMatch = [b[bm.indexB]]; ++ const tailA = bm.indexA + 1; ++ const tailB = bm.indexB + 1; ++ const a2 = a.slice(tailA); ++ const b2 = b.slice(tailB); ++ ++ const group1 = group(a1, b1, level + 1, cache); ++ const groupMatch = group(aMatch, bMatch, level + 1, cache); ++ const group2 = group(a2, b2, level + 1, cache); ++ let result = groupMatch; ++ ++ if (bm.indexA > 0 || bm.indexB > 0) { ++ result = group1.concat(result); ++ } ++ ++ if (a.length > tailA || b.length > tailB) { ++ result = result.concat(group2); ++ } ++ ++ return result; ++ } ++ ++ return group; ++} +diff --git a/src/render-utils.ts b/src/render-utils.ts +new file mode 100644 +index 00000000..73a1c603 +--- /dev/null ++++ b/src/render-utils.ts +@@ -0,0 +1,275 @@ ++import * as jsDiff from "diff"; ++ ++import { unifyPath, hashCode } from "./utils"; ++import * as rematch from "./rematch"; ++import { LineMatchingType, DiffStyleType, LineType, DiffLineParts, DiffFile, DiffFileName } from "./types"; ++ ++export enum CSSLineClass { ++ INSERTS = "d2h-ins", ++ DELETES = "d2h-del", ++ CONTEXT = "d2h-cntx", ++ INFO = "d2h-info", ++ INSERT_CHANGES = "d2h-ins d2h-change", ++ DELETE_CHANGES = "d2h-del d2h-change" ++} ++ ++export type HighlightedLines = { ++ oldLine: { ++ prefix: string; ++ content: string; ++ }; ++ newLine: { ++ prefix: string; ++ content: string; ++ }; ++}; ++ ++export interface RenderConfig { ++ matching?: LineMatchingType; ++ matchWordsThreshold?: number; ++ maxLineLengthHighlight?: number; ++ diffStyle?: DiffStyleType; ++} ++ ++export const defaultRenderConfig = { ++ matching: LineMatchingType.NONE, ++ matchWordsThreshold: 0.25, ++ maxLineLengthHighlight: 10000, ++ diffStyle: DiffStyleType.WORD ++}; ++ ++const separator = "/"; ++const distance = rematch.newDistanceFn((change: jsDiff.Change) => change.value); ++const matcher = rematch.newMatcherFn(distance); ++ ++function isDevNullName(name: string): boolean { ++ return name.indexOf("dev/null") !== -1; ++} ++ ++function removeInsElements(line: string): string { ++ return line.replace(/(]*>((.|\n)*?)<\/ins>)/g, ""); ++} ++ ++function removeDelElements(line: string): string { ++ return line.replace(/(]*>((.|\n)*?)<\/del>)/g, ""); ++} ++ ++/** ++ * Convert from LineType to CSSLineClass ++ */ ++export function toCSSClass(lineType: LineType): CSSLineClass { ++ switch (lineType) { ++ case LineType.CONTEXT: ++ return CSSLineClass.CONTEXT; ++ case LineType.INSERT: ++ return CSSLineClass.INSERTS; ++ case LineType.DELETE: ++ return CSSLineClass.DELETES; ++ } ++} ++ ++/** ++ * Prefix length of the hunk lines in the diff ++ */ ++function prefixLength(isCombined: boolean): number { ++ return isCombined ? 2 : 1; ++} ++ ++/** ++ * Escapes all required characters for safe HTML rendering ++ */ ++// TODO: Test this method inside deconstructLine since it should not be used anywhere else ++export function escapeForHtml(str: string): string { ++ return str ++ .slice(0) ++ .replace(/&/g, "&") ++ .replace(//g, ">") ++ .replace(/"/g, """) ++ .replace(/'/g, "'") ++ .replace(/\//g, "/"); ++} ++ ++/** ++ * Deconstructs diff @line by separating the content from the prefix type ++ */ ++export function deconstructLine(line: string, isCombined: boolean): DiffLineParts { ++ const indexToSplit = prefixLength(isCombined); ++ return { ++ prefix: line.substring(0, indexToSplit), ++ content: escapeForHtml(line.substring(indexToSplit)) ++ }; ++} ++ ++/** ++ * Generates pretty filename diffs ++ * ++ * e.g.: ++ * 1. file = { oldName: "my/path/to/file.js", newName: "my/path/to/new-file.js" } ++ * returns "my/path/to/{file.js → new-file.js}" ++ * 2. file = { oldName: "my/path/to/file.js", newName: "very/new/path/to/new-file.js" } ++ * returns "my/path/to/file.js → very/new/path/to/new-file.js" ++ * 3. file = { oldName: "my/path/to/file.js", newName: "my/path/for/file.js" } ++ * returns "my/path/{to → for}/file.js" ++ */ ++export function filenameDiff(file: DiffFileName): string { ++ // TODO: Move unify path to parsing ++ const oldFilename = unifyPath(file.oldName); ++ const newFilename = unifyPath(file.newName); ++ ++ if (oldFilename !== newFilename && !isDevNullName(oldFilename) && !isDevNullName(newFilename)) { ++ const prefixPaths = []; ++ const suffixPaths = []; ++ ++ const oldFilenameParts = oldFilename.split(separator); ++ const newFilenameParts = newFilename.split(separator); ++ ++ const oldFilenamePartsSize = oldFilenameParts.length; ++ const newFilenamePartsSize = newFilenameParts.length; ++ ++ let i = 0; ++ let j = oldFilenamePartsSize - 1; ++ let k = newFilenamePartsSize - 1; ++ ++ while (i < j && i < k) { ++ if (oldFilenameParts[i] === newFilenameParts[i]) { ++ prefixPaths.push(newFilenameParts[i]); ++ i += 1; ++ } else { ++ break; ++ } ++ } ++ ++ while (j > i && k > i) { ++ if (oldFilenameParts[j] === newFilenameParts[k]) { ++ suffixPaths.unshift(newFilenameParts[k]); ++ j -= 1; ++ k -= 1; ++ } else { ++ break; ++ } ++ } ++ ++ const finalPrefix = prefixPaths.join(separator); ++ const finalSuffix = suffixPaths.join(separator); ++ ++ const oldRemainingPath = oldFilenameParts.slice(i, j + 1).join(separator); ++ const newRemainingPath = newFilenameParts.slice(i, k + 1).join(separator); ++ ++ if (finalPrefix.length && finalSuffix.length) { ++ return ( ++ finalPrefix + separator + "{" + oldRemainingPath + " → " + newRemainingPath + "}" + separator + finalSuffix ++ ); ++ } else if (finalPrefix.length) { ++ return finalPrefix + separator + "{" + oldRemainingPath + " → " + newRemainingPath + "}"; ++ } else if (finalSuffix.length) { ++ return "{" + oldRemainingPath + " → " + newRemainingPath + "}" + separator + finalSuffix; ++ } ++ ++ return oldFilename + " → " + newFilename; ++ } else if (!isDevNullName(newFilename)) { ++ return newFilename; ++ } else { ++ return oldFilename; ++ } ++} ++ ++/** ++ * Generates a unique string numerical identifier based on the names of the file diff ++ */ ++export function getHtmlId(file: DiffFileName): string { ++ return `d2h-${hashCode(filenameDiff(file)) ++ .toString() ++ .slice(-6)}`; ++} ++ ++/** ++ * Selects the correct icon name for the file ++ */ ++export function getFileIcon(file: DiffFile): string { ++ let templateName = "file-changed"; ++ ++ if (file.isRename) { ++ templateName = "file-renamed"; ++ } else if (file.isCopy) { ++ templateName = "file-renamed"; ++ } else if (file.isNew) { ++ templateName = "file-added"; ++ } else if (file.isDeleted) { ++ templateName = "file-deleted"; ++ } else if (file.newName !== file.oldName) { ++ // If file is not Added, not Deleted and the names changed it must be a rename :) ++ templateName = "file-renamed"; ++ } ++ ++ return templateName; ++} ++ ++/** ++ * Highlight differences between @diffLine1 and @diffLine2 using and tags ++ */ ++export function diffHighlight( ++ diffLine1: string, ++ diffLine2: string, ++ isCombined: boolean, ++ config: RenderConfig = {} ++): HighlightedLines { ++ const { matching, maxLineLengthHighlight, matchWordsThreshold, diffStyle } = { ...defaultRenderConfig, ...config }; ++ ++ const line1 = deconstructLine(diffLine1, isCombined); ++ const line2 = deconstructLine(diffLine2, isCombined); ++ ++ if (line1.content.length > maxLineLengthHighlight || line2.content.length > maxLineLengthHighlight) { ++ return { ++ oldLine: { ++ prefix: line1.prefix, ++ content: line1.content ++ }, ++ newLine: { ++ prefix: line2.prefix, ++ content: line2.content ++ } ++ }; ++ } ++ ++ const diff = ++ diffStyle === "char" ++ ? jsDiff.diffChars(line1.content, line2.content) ++ : jsDiff.diffWordsWithSpace(line1.content, line2.content); ++ ++ const changedWords: jsDiff.Change[] = []; ++ if (diffStyle === "word" && matching === "words") { ++ const removed = diff.filter(element => element.removed); ++ const added = diff.filter(element => element.added); ++ const chunks = matcher(added, removed); ++ chunks.forEach(chunk => { ++ if (chunk[0].length === 1 && chunk[1].length === 1) { ++ const dist = distance(chunk[0][0], chunk[1][0]); ++ if (dist < matchWordsThreshold) { ++ changedWords.push(chunk[0][0]); ++ changedWords.push(chunk[1][0]); ++ } ++ } ++ }); ++ } ++ ++ const highlightedLine = diff.reduce((highlightedLine, part) => { ++ const elemType = part.added ? "ins" : part.removed ? "del" : null; ++ const addClass = changedWords.indexOf(part) > -1 ? ' class="d2h-change"' : ""; ++ ++ return elemType !== null ++ ? `${highlightedLine}<${elemType}${addClass}>${part.value}` ++ : `${highlightedLine}${part.value}`; ++ }, ""); ++ ++ return { ++ oldLine: { ++ prefix: line1.prefix, ++ content: removeInsElements(highlightedLine) ++ }, ++ newLine: { ++ prefix: line2.prefix, ++ content: removeDelElements(highlightedLine) ++ } ++ }; ++} +diff --git a/src/side-by-side-printer.js b/src/side-by-side-printer.js +deleted file mode 100644 +index 91fb84b7..00000000 +--- a/src/side-by-side-printer.js ++++ /dev/null +@@ -1,275 +0,0 @@ +-/* +- * +- * HtmlPrinter (html-printer.js) +- * Author: rtfpessoa +- * +- */ +- +-(function() { +- var diffParser = require('./diff-parser.js').DiffParser; +- var printerUtils = require('./printer-utils.js').PrinterUtils; +- var utils = require('./utils.js').Utils; +- var Rematch = require('./rematch.js').Rematch; +- +- var hoganUtils; +- +- var genericTemplatesPath = 'generic'; +- var baseTemplatesPath = 'side-by-side'; +- var iconsBaseTemplatesPath = 'icon'; +- var tagsBaseTemplatesPath = 'tag'; +- +- var matcher = Rematch.rematch(function(a, b) { +- var amod = a.content.substr(1); +- var bmod = b.content.substr(1); +- +- return Rematch.distance(amod, bmod); +- }); +- +- function SideBySidePrinter(config) { +- this.config = config; +- +- var HoganJsUtils = require('./hoganjs-utils.js').HoganJsUtils; +- hoganUtils = new HoganJsUtils(config); +- } +- +- SideBySidePrinter.prototype.makeDiffHtml = function(file, diffs) { +- var fileDiffTemplate = hoganUtils.template(baseTemplatesPath, 'file-diff'); +- var filePathTemplate = hoganUtils.template(genericTemplatesPath, 'file-path'); +- var fileIconTemplate = hoganUtils.template(iconsBaseTemplatesPath, 'file'); +- var fileTagTemplate = hoganUtils.template(tagsBaseTemplatesPath, printerUtils.getFileTypeIcon(file)); +- +- return fileDiffTemplate.render({ +- file: file, +- fileHtmlId: printerUtils.getHtmlId(file), +- diffs: diffs, +- filePath: filePathTemplate.render({ +- fileDiffName: printerUtils.getDiffName(file) +- }, { +- fileIcon: fileIconTemplate, +- fileTag: fileTagTemplate +- }) +- }); +- }; +- +- SideBySidePrinter.prototype.generateSideBySideJsonHtml = function(diffFiles) { +- var that = this; +- +- var content = diffFiles.map(function(file) { +- var diffs; +- if (file.blocks.length) { +- diffs = that.generateSideBySideFileHtml(file); +- } else { +- diffs = that.generateEmptyDiff(); +- } +- +- return that.makeDiffHtml(file, diffs); +- }).join('\n'); +- +- return hoganUtils.render(genericTemplatesPath, 'wrapper', {'content': content}); +- }; +- +- SideBySidePrinter.prototype.makeSideHtml = function(blockHeader) { +- return hoganUtils.render(genericTemplatesPath, 'column-line-number', { +- diffParser: diffParser, +- blockHeader: utils.escape(blockHeader), +- lineClass: 'd2h-code-side-linenumber', +- contentClass: 'd2h-code-side-line' +- }); +- }; +- +- SideBySidePrinter.prototype.generateSideBySideFileHtml = function(file) { +- var that = this; +- var fileHtml = {}; +- fileHtml.left = ''; +- fileHtml.right = ''; +- +- file.blocks.forEach(function(block) { +- fileHtml.left += that.makeSideHtml(block.header); +- fileHtml.right += that.makeSideHtml(''); +- +- var oldLines = []; +- var newLines = []; +- +- function processChangeBlock() { +- var matches; +- var insertType; +- var deleteType; +- +- var comparisons = oldLines.length * newLines.length; +- +- var maxLineSizeInBlock = Math.max.apply(null, (oldLines.concat(newLines)).map(function(elem) { +- return elem.length; +- })); +- +- var doMatching = comparisons < that.config.matchingMaxComparisons && +- maxLineSizeInBlock < that.config.maxLineSizeInBlockForComparison && +- (that.config.matching === 'lines' || that.config.matching === 'words'); +- +- if (doMatching) { +- matches = matcher(oldLines, newLines); +- insertType = diffParser.LINE_TYPE.INSERT_CHANGES; +- deleteType = diffParser.LINE_TYPE.DELETE_CHANGES; +- } else { +- matches = [[oldLines, newLines]]; +- insertType = diffParser.LINE_TYPE.INSERTS; +- deleteType = diffParser.LINE_TYPE.DELETES; +- } +- +- matches.forEach(function(match) { +- oldLines = match[0]; +- newLines = match[1]; +- +- var common = Math.min(oldLines.length, newLines.length); +- var max = Math.max(oldLines.length, newLines.length); +- +- for (var j = 0; j < common; j++) { +- var oldLine = oldLines[j]; +- var newLine = newLines[j]; +- +- that.config.isCombined = file.isCombined; +- +- var diff = printerUtils.diffHighlight(oldLine.content, newLine.content, that.config); +- +- fileHtml.left += +- that.generateSingleLineHtml(file.isCombined, deleteType, oldLine.oldNumber, +- diff.first.line, diff.first.prefix); +- fileHtml.right += +- that.generateSingleLineHtml(file.isCombined, insertType, newLine.newNumber, +- diff.second.line, diff.second.prefix); +- } +- +- if (max > common) { +- var oldSlice = oldLines.slice(common); +- var newSlice = newLines.slice(common); +- +- var tmpHtml = that.processLines(file.isCombined, oldSlice, newSlice); +- fileHtml.left += tmpHtml.left; +- fileHtml.right += tmpHtml.right; +- } +- }); +- +- oldLines = []; +- newLines = []; +- } +- +- for (var i = 0; i < block.lines.length; i++) { +- var line = block.lines[i]; +- var prefix = line.content[0]; +- var escapedLine = utils.escape(line.content.substr(1)); +- +- if (line.type !== diffParser.LINE_TYPE.INSERTS && +- (newLines.length > 0 || (line.type !== diffParser.LINE_TYPE.DELETES && oldLines.length > 0))) { +- processChangeBlock(); +- } +- +- if (line.type === diffParser.LINE_TYPE.CONTEXT) { +- fileHtml.left += that.generateSingleLineHtml(file.isCombined, line.type, line.oldNumber, escapedLine, prefix); +- fileHtml.right += that.generateSingleLineHtml(file.isCombined, line.type, line.newNumber, escapedLine, prefix); +- } else if (line.type === diffParser.LINE_TYPE.INSERTS && !oldLines.length) { +- fileHtml.left += that.generateSingleLineHtml(file.isCombined, diffParser.LINE_TYPE.CONTEXT, '', '', ''); +- fileHtml.right += that.generateSingleLineHtml(file.isCombined, line.type, line.newNumber, escapedLine, prefix); +- } else if (line.type === diffParser.LINE_TYPE.DELETES) { +- oldLines.push(line); +- } else if (line.type === diffParser.LINE_TYPE.INSERTS && Boolean(oldLines.length)) { +- newLines.push(line); +- } else { +- console.error('unknown state in html side-by-side generator'); +- processChangeBlock(); +- } +- } +- +- processChangeBlock(); +- }); +- +- return fileHtml; +- }; +- +- SideBySidePrinter.prototype.processLines = function(isCombined, oldLines, newLines) { +- var that = this; +- var fileHtml = {}; +- fileHtml.left = ''; +- fileHtml.right = ''; +- +- var maxLinesNumber = Math.max(oldLines.length, newLines.length); +- for (var i = 0; i < maxLinesNumber; i++) { +- var oldLine = oldLines[i]; +- var newLine = newLines[i]; +- var oldContent; +- var newContent; +- var oldPrefix; +- var newPrefix; +- +- if (oldLine) { +- oldContent = utils.escape(oldLine.content.substr(1)); +- oldPrefix = oldLine.content[0]; +- } +- +- if (newLine) { +- newContent = utils.escape(newLine.content.substr(1)); +- newPrefix = newLine.content[0]; +- } +- +- if (oldLine && newLine) { +- fileHtml.left += that.generateSingleLineHtml(isCombined, oldLine.type, oldLine.oldNumber, oldContent, oldPrefix); +- fileHtml.right += that.generateSingleLineHtml(isCombined, newLine.type, newLine.newNumber, newContent, newPrefix); +- } else if (oldLine) { +- fileHtml.left += that.generateSingleLineHtml(isCombined, oldLine.type, oldLine.oldNumber, oldContent, oldPrefix); +- fileHtml.right += that.generateSingleLineHtml(isCombined, diffParser.LINE_TYPE.CONTEXT, '', '', ''); +- } else if (newLine) { +- fileHtml.left += that.generateSingleLineHtml(isCombined, diffParser.LINE_TYPE.CONTEXT, '', '', ''); +- fileHtml.right += that.generateSingleLineHtml(isCombined, newLine.type, newLine.newNumber, newContent, newPrefix); +- } else { +- console.error('How did it get here?'); +- } +- } +- +- return fileHtml; +- }; +- +- SideBySidePrinter.prototype.generateSingleLineHtml = function(isCombined, type, number, content, possiblePrefix) { +- var lineWithoutPrefix = content; +- var prefix = possiblePrefix; +- var lineClass = 'd2h-code-side-linenumber'; +- var contentClass = 'd2h-code-side-line'; +- +- if (!number && !content) { +- lineClass += ' d2h-code-side-emptyplaceholder'; +- contentClass += ' d2h-code-side-emptyplaceholder'; +- type += ' d2h-emptyplaceholder'; +- prefix = ' '; +- lineWithoutPrefix = ' '; +- } else if (!prefix) { +- var lineWithPrefix = printerUtils.separatePrefix(isCombined, content); +- prefix = lineWithPrefix.prefix; +- lineWithoutPrefix = lineWithPrefix.line; +- } +- +- if (prefix === ' ') { +- prefix = ' '; +- } +- +- return hoganUtils.render(genericTemplatesPath, 'line', +- { +- type: type, +- lineClass: lineClass, +- contentClass: contentClass, +- prefix: prefix, +- content: lineWithoutPrefix, +- lineNumber: number +- }); +- }; +- +- SideBySidePrinter.prototype.generateEmptyDiff = function() { +- var fileHtml = {}; +- fileHtml.right = ''; +- +- fileHtml.left = hoganUtils.render(genericTemplatesPath, 'empty-diff', { +- contentClass: 'd2h-code-side-line', +- diffParser: diffParser +- }); +- +- return fileHtml; +- }; +- +- module.exports.SideBySidePrinter = SideBySidePrinter; +-})(); +diff --git a/src/side-by-side-renderer.ts b/src/side-by-side-renderer.ts +new file mode 100644 +index 00000000..72daa141 +--- /dev/null ++++ b/src/side-by-side-renderer.ts +@@ -0,0 +1,313 @@ ++import HoganJsUtils from "./hoganjs-utils"; ++import * as Rematch from "./rematch"; ++import * as renderUtils from "./render-utils"; ++import { ++ DiffLine, ++ LineType, ++ DiffFile, ++ DiffBlock, ++ DiffLineContext, ++ DiffLineDeleted, ++ DiffLineInserted, ++ DiffLineContent ++} from "./types"; ++ ++export interface SideBySideRendererConfig extends renderUtils.RenderConfig { ++ renderNothingWhenEmpty?: boolean; ++ matchingMaxComparisons?: number; ++ maxLineSizeInBlockForComparison?: number; ++} ++ ++export const defaultSideBySideRendererConfig = { ++ ...renderUtils.defaultRenderConfig, ++ renderNothingWhenEmpty: false, ++ matchingMaxComparisons: 2500, ++ maxLineSizeInBlockForComparison: 200 ++}; ++ ++const genericTemplatesPath = "generic"; ++const baseTemplatesPath = "side-by-side"; ++const iconsBaseTemplatesPath = "icon"; ++const tagsBaseTemplatesPath = "tag"; ++ ++export default class SideBySideRenderer { ++ private readonly hoganUtils: HoganJsUtils; ++ private readonly config: typeof defaultSideBySideRendererConfig; ++ ++ constructor(hoganUtils: HoganJsUtils, config: SideBySideRendererConfig = {}) { ++ this.hoganUtils = hoganUtils; ++ this.config = { ...defaultSideBySideRendererConfig, ...config }; ++ } ++ ++ render(diffFiles: DiffFile[]): string { ++ const diffsHtml = diffFiles ++ .map(file => { ++ let diffs; ++ if (file.blocks.length) { ++ diffs = this.generateFileHtml(file); ++ } else { ++ diffs = this.generateEmptyDiff(); ++ } ++ return this.makeFileDiffHtml(file, diffs); ++ }) ++ .join("\n"); ++ ++ return this.hoganUtils.render(genericTemplatesPath, "wrapper", { content: diffsHtml }); ++ } ++ ++ makeFileDiffHtml(file: DiffFile, diffs: FileHtml): string { ++ if (this.config.renderNothingWhenEmpty && Array.isArray(file.blocks) && file.blocks.length === 0) return ""; ++ ++ const fileDiffTemplate = this.hoganUtils.template(baseTemplatesPath, "file-diff"); ++ const filePathTemplate = this.hoganUtils.template(genericTemplatesPath, "file-path"); ++ const fileIconTemplate = this.hoganUtils.template(iconsBaseTemplatesPath, "file"); ++ const fileTagTemplate = this.hoganUtils.template(tagsBaseTemplatesPath, renderUtils.getFileIcon(file)); ++ ++ return fileDiffTemplate.render({ ++ file: file, ++ fileHtmlId: renderUtils.getHtmlId(file), ++ diffs: diffs, ++ filePath: filePathTemplate.render( ++ { ++ fileDiffName: renderUtils.filenameDiff(file) ++ }, ++ { ++ fileIcon: fileIconTemplate, ++ fileTag: fileTagTemplate ++ } ++ ) ++ }); ++ } ++ ++ generateEmptyDiff(): FileHtml { ++ return { ++ right: "", ++ left: this.hoganUtils.render(genericTemplatesPath, "empty-diff", { ++ contentClass: "d2h-code-side-line", ++ CSSLineClass: renderUtils.CSSLineClass ++ }) ++ }; ++ } ++ ++ generateFileHtml(file: DiffFile): FileHtml { ++ const matcher = Rematch.newMatcherFn( ++ Rematch.newDistanceFn((e: DiffLine) => renderUtils.deconstructLine(e.content, file.isCombined).content) ++ ); ++ ++ return file.blocks ++ .map(block => { ++ const fileHtml = { ++ left: this.makeHeaderHtml(block.header), ++ right: this.makeHeaderHtml("") ++ }; ++ ++ this.applyLineGroupping(block).forEach(([contextLines, oldLines, newLines]) => { ++ if (oldLines.length && newLines.length && !contextLines.length) { ++ this.applyRematchMatching(oldLines, newLines, matcher).map(([oldLines, newLines]) => { ++ const { left, right } = this.processChangedLines(file.isCombined, oldLines, newLines); ++ fileHtml.left += left; ++ fileHtml.right += right; ++ }); ++ } else if (contextLines.length) { ++ contextLines.forEach(line => { ++ const { prefix, content } = renderUtils.deconstructLine(line.content, file.isCombined); ++ const { left, right } = this.generateLineHtml( ++ { ++ type: renderUtils.CSSLineClass.CONTEXT, ++ prefix: prefix, ++ content: content, ++ number: line.oldNumber ++ }, ++ { ++ type: renderUtils.CSSLineClass.CONTEXT, ++ prefix: prefix, ++ content: content, ++ number: line.newNumber ++ } ++ ); ++ fileHtml.left += left; ++ fileHtml.right += right; ++ }); ++ } else if (oldLines.length || newLines.length) { ++ const { left, right } = this.processChangedLines(file.isCombined, oldLines, newLines); ++ fileHtml.left += left; ++ fileHtml.right += right; ++ } else { ++ console.error("Unknown state reached while processing groups of lines", contextLines, oldLines, newLines); ++ } ++ }); ++ ++ return fileHtml; ++ }) ++ .reduce( ++ (accomulated, html) => { ++ return { left: accomulated.left + html.left, right: accomulated.right + html.right }; ++ }, ++ { left: "", right: "" } ++ ); ++ } ++ ++ applyLineGroupping(block: DiffBlock): DiffLineGroups { ++ const blockLinesGroups: DiffLineGroups = []; ++ ++ let oldLines: (DiffLineDeleted & DiffLineContent)[] = []; ++ let newLines: (DiffLineInserted & DiffLineContent)[] = []; ++ ++ for (let i = 0; i < block.lines.length; i++) { ++ const diffLine = block.lines[i]; ++ ++ if ( ++ (diffLine.type !== LineType.INSERT && newLines.length) || ++ (diffLine.type === LineType.CONTEXT && oldLines.length > 0) ++ ) { ++ blockLinesGroups.push([[], oldLines, newLines]); ++ oldLines = []; ++ newLines = []; ++ } ++ ++ if (diffLine.type === LineType.CONTEXT) { ++ blockLinesGroups.push([[diffLine], [], []]); ++ } else if (diffLine.type === LineType.INSERT && oldLines.length === 0) { ++ blockLinesGroups.push([[], [], [diffLine]]); ++ } else if (diffLine.type === LineType.INSERT && oldLines.length > 0) { ++ newLines.push(diffLine); ++ } else if (diffLine.type === LineType.DELETE) { ++ oldLines.push(diffLine); ++ } ++ } ++ ++ if (oldLines.length || newLines.length) { ++ blockLinesGroups.push([[], oldLines, newLines]); ++ oldLines = []; ++ newLines = []; ++ } ++ ++ return blockLinesGroups; ++ } ++ ++ applyRematchMatching( ++ oldLines: DiffLine[], ++ newLines: DiffLine[], ++ matcher: Rematch.MatcherFn ++ ): DiffLine[][][] { ++ const comparisons = oldLines.length * newLines.length; ++ const maxLineSizeInBlock = Math.max.apply( ++ null, ++ [0].concat(oldLines.concat(newLines).map(elem => elem.content.length)) ++ ); ++ const doMatching = ++ comparisons < this.config.matchingMaxComparisons && ++ maxLineSizeInBlock < this.config.maxLineSizeInBlockForComparison && ++ (this.config.matching === "lines" || this.config.matching === "words"); ++ ++ const matches = doMatching ? matcher(oldLines, newLines) : [[oldLines, newLines]]; ++ ++ return matches; ++ } ++ ++ makeHeaderHtml(blockHeader: string): string { ++ return this.hoganUtils.render(genericTemplatesPath, "block-header", { ++ CSSLineClass: renderUtils.CSSLineClass, ++ blockHeader: blockHeader, ++ lineClass: "d2h-code-side-linenumber", ++ contentClass: "d2h-code-side-line" ++ }); ++ } ++ ++ processChangedLines(isCombined: boolean, oldLines: DiffLine[], newLines: DiffLine[]): FileHtml { ++ const fileHtml = { ++ right: "", ++ left: "" ++ }; ++ ++ const maxLinesNumber = Math.max(oldLines.length, newLines.length); ++ for (let i = 0; i < maxLinesNumber; i++) { ++ const oldLine = oldLines[i]; ++ const newLine = newLines[i]; ++ ++ const diff = ++ oldLine !== undefined && newLine !== undefined ++ ? renderUtils.diffHighlight(oldLine.content, newLine.content, isCombined, this.config) ++ : undefined; ++ ++ const preparedOldLine = ++ oldLine !== undefined && oldLine.oldNumber !== undefined ++ ? { ++ ...(diff !== undefined ++ ? { ++ prefix: diff.oldLine.prefix, ++ content: diff.oldLine.content, ++ type: renderUtils.CSSLineClass.DELETE_CHANGES ++ } ++ : { ++ ...renderUtils.deconstructLine(oldLine.content, isCombined), ++ type: renderUtils.toCSSClass(oldLine.type) ++ }), ++ number: oldLine.oldNumber ++ } ++ : undefined; ++ ++ const preparedNewLine = ++ newLine !== undefined && newLine.newNumber !== undefined ++ ? { ++ ...(diff !== undefined ++ ? { ++ prefix: diff.newLine.prefix, ++ content: diff.newLine.content, ++ type: renderUtils.CSSLineClass.INSERT_CHANGES ++ } ++ : { ++ ...renderUtils.deconstructLine(newLine.content, isCombined), ++ type: renderUtils.toCSSClass(newLine.type) ++ }), ++ number: newLine.newNumber ++ } ++ : undefined; ++ ++ const { left, right } = this.generateLineHtml(preparedOldLine, preparedNewLine); ++ fileHtml.left += left; ++ fileHtml.right += right; ++ } ++ ++ return fileHtml; ++ } ++ ++ generateLineHtml(oldLine?: DiffPreparedLine, newLine?: DiffPreparedLine): FileHtml { ++ return { ++ left: this.generateSingleHtml(oldLine), ++ right: this.generateSingleHtml(newLine) ++ }; ++ } ++ ++ generateSingleHtml(line?: DiffPreparedLine): string { ++ const lineClass = "d2h-code-side-linenumber"; ++ const contentClass = "d2h-code-side-line"; ++ ++ return this.hoganUtils.render(genericTemplatesPath, "line", { ++ type: line?.type || `${renderUtils.CSSLineClass.CONTEXT} d2h-emptyplaceholder`, ++ lineClass: line !== undefined ? lineClass : `${lineClass} d2h-code-side-emptyplaceholder`, ++ contentClass: line !== undefined ? contentClass : `${contentClass} d2h-code-side-emptyplaceholder`, ++ prefix: line?.prefix === " " ? " " : line?.prefix || " ", ++ content: line?.content || " ", ++ lineNumber: line?.number ++ }); ++ } ++} ++ ++type DiffLineGroups = [ ++ (DiffLineContext & DiffLineContent)[], ++ (DiffLineDeleted & DiffLineContent)[], ++ (DiffLineInserted & DiffLineContent)[] ++][]; ++ ++type DiffPreparedLine = { ++ type: renderUtils.CSSLineClass; ++ prefix: string; ++ content: string; ++ number: number; ++}; ++ ++type FileHtml = { ++ left: string; ++ right: string; ++}; +diff --git a/src/templates/diff2html-templates.js b/src/templates/diff2html-templates.js +deleted file mode 100644 +index 945a9f2b..00000000 +--- a/src/templates/diff2html-templates.js ++++ /dev/null +@@ -1,23 +0,0 @@ +-(function() { +-if (!!!global.browserTemplates) global.browserTemplates = {}; +-var Hogan = require("hogan.js");global.browserTemplates["file-summary-line"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("
  • ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(t.rp("");t.b(t.v(t.f("fileName",c,p,0)));t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b(t.v(t.f("addedLines",c,p,0)));t.b("");t.b("\n" + i);t.b(" ");t.b(t.v(t.f("deletedLines",c,p,0)));t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("
  • ");return t.fl(); },partials: {"");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b(" Files changed (");t.b(t.v(t.f("filesNumber",c,p,0)));t.b(")");t.b("\n" + i);t.b(" hide");t.b("\n" + i);t.b(" show");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
      ");t.b("\n" + i);t.b(" ");t.b(t.t(t.f("files",c,p,0)));t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["generic-column-line-number"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("
    ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["generic-empty-diff"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["generic-file-path"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("");t.b("\n" + i);t.b(t.rp("");t.b(t.v(t.f("fileDiffName",c,p,0)));t.b("");t.b("\n" + i);t.b(t.rp("");return t.fl(); },partials: {"");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["generic-wrapper"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("
    ");t.b("\n" + i);t.b(" ");t.b(t.t(t.f("content",c,p,0)));t.b("\n" + i);t.b("
    ");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["icon-file-added"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["icon-file-changed"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["icon-file-deleted"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["icon-file-renamed"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["icon-file"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["line-by-line-file-diff"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b(" ");t.b(t.t(t.f("filePath",c,p,0)));t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    Use the following format for additions: ` - VERSION: [feature/patch (if applicable)] Short description of change. Links to relevant issues/PRs.`\n' + + ' $a="\n" + ++ ' \n' + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ ""; ++ ++ expect(html).toEqual(expected); ++ }); ++ }); ++}); +diff --git a/src/__tests__/printer-utils-tests.ts b/src/__tests__/printer-utils-tests.ts +new file mode 100644 +index 00000000..6452bebc +--- /dev/null ++++ b/src/__tests__/printer-utils-tests.ts +@@ -0,0 +1,159 @@ ++import { escapeForHtml, getHtmlId, filenameDiff, diffHighlight } from "../render-utils"; ++import { DiffStyleType, LineMatchingType } from "../types"; ++ ++describe("Utils", () => { ++ describe("escapeForHtml", () => { ++ it("should escape & with &", () => { ++ const result = escapeForHtml("&"); ++ expect(result).toEqual("&"); ++ }); ++ it("should escape < with <", () => { ++ const result = escapeForHtml("<"); ++ expect(result).toEqual("<"); ++ }); ++ it("should escape > with >", () => { ++ const result = escapeForHtml(">"); ++ expect(result).toEqual(">"); ++ }); ++ it('should escape " with "', () => { ++ const result = escapeForHtml('"'); ++ expect(result).toEqual("""); ++ }); ++ it("should escape ' with '", () => { ++ const result = escapeForHtml("'"); ++ expect(result).toEqual("'"); ++ }); ++ it("should escape / with /", () => { ++ const result = escapeForHtml("/"); ++ expect(result).toEqual("/"); ++ }); ++ it("should escape a string containing HTML code", () => { ++ const result = escapeForHtml(`Search 'Diff2Html'`); ++ expect(result).toEqual( ++ "<a href="/search?q=diff2html">Search 'Diff2Html'</a>" ++ ); ++ }); ++ }); ++ ++ describe("getHtmlId", () => { ++ it("should generate file unique id", () => { ++ const result = getHtmlId({ ++ oldName: "sample.js", ++ newName: "sample.js" ++ }); ++ expect("d2h-960013").toEqual(result); ++ }); ++ it("should generate file unique id for empty hashes", () => { ++ const result = getHtmlId({ ++ oldName: "sample.js", ++ newName: "sample.js" ++ }); ++ expect("d2h-960013").toEqual(result); ++ }); ++ }); ++ ++ describe("getDiffName", () => { ++ it("should generate the file name for a changed file", () => { ++ const result = filenameDiff({ ++ oldName: "sample.js", ++ newName: "sample.js" ++ }); ++ expect("sample.js").toEqual(result); ++ }); ++ it("should generate the file name for a changed file and full rename", () => { ++ const result = filenameDiff({ ++ oldName: "sample1.js", ++ newName: "sample2.js" ++ }); ++ expect("sample1.js → sample2.js").toEqual(result); ++ }); ++ it("should generate the file name for a changed file and prefix rename", () => { ++ const result = filenameDiff({ ++ oldName: "src/path/sample.js", ++ newName: "source/path/sample.js" ++ }); ++ expect("{src → source}/path/sample.js").toEqual(result); ++ }); ++ it("should generate the file name for a changed file and suffix rename", () => { ++ const result = filenameDiff({ ++ oldName: "src/path/sample1.js", ++ newName: "src/path/sample2.js" ++ }); ++ expect("src/path/{sample1.js → sample2.js}").toEqual(result); ++ }); ++ it("should generate the file name for a changed file and middle rename", () => { ++ const result = filenameDiff({ ++ oldName: "src/really/big/path/sample.js", ++ newName: "src/small/path/sample.js" ++ }); ++ expect("src/{really/big → small}/path/sample.js").toEqual(result); ++ }); ++ it("should generate the file name for a deleted file", () => { ++ const result = filenameDiff({ ++ oldName: "src/my/file.js", ++ newName: "/dev/null" ++ }); ++ expect("src/my/file.js").toEqual(result); ++ }); ++ it("should generate the file name for a new file", () => { ++ const result = filenameDiff({ ++ oldName: "/dev/null", ++ newName: "src/my/file.js" ++ }); ++ expect("src/my/file.js").toEqual(result); ++ }); ++ }); ++ ++ describe("diffHighlight", () => { ++ it("should highlight two lines", () => { ++ const result = diffHighlight("-var myVar = 2;", "+var myVariable = 3;", false, { ++ matching: LineMatchingType.WORDS ++ }); ++ ++ expect(result).toEqual({ ++ oldLine: { ++ prefix: "-", ++ content: "var myVar = 2;" ++ }, ++ newLine: { ++ prefix: "+", ++ content: "var myVariable = 3;" ++ } ++ }); ++ }); ++ it("should highlight two lines char by char", () => { ++ const result = diffHighlight("-var myVar = 2;", "+var myVariable = 3;", false, { ++ diffStyle: DiffStyleType.CHAR ++ }); ++ ++ expect({ ++ oldLine: { ++ prefix: "-", ++ content: "var myVar = 2;" ++ }, ++ newLine: { ++ prefix: "+", ++ content: "var myVariable = 3;" ++ } ++ }).toEqual(result); ++ }); ++ it("should highlight combined diff lines", () => { ++ const result = diffHighlight(" -var myVar = 2;", " +var myVariable = 3;", true, { ++ diffStyle: DiffStyleType.WORD, ++ matching: LineMatchingType.WORDS, ++ matchWordsThreshold: 1.0 ++ }); ++ ++ expect({ ++ oldLine: { ++ prefix: " -", ++ content: 'var myVar = 2;' ++ }, ++ newLine: { ++ prefix: " +", ++ content: 'var myVariable = 3;' ++ } ++ }).toEqual(result); ++ }); ++ }); ++}); +diff --git a/src/__tests__/side-by-side-printer-tests.ts b/src/__tests__/side-by-side-printer-tests.ts +new file mode 100644 +index 00000000..3237fa97 +--- /dev/null ++++ b/src/__tests__/side-by-side-printer-tests.ts +@@ -0,0 +1,464 @@ ++import SideBySideRenderer from "../side-by-side-renderer"; ++import HoganJsUtils from "../hoganjs-utils"; ++import { LineType, DiffLine, DiffFile, LineMatchingType } from "../types"; ++import { CSSLineClass } from "../render-utils"; ++ ++describe("SideBySideRenderer", () => { ++ describe("generateEmptyDiff", () => { ++ it("should return an empty diff", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const sideBySideRenderer = new SideBySideRenderer(hoganUtils, {}); ++ const fileHtml = sideBySideRenderer.generateEmptyDiff(); ++ const expectedRight = ""; ++ const expectedLeft = ++ "\n" + ++ ' \n" + ++ ""; ++ ++ expect(fileHtml.right).toEqual(expectedRight); ++ expect(fileHtml.left).toEqual(expectedLeft); ++ }); ++ }); ++ ++ describe("generateSideBySideFileHtml", () => { ++ it("should generate lines with the right prefixes", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const sideBySideRenderer = new SideBySideRenderer(hoganUtils, {}); ++ ++ const file: DiffFile = { ++ isGitDiff: true, ++ blocks: [ ++ { ++ lines: [ ++ { ++ content: " context", ++ type: LineType.CONTEXT, ++ oldNumber: 19, ++ newNumber: 19 ++ }, ++ { ++ content: "-removed", ++ type: LineType.DELETE, ++ oldNumber: 20, ++ newNumber: undefined ++ }, ++ { ++ content: "+added", ++ type: LineType.INSERT, ++ oldNumber: undefined, ++ newNumber: 20 ++ }, ++ { ++ content: "+another added", ++ type: LineType.INSERT, ++ oldNumber: undefined, ++ newNumber: 21 ++ } ++ ], ++ oldStartLine: 19, ++ newStartLine: 19, ++ header: "@@ -19,7 +19,7 @@" ++ } ++ ], ++ deletedLines: 1, ++ addedLines: 2, ++ checksumBefore: "fc56817", ++ checksumAfter: "e8e7e49", ++ mode: "100644", ++ oldName: "coverage.init", ++ language: "init", ++ newName: "coverage.init", ++ isCombined: false ++ }; ++ ++ const fileHtml = sideBySideRenderer.generateFileHtml(file); ++ ++ const expectedLeft = ++ "\n" + ++ ' \n' + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ ""; ++ ++ const expectedRight = ++ "\n" + ++ ' \n' + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ ""; ++ ++ expect(fileHtml.left).toEqual(expectedLeft); ++ expect(fileHtml.right).toEqual(expectedRight); ++ }); ++ }); ++ ++ describe("generateSingleLineHtml", () => { ++ it("should work for insertions", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const sideBySideRenderer = new SideBySideRenderer(hoganUtils, {}); ++ const fileHtml = sideBySideRenderer.generateLineHtml(undefined, { ++ type: CSSLineClass.INSERTS, ++ prefix: "+", ++ content: "test", ++ number: 30 ++ }); ++ ++ const expected = { ++ left: ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "", ++ right: ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "" ++ }; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ it("should work for deletions", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const sideBySideRenderer = new SideBySideRenderer(hoganUtils, {}); ++ const fileHtml = sideBySideRenderer.generateLineHtml( ++ { ++ type: CSSLineClass.DELETES, ++ prefix: "-", ++ content: "test", ++ number: 30 ++ }, ++ undefined ++ ); ++ const expected = { ++ left: ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "", ++ right: ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "" ++ }; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ }); ++ ++ describe("generateSideBySideJsonHtml", () => { ++ it("should work for list of files", () => { ++ const exampleJson: DiffFile[] = [ ++ { ++ blocks: [ ++ { ++ lines: [ ++ { ++ content: "-test", ++ type: LineType.DELETE, ++ oldNumber: 1, ++ newNumber: undefined ++ }, ++ { ++ content: "+test1r", ++ type: LineType.INSERT, ++ oldNumber: undefined, ++ newNumber: 1 ++ } ++ ], ++ oldStartLine: 1, ++ oldStartLine2: undefined, ++ newStartLine: 1, ++ header: "@@ -1 +1 @@" ++ } ++ ], ++ deletedLines: 1, ++ addedLines: 1, ++ checksumBefore: "0000001", ++ checksumAfter: "0ddf2ba", ++ oldName: "sample", ++ language: "txt", ++ newName: "sample", ++ isCombined: false, ++ isGitDiff: true ++ } ++ ]; ++ ++ const hoganUtils = new HoganJsUtils({}); ++ const sideBySideRenderer = new SideBySideRenderer(hoganUtils, { matching: LineMatchingType.LINES }); ++ const html = sideBySideRenderer.render(exampleJson); ++ const expected = ++ '
    \n' + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' sample\n' + ++ ' CHANGED\n' + ++ "
    \n" + ++ '
    \n' + ++ '
    \n' + ++ '
    \n' + ++ '
    \n' + + " $a=\"\n" + ++ ' \n" + ++ ""; ++ ++ it("should render view", () => { ++ const hoganJsUtils = new HoganJsUtils({}); ++ const result = hoganJsUtils.render("generic", "empty-diff", { ++ contentClass: "d2h-code-line", ++ CSSLineClass: CSSLineClass ++ }); ++ expect(result).toEqual(emptyDiffHtml); ++ }); ++ ++ it("should render view without cache", () => { ++ const hoganJsUtils = new HoganJsUtils({}); ++ const result = hoganJsUtils.render("generic", "empty-diff", { ++ contentClass: "d2h-code-line", ++ CSSLineClass: CSSLineClass ++ }); ++ expect(result).toEqual(emptyDiffHtml); ++ }); ++ ++ it("should throw exception if template is missing", () => { ++ const hoganJsUtils = new HoganJsUtils({}); ++ expect(() => hoganJsUtils.render("generic", "missing-template", {})).toThrow(Error); ++ }); ++ ++ it("should allow templates to be overridden with compiled templates", () => { ++ const emptyDiffTemplate = HoganJsUtils.compile("

    {{myName}}

    "); ++ const hoganJsUtils = new HoganJsUtils({ compiledTemplates: { "generic-empty-diff": emptyDiffTemplate } }); ++ ++ const result = hoganJsUtils.render("generic", "empty-diff", { myName: "Rodrigo Fernandes" }); ++ expect(result).toEqual("

    Rodrigo Fernandes

    "); ++ }); ++ ++ it("should allow templates to be overridden with uncompiled templates", () => { ++ const emptyDiffTemplate = "

    {{myName}}

    "; ++ const hoganJsUtils = new HoganJsUtils({ rawTemplates: { "generic-empty-diff": emptyDiffTemplate } }); ++ ++ const result = hoganJsUtils.render("generic", "empty-diff", { myName: "Rodrigo Fernandes" }); ++ expect(result).toEqual("

    Rodrigo Fernandes

    "); ++ }); ++ ++ it("should allow templates to be overridden giving priority to raw templates", () => { ++ const emptyDiffTemplate = HoganJsUtils.compile("

    Not used!

    "); ++ const emptyDiffTemplateUncompiled = "

    {{myName}}

    "; ++ const hoganJsUtils = new HoganJsUtils({ ++ compiledTemplates: { "generic-empty-diff": emptyDiffTemplate }, ++ rawTemplates: { "generic-empty-diff": emptyDiffTemplateUncompiled } ++ }); ++ ++ const result = hoganJsUtils.render("generic", "empty-diff", { myName: "Rodrigo Fernandes" }); ++ expect(result).toEqual("

    Rodrigo Fernandes

    "); ++ }); ++ }); ++}); +diff --git a/src/__tests__/line-by-line-tests.ts b/src/__tests__/line-by-line-tests.ts +new file mode 100644 +index 00000000..8d0851f6 +--- /dev/null ++++ b/src/__tests__/line-by-line-tests.ts +@@ -0,0 +1,613 @@ ++import LineByLineRenderer from "../line-by-line-renderer"; ++import HoganJsUtils from "../hoganjs-utils"; ++import { LineType, DiffFile, LineMatchingType } from "../types"; ++import { CSSLineClass } from "../render-utils"; ++ ++describe("LineByLineRenderer", () => { ++ describe("_generateEmptyDiff", () => { ++ it("should return an empty diff", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); ++ const fileHtml = lineByLineRenderer.generateEmptyDiff(); ++ const expected = ++ "\n" + ++ ' \n" + ++ ""; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ }); ++ ++ describe("makeLineHtml", () => { ++ it("should work for insertions", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); ++ let fileHtml = lineByLineRenderer.generateSingleLineHtml({ ++ type: CSSLineClass.INSERTS, ++ prefix: "+", ++ content: "test", ++ oldNumber: undefined, ++ newNumber: 30 ++ }); ++ fileHtml = fileHtml.replace(/\n\n+/g, "\n"); ++ const expected = ++ "\n" + ++ ' \n" + ++ ' \n" + ++ ""; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ ++ it("should work for deletions", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); ++ let fileHtml = lineByLineRenderer.generateSingleLineHtml({ ++ type: CSSLineClass.DELETES, ++ prefix: "-", ++ content: "test", ++ oldNumber: 30, ++ newNumber: undefined ++ }); ++ fileHtml = fileHtml.replace(/\n\n+/g, "\n"); ++ const expected = ++ "\n" + ++ ' \n" + ++ ' \n" + ++ ""; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ ++ it("should convert indents into non breakin spaces (2 white spaces)", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); ++ let fileHtml = lineByLineRenderer.generateSingleLineHtml({ ++ type: CSSLineClass.INSERTS, ++ prefix: "+", ++ content: " test", ++ oldNumber: undefined, ++ newNumber: 30 ++ }); ++ fileHtml = fileHtml.replace(/\n\n+/g, "\n"); ++ const expected = ++ "\n" + ++ ' \n" + ++ ' \n" + ++ ""; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ ++ it("should convert indents into non breakin spaces (4 white spaces)", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); ++ let fileHtml = lineByLineRenderer.generateSingleLineHtml({ ++ type: CSSLineClass.INSERTS, ++ prefix: "+", ++ content: " test", ++ oldNumber: undefined, ++ newNumber: 30 ++ }); ++ fileHtml = fileHtml.replace(/\n\n+/g, "\n"); ++ const expected = ++ "\n" + ++ ' \n" + ++ ' \n" + ++ ""; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ ++ it("should preserve tabs", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); ++ let fileHtml = lineByLineRenderer.generateSingleLineHtml({ ++ type: CSSLineClass.INSERTS, ++ prefix: "+", ++ content: "\ttest", ++ oldNumber: undefined, ++ newNumber: 30 ++ }); ++ fileHtml = fileHtml.replace(/\n\n+/g, "\n"); ++ const expected = ++ "\n" + ++ ' \n" + ++ ' \n" + ++ ""; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ }); ++ ++ describe("makeFileDiffHtml", () => { ++ it("should work for simple file", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); ++ ++ const file = { ++ addedLines: 12, ++ deletedLines: 41, ++ language: "js", ++ oldName: "my/file/name.js", ++ newName: "my/file/name.js", ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [] ++ }; ++ const diffs = "Random Html"; ++ ++ const fileHtml = lineByLineRenderer.makeFileDiffHtml(file, diffs); ++ ++ const expected = ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' my/file/name.js\n' + ++ ' CHANGED\n' + ++ "
    \n" + ++ '
    \n' + ++ '
    \n' + ++ '
    - 1.1.9: Fix around ubuntu's inability to cache promises. [#877](https://github.com/FredrikNoren/ungit/pull/878)\n" + +- ' - 1.1.8:\n' + +- "@@ -11,7 +10,7 @@ $a=\"\n" + ++ "\n" + ++ " \n" + ++ "
    - 1.1.9: Fix around ubuntu's inability to cache promises. [#8\n" + +- ' - 1.1.7:\n' + +- ' - Fix diff flickering issue and optimization [#865](https://github.com/FredrikNoren/ungit/pull/865)\n' + +- ' - Fix credential dialog issue [#864](https://github.com/FredrikNoren/ungit/pull/864)\n' + +- '- - Fix HEAD branch order when redraw [#858](https://github.com/FredrikNoren/ungit/issues/858)\n' + +- '+4 - Fix HEAD branch order when redraw [#858](https://github.com/FredrikNoren/ungit/issues/858)\n' + +- ' - 1.1.6: Fix path auto complete [#861](https://github.com/FredrikNoren/ungit/issues/861)\n' + ++ " - 1.1.8:\n" + ++ "@@ -11,7 +10,7 @@ $a="<table><tr><td>- 1.1.9: Fix around ubuntu's inability to cache promises. [#8\n" + ++ " - 1.1.7:\n" + ++ " - Fix diff flickering issue and optimization [#865](https://github.com/FredrikNoren/ungit/pull/865)\n" + ++ " - Fix credential dialog issue [#864](https://github.com/FredrikNoren/ungit/pull/864)\n" + ++ "- - Fix HEAD branch order when redraw [#858](https://github.com/FredrikNoren/ungit/issues/858)\n" + ++ "+4 - Fix HEAD branch order when redraw [#858](https://github.com/FredrikNoren/ungit/issues/858)\n" + ++ " - 1.1.6: Fix path auto complete [#861](https://github.com/FredrikNoren/ungit/issues/861)\n" + + ' - 1.1.5: Update "Toggle all" button after commit or changing selected files [#859](https://github.com/FredrikNoren/ungit/issues/859)\n' + +- ' - 1.1.4: [patch] Promise refactoring\n' + +- ' \n'; ++ " - 1.1.4: [patch] Promise refactoring\n" + ++ " \n"; + +- var htmlExample2 = '
    \n' + ++ const htmlExample2 = ++ '
    \n' + + '
    \n' + + '
    \n' + + ' \n' + +@@ -318,207 +319,207 @@ describe('Diff2Html', function() { + ' \n' + + ' CHANGELOG.md\n' + + ' CHANGED\n' + +- '
    \n' + ++ "
    \n" + + '
    \n' + + '
    \n' + + ' \n' + + ' \n' + +- ' \n' + ++ " \n" + + ' \n' + + ' \n' + +- '\n' + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + ++ "\n" + + ' \n' + + ' \n' + +- '\n' + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + +- ' \n" + ++ "\n" + ++ ' \n' + +- ' \n" + ++ ' \n' + +- '\n' + +- ' \n" + ++ "\n" + ++ ' \n' + +- ' \n" + ++ ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + ++ " \n" + ++ " \n" + ++ "\n" + + ' \n' + ++ " \n" + + ' \n' + +- '\n' + +- ' \n' + +- '
    \n' + + '
    @@ -1,7 +1,6 @@
    \n' + +- '
    \n' + + '
    1
    \n' + + '
    1
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' # Change Log\n' + +- '
    \n' + +- '
    \n' + + '
    2
    \n' + + '
    2
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' All notable changes to this project will be documented in this file.\n' + +- '
    \n' + +- '
    \n' + + '
    3
    \n' + + '
    3
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' This project adheres to [Semantic Versioning](http://semver.org/).\n' + +- '
    \n' + +- '
    \n' + + '
    4
    \n' + + '
    \n' + +- '
    \n' + + '
    \n' + + ' -\n' + + ' $a="<table><tr><td>Use the following format for additions: ` - VERSION: [feature/patch (if applicable)] Short description of change. Links to relevant issues/PRs.`\n' + +- '
    \n' + +- '
    \n' + + '
    5
    \n' + + '
    4
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' $a="<table><tr><td>\n' + +- '
    \n' + +- '
    \n' + + '
    6
    \n' + + '
    5
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' $a="<table><tr><td>- 1.1.9: Fix around ubuntu's inability to cache promises. [#877](https://github.com/FredrikNoren/ungit/pull/878)\n' + +- '
    \n' + +- '
    \n' + + '
    7
    \n' + + '
    6
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' - 1.1.8:\n' + +- '
    \n' + +- '
    \n' + + '
    @@ -11,7 +10,7 @@ $a="<table><tr><td>- 1.1.9: Fix around ubuntu's inability to cache promises. [#8
    \n' + +- '
    \n' + + '
    11
    \n' + + '
    10
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' - 1.1.7:\n' + +- '
    \n' + +- '
    \n' + + '
    12
    \n' + + '
    11
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' - Fix diff flickering issue and optimization [#865](https://github.com/FredrikNoren/ungit/pull/865)\n' + +- '
    \n' + +- '
    \n' + + '
    13
    \n' + + '
    12
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' - Fix credential dialog issue [#864](https://github.com/FredrikNoren/ungit/pull/864)\n' + +- '
    \n' + +- '
    \n' + ++ " \n" + ++ "
    \n' + + '
    14
    \n' + + '
    \n' + +- '
    \n' + +- '
    \n' + ++ "
    \n' + ++ '
    \n' + + ' -\n' + + ' - Fix HEAD branch order when redraw [#858](https://github.com/FredrikNoren/ungit/issues/858)\n' + +- '
    \n' + +- '
    \n' + ++ " \n" + ++ "
    \n' + + '
    \n' + + '
    13
    \n' + +- '
    \n' + +- '
    \n' + ++ "
    \n' + ++ '
    \n' + + ' +\n' + + ' 4 - Fix HEAD branch order when redraw [#858](https://github.com/FredrikNoren/ungit/issues/858)\n' + +- '
    \n' + +- '
    \n' + + '
    15
    \n' + + '
    14
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' - 1.1.6: Fix path auto complete [#861](https://github.com/FredrikNoren/ungit/issues/861)\n' + +- '
    \n' + +- '
    \n' + + '
    16
    \n' + + '
    15
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' - 1.1.5: Update "Toggle all" button after commit or changing selected files [#859](https://github.com/FredrikNoren/ungit/issues/859)\n' + +- '
    \n' + +- '
    \n' + + '
    17
    \n' + + '
    16
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + + ' - 1.1.4: [patch] Promise refactoring\n' + +- '
    \n' + +- '
    \n' + + '
    18
    \n' + + '
    17
    \n' + +- '
    \n' + + '
    \n' + + '  \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    '; ++ " \n" + ++ "
    \n" + ++ " \n" + ++ " \n" + ++ "\n" + ++ ""; + +- var result = Diff2Html.getPrettyHtmlFromDiff(diffExample2); +- assert.equal(result, htmlExample2); ++ const result = html(diffExample2, { drawFileList: false }); ++ expect(result).toEqual(htmlExample2); + }); + }); + }); +diff --git a/src/__tests__/file-list-printer-tests.ts b/src/__tests__/file-list-printer-tests.ts +new file mode 100644 +index 00000000..102c11f6 +--- /dev/null ++++ b/src/__tests__/file-list-printer-tests.ts +@@ -0,0 +1,179 @@ ++import { render } from "../file-list-renderer"; ++import HoganJsUtils from "../hoganjs-utils"; ++ ++describe("FileListPrinter", () => { ++ describe("generateFileList", () => { ++ it("should expose old and new files to templates", () => { ++ const hoganUtils = new HoganJsUtils({ ++ rawTemplates: { ++ "file-summary-wrapper": "{{{files}}}", ++ "file-summary-line": "{{oldName}}, {{newName}}, {{fileName}}" ++ } ++ }); ++ const files = [ ++ { ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [], ++ addedLines: 12, ++ deletedLines: 41, ++ language: "js", ++ oldName: "my/file/name.js", ++ newName: "my/file/name.js" ++ }, ++ { ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [], ++ addedLines: 12, ++ deletedLines: 41, ++ language: "js", ++ oldName: "my/file/name1.js", ++ newName: "my/file/name2.js" ++ }, ++ { ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [], ++ addedLines: 12, ++ deletedLines: 0, ++ language: "js", ++ oldName: "dev/null", ++ newName: "my/file/name.js", ++ isNew: true ++ }, ++ { ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [], ++ addedLines: 0, ++ deletedLines: 41, ++ language: "js", ++ oldName: "my/file/name.js", ++ newName: "dev/null", ++ isDeleted: true ++ } ++ ]; ++ ++ const fileHtml = render(files, hoganUtils); ++ const expected = ++ "my/file/name.js, my/file/name.js, my/file/name.js\n" + ++ "my/file/name1.js, my/file/name2.js, my/file/{name1.js → name2.js}\n" + ++ "dev/null, my/file/name.js, my/file/name.js\n" + ++ "my/file/name.js, dev/null, my/file/name.js"; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ ++ it("should work for all kinds of files", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const files = [ ++ { ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [], ++ addedLines: 12, ++ deletedLines: 41, ++ language: "js", ++ oldName: "my/file/name.js", ++ newName: "my/file/name.js" ++ }, ++ { ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [], ++ addedLines: 12, ++ deletedLines: 41, ++ language: "js", ++ oldName: "my/file/name1.js", ++ newName: "my/file/name2.js" ++ }, ++ { ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [], ++ addedLines: 12, ++ deletedLines: 0, ++ language: "js", ++ oldName: "dev/null", ++ newName: "my/file/name.js", ++ isNew: true ++ }, ++ { ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [], ++ addedLines: 0, ++ deletedLines: 41, ++ language: "js", ++ oldName: "my/file/name.js", ++ newName: "dev/null", ++ isDeleted: true ++ } ++ ]; ++ ++ const fileHtml = render(files, hoganUtils); ++ ++ const expected = ++ '
    \n' + ++ '
    \n' + ++ ' Files changed (4)\n' + ++ ' hide\n' + ++ ' show\n' + ++ "
    \n" + ++ '
      \n' + ++ '
    1. \n' + ++ ' \n' + ++ ' my/file/name.js\n' + ++ ' \n' + ++ ' +12\n' + ++ ' -41\n' + ++ " \n" + ++ " \n" + ++ "
    2. \n" + ++ '
    3. \n' + ++ ' \n' + ++ ' my/file/{name1.js → name2.js}\n' + ++ ' \n' + ++ ' +12\n' + ++ ' -41\n' + ++ " \n" + ++ " \n" + ++ "
    4. \n" + ++ '
    5. \n' + ++ ' \n' + ++ ' my/file/name.js\n' + ++ ' \n' + ++ ' +12\n' + ++ ' -0\n' + ++ " \n" + ++ " \n" + ++ "
    6. \n" + ++ '
    7. \n' + ++ ' \n' + ++ ' my/file/name.js\n' + ++ ' \n' + ++ ' +0\n' + ++ ' -41\n' + ++ " \n" + ++ " \n" + ++ "
    8. \n" + ++ "
    \n" + ++ "
    "; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ }); ++}); +diff --git a/src/__tests__/hogan-cache-tests.ts b/src/__tests__/hogan-cache-tests.ts +new file mode 100644 +index 00000000..d292babb +--- /dev/null ++++ b/src/__tests__/hogan-cache-tests.ts +@@ -0,0 +1,66 @@ ++import HoganJsUtils from "../hoganjs-utils"; ++import { CSSLineClass } from "../render-utils"; ++ ++describe("HoganJsUtils", () => { ++ describe("render", () => { ++ const emptyDiffHtml = ++ "
    \n' + ++ '
    \n' + ++ " File without changes\n" + ++ "
    \n" + ++ "
    \n' + ++ '
    \n' + ++ " File without changes\n" + ++ "
    \n" + ++ "
    \n' + ++ '
    \n' + ++ '
    30
    \n' + ++ "
    \n' + ++ '
    \n' + ++ ' +\n' + ++ ' test\n' + ++ "
    \n" + ++ "
    \n' + ++ '
    30
    \n' + ++ '
    \n' + ++ "
    \n' + ++ '
    \n' + ++ ' -\n' + ++ ' test\n' + ++ "
    \n" + ++ "
    \n' + ++ '
    \n' + ++ '
    30
    \n' + ++ "
    \n' + ++ '
    \n' + ++ ' +\n' + ++ ' test\n' + ++ "
    \n" + ++ "
    \n' + ++ '
    \n' + ++ '
    30
    \n' + ++ "
    \n' + ++ '
    \n' + ++ ' +\n' + ++ ' test\n' + ++ "
    \n" + ++ "
    \n' + ++ '
    \n' + ++ "" + ++ '
    30
    \n' + ++ "
    \n' + ++ '
    \n' + ++ ' +\n' + ++ ' \ttest\n' + ++ "
    \n" + ++ "
    \n' + ++ ' \n' + ++ " Random Html\n" + ++ " \n" + ++ "
    \n" + ++ " \n" + ++ " \n" + ++ ""; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ it("should work for simple added file", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); ++ ++ const file = { ++ addedLines: 12, ++ deletedLines: 0, ++ language: "js", ++ oldName: "dev/null", ++ newName: "my/file/name.js", ++ isNew: true, ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [] ++ }; ++ const diffs = "Random Html"; ++ ++ const fileHtml = lineByLineRenderer.makeFileDiffHtml(file, diffs); ++ ++ const expected = ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' my/file/name.js\n' + ++ ' ADDED\n' + ++ "
    \n" + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' \n' + ++ " Random Html\n" + ++ " \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    "; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ it("should work for simple deleted file", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); ++ ++ const file = { ++ addedLines: 0, ++ deletedLines: 41, ++ language: "js", ++ oldName: "my/file/name.js", ++ newName: "dev/null", ++ isDeleted: true, ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [] ++ }; ++ const diffs = "Random Html"; ++ ++ const fileHtml = lineByLineRenderer.makeFileDiffHtml(file, diffs); ++ ++ const expected = ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' my/file/name.js\n' + ++ ' DELETED\n' + ++ "
    \n" + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' \n' + ++ " Random Html\n" + ++ " \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    "; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ it("should work for simple renamed file", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); ++ ++ const file = { ++ addedLines: 12, ++ deletedLines: 41, ++ language: "js", ++ oldName: "my/file/name1.js", ++ newName: "my/file/name2.js", ++ isRename: true, ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [] ++ }; ++ const diffs = "Random Html"; ++ ++ const fileHtml = lineByLineRenderer.makeFileDiffHtml(file, diffs); ++ ++ const expected = ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' my/file/{name1.js → name2.js}\n' + ++ ' RENAMED\n' + ++ "
    \n" + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' \n' + ++ " Random Html\n" + ++ " \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    "; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ it("should return empty when option renderNothingWhenEmpty is true and file blocks not present", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, { ++ renderNothingWhenEmpty: true ++ }); ++ ++ const file = { ++ addedLines: 0, ++ deletedLines: 0, ++ language: "js", ++ oldName: "my/file/name1.js", ++ newName: "my/file/name2.js", ++ isRename: true, ++ isCombined: false, ++ isGitDiff: false, ++ blocks: [] ++ }; ++ ++ const diffs = "Random Html"; ++ ++ const fileHtml = lineByLineRenderer.makeFileDiffHtml(file, diffs); ++ ++ const expected = ""; ++ ++ expect(fileHtml).toEqual(expected); ++ }); ++ }); ++ ++ describe("generateLineByLineJsonHtml", () => { ++ it("should work for list of files", () => { ++ const exampleJson: DiffFile[] = [ ++ { ++ blocks: [ ++ { ++ lines: [ ++ { ++ content: "-test", ++ type: LineType.DELETE, ++ oldNumber: 1, ++ newNumber: undefined ++ }, ++ { ++ content: "+test1r", ++ type: LineType.INSERT, ++ oldNumber: undefined, ++ newNumber: 1 ++ } ++ ], ++ oldStartLine: 1, ++ oldStartLine2: undefined, ++ newStartLine: 1, ++ header: "@@ -1 +1 @@" ++ } ++ ], ++ deletedLines: 1, ++ addedLines: 1, ++ checksumBefore: "0000001", ++ checksumAfter: "0ddf2ba", ++ oldName: "sample", ++ newName: "sample", ++ language: "txt", ++ isCombined: false, ++ isGitDiff: true ++ } ++ ]; ++ ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, { ++ matching: LineMatchingType.LINES ++ }); ++ const html = lineByLineRenderer.render(exampleJson); ++ const expected = ++ '
    \n' + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' sample\n' + ++ ' CHANGED\n' + ++ "
    \n" + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' \n' + ++ " \n" + ++ ' \n' + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "\n" + ++ " \n" + ++ "
    \n' + ++ '
    @@ -1 +1 @@
    \n' + ++ "
    \n' + ++ '
    1
    \n' + ++ '
    \n' + ++ "
    \n' + ++ '
    \n' + ++ ' -\n' + ++ ' test\n' + ++ "
    \n" + ++ "
    \n' + ++ '
    \n' + ++ '
    1
    \n' + ++ "
    \n' + ++ '
    \n' + ++ ' +\n' + ++ ' test1r\n' + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    "; ++ ++ expect(html).toEqual(expected); ++ }); ++ ++ it("should work for empty blocks", () => { ++ const exampleJson = [ ++ { ++ blocks: [], ++ deletedLines: 0, ++ addedLines: 0, ++ oldName: "sample", ++ language: "js", ++ newName: "sample", ++ isCombined: false, ++ isGitDiff: false ++ } ++ ]; ++ ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, { ++ renderNothingWhenEmpty: false ++ }); ++ const html = lineByLineRenderer.render(exampleJson); ++ const expected = ++ '
    \n' + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' sample\n' + ++ ' CHANGED\n' + ++ "
    \n" + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' \n' + ++ " \n" + ++ ' \n" + ++ "\n" + ++ " \n" + ++ "
    \n' + ++ '
    \n' + ++ " File without changes\n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    "; ++ ++ expect(html).toEqual(expected); ++ }); ++ }); ++ ++ describe("_generateFileHtml", () => { ++ it("should work for simple file", () => { ++ const hoganUtils = new HoganJsUtils({}); ++ const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); ++ const file: DiffFile = { ++ blocks: [ ++ { ++ lines: [ ++ { ++ content: " one context line", ++ type: LineType.CONTEXT, ++ oldNumber: 1, ++ newNumber: 1 ++ }, ++ { ++ content: "-test", ++ type: LineType.DELETE, ++ oldNumber: 2, ++ newNumber: undefined ++ }, ++ { ++ content: "+test1r", ++ type: LineType.INSERT, ++ oldNumber: undefined, ++ newNumber: 2 ++ }, ++ { ++ content: "+test2r", ++ type: LineType.INSERT, ++ oldNumber: undefined, ++ newNumber: 3 ++ } ++ ], ++ oldStartLine: 1, ++ oldStartLine2: undefined, ++ newStartLine: 1, ++ header: "@@ -1 +1 @@" ++ } ++ ], ++ deletedLines: 1, ++ addedLines: 1, ++ checksumBefore: "0000001", ++ checksumAfter: "0ddf2ba", ++ oldName: "sample", ++ language: "txt", ++ newName: "sample", ++ isCombined: false, ++ isGitDiff: true ++ }; ++ ++ const html = lineByLineRenderer.generateFileHtml(file); ++ ++ const expected = ++ "
    \n' + ++ '
    @@ -1 +1 @@
    \n' + ++ "
    \n' + ++ '
    1
    \n' + ++ '
    1
    \n' + ++ "
    \n' + ++ '
    \n' + ++ '  \n' + ++ ' one context line\n' + ++ "
    \n" + ++ "
    \n' + ++ '
    2
    \n' + ++ '
    \n' + ++ "
    \n' + ++ '
    \n' + ++ ' -\n' + ++ ' test\n' + ++ "
    \n" + ++ "
    \n' + ++ '
    \n' + ++ '
    2
    \n' + ++ "
    \n' + ++ '
    \n' + ++ ' +\n' + ++ ' test1r\n' + ++ "
    \n" + ++ "
    \n' + ++ '
    \n' + ++ '
    3
    \n' + ++ "
    \n' + ++ '
    \n' + ++ ' +\n' + ++ ' test2r\n' + ++ "
    \n" + ++ "
    \n' + ++ '
    \n' + ++ " File without changes\n" + ++ "
    \n" + ++ "
    \n' + ++ '
    @@ -19,7 +19,7 @@
    \n' + ++ "
    \n' + ++ " 19\n" + ++ " \n' + ++ '
    \n' + ++ '  \n' + ++ ' context\n' + ++ "
    \n" + ++ "
    \n' + ++ " 20\n" + ++ " \n' + ++ '
    \n' + ++ ' -\n' + ++ ' removed\n' + ++ "
    \n" + ++ "
    \n' + ++ " " + ++ "\n" + ++ " \n' + ++ '
    \n' + ++ '  \n' + ++ '  \n' + ++ "
    \n" + ++ "
    \n' + ++ '
    \n' + ++ "
    \n' + ++ " 19\n" + ++ " \n' + ++ '
    \n' + ++ '  \n' + ++ ' context\n' + ++ "
    \n" + ++ "
    \n' + ++ " 20\n" + ++ " \n' + ++ '
    \n' + ++ ' +\n' + ++ ' added\n' + ++ "
    \n" + ++ "
    \n' + ++ " 21\n" + ++ " \n' + ++ '
    \n' + ++ ' +\n' + ++ ' another added\n' + ++ "
    \n" + ++ "
    \n' + ++ " \n" + ++ " \n' + ++ '
    \n' + ++ '  \n' + ++ '  \n' + ++ "
    \n" + ++ "
    \n' + ++ " 30\n" + ++ " \n' + ++ '
    \n' + ++ ' +\n' + ++ ' test\n' + ++ "
    \n" + ++ "
    \n' + ++ " 30\n" + ++ " \n' + ++ '
    \n' + ++ ' -\n' + ++ ' test\n' + ++ "
    \n" + ++ "
    \n' + ++ " \n" + ++ " \n' + ++ '
    \n' + ++ '  \n' + ++ '  \n' + ++ "
    \n" + ++ "
    \n' + ++ ' \n' + ++ " \n" + ++ ' \n' + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "\n" + ++ " \n" + ++ "
    \n' + ++ '
    @@ -1 +1 @@
    \n' + ++ "
    \n' + ++ " 1\n" + ++ " \n' + ++ '
    \n' + ++ ' -\n' + ++ ' test\n' + ++ "
    \n" + ++ "
    \n" + ++ " \n" + ++ " \n" + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' \n' + ++ " \n" + ++ ' \n' + ++ ' \n" + ++ "\n" + ++ ' \n" + ++ ' \n" + ++ "\n" + ++ " \n" + ++ "
    \n' + ++ '
    \n' + ++ "
    \n' + ++ " 1\n" + ++ " \n' + ++ '
    \n' + ++ ' +\n' + ++ ' test1r\n' + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ " \n" + ++ "\n" + ++ ""; ++ ++ expect(html).toEqual(expected); ++ }); ++ it("should work for files without blocks", () => { ++ const exampleJson: DiffFile[] = [ ++ { ++ blocks: [], ++ oldName: "sample", ++ language: "js", ++ newName: "sample", ++ isCombined: false, ++ addedLines: 0, ++ deletedLines: 0, ++ isGitDiff: false ++ } ++ ]; ++ ++ const hoganUtils = new HoganJsUtils({}); ++ const sideBySideRenderer = new SideBySideRenderer(hoganUtils, {}); ++ const html = sideBySideRenderer.render(exampleJson); ++ const expected = ++ '
    \n' + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' sample\n' + ++ ' CHANGED\n' + ++ "
    \n" + ++ '
    \n' + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' \n' + ++ " \n" + ++ ' \n" + ++ "\n" + ++ " \n" + ++ "
    \n' + ++ '
    \n' + ++ " File without changes\n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ '
    \n' + ++ '
    \n' + ++ ' \n' + ++ ' \n' + ++ " \n" + ++ " \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    \n" + ++ "
    "; ++ ++ expect(html).toEqual(expected); ++ }); ++ }); ++ ++ describe("processLines", () => { ++ it("should process file lines", () => { ++ const oldLines: DiffLine[] = [ ++ { ++ content: "-test", ++ type: LineType.DELETE, ++ oldNumber: 1, ++ newNumber: undefined ++ } ++ ]; ++ ++ const newLines: DiffLine[] = [ ++ { ++ content: "+test1r", ++ type: LineType.INSERT, ++ oldNumber: undefined, ++ newNumber: 1 ++ } ++ ]; ++ ++ const hoganUtils = new HoganJsUtils({}); ++ const sideBySideRenderer = new SideBySideRenderer(hoganUtils, { matching: LineMatchingType.LINES }); ++ const html = sideBySideRenderer.processChangedLines(false, oldLines, newLines); ++ const expected = { ++ left: ++ "
    \n' + ++ " 1\n" + ++ " \n' + ++ '
    \n' + ++ ' -\n' + ++ ' test\n' + ++ "
    \n" + ++ "
    \n' + ++ " 1\n" + ++ " \n' + ++ '
    \n' + ++ ' +\n' + ++ ' test1r\n' + ++ "
    \n" + ++ "
    ");t.b("\n" + i);t.b("
    ");t.b(t.t(t.f("blockHeader",c,p,0)));t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b(" File without changes");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b(" ");t.b(t.t(t.f("lineNumber",c,p,0)));t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);if(t.s(t.f("prefix",c,p,1),c,p,0,171,247,"{{ }}")){t.rs(c,p,function(c,p,t){t.b(" ");t.b(t.t(t.f("prefix",c,p,0)));t.b("");t.b("\n" + i);});c.pop();}if(t.s(t.f("content",c,p,1),c,p,0,279,353,"{{ }}")){t.rs(c,p,function(c,p,t){t.b(" ");t.b(t.t(t.f("content",c,p,0)));t.b("");t.b("\n" + i);});c.pop();}t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b(t.t(t.f("diffs",c,p,0)));t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["line-by-line-numbers"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("
    ");t.b(t.v(t.f("oldNumber",c,p,0)));t.b("
    ");t.b("\n" + i);t.b("
    ");t.b(t.v(t.f("newNumber",c,p,0)));t.b("
    ");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["side-by-side-file-diff"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b(" ");t.b(t.t(t.f("filePath",c,p,0)));t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b(t.t(t.d("diffs.left",c,p,0)));t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b(" ");t.b(t.t(t.d("diffs.right",c,p,0)));t.b("\n" + i);t.b(" ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");t.b("\n" + i);t.b("
    ");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["tag-file-added"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("ADDED");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["tag-file-changed"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("CHANGED");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["tag-file-deleted"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("DELETED");return t.fl(); },partials: {}, subs: { }}); +-global.browserTemplates["tag-file-renamed"] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("RENAMED");return t.fl(); },partials: {}, subs: { }}); +-module.exports = global.browserTemplates; +-})(); +diff --git a/src/templates/generic-block-header.mustache b/src/templates/generic-block-header.mustache +new file mode 100644 +index 00000000..caf1c299 +--- /dev/null ++++ b/src/templates/generic-block-header.mustache +@@ -0,0 +1,6 @@ ++ ++ ++ ++
    {{{blockHeader}}}
    ++ ++ +diff --git a/src/templates/generic-column-line-number.mustache b/src/templates/generic-column-line-number.mustache +deleted file mode 100644 +index 181d6518..00000000 +--- a/src/templates/generic-column-line-number.mustache ++++ /dev/null +@@ -1,6 +0,0 @@ +- +- +- +-
    {{{blockHeader}}}
    +- +- +diff --git a/src/templates/generic-empty-diff.mustache b/src/templates/generic-empty-diff.mustache +index c6b1abdf..362e31fa 100644 +--- a/src/templates/generic-empty-diff.mustache ++++ b/src/templates/generic-empty-diff.mustache +@@ -1,6 +1,6 @@ + +- +-
    ++ ++
    + File without changes +
    + +diff --git a/src/types.ts b/src/types.ts +new file mode 100644 +index 00000000..f080f169 +--- /dev/null ++++ b/src/types.ts +@@ -0,0 +1,86 @@ ++export type DiffLineParts = { ++ prefix: string; ++ content: string; ++}; ++ ++export enum LineType { ++ INSERT = "insert", ++ DELETE = "delete", ++ CONTEXT = "context" ++} ++ ++export interface DiffLineDeleted { ++ type: LineType.DELETE; ++ oldNumber: number; ++ newNumber: undefined; ++} ++ ++export interface DiffLineInserted { ++ type: LineType.INSERT; ++ oldNumber: undefined; ++ newNumber: number; ++} ++ ++export interface DiffLineContext { ++ type: LineType.CONTEXT; ++ oldNumber: number; ++ newNumber: number; ++} ++ ++export type DiffLineContent = { ++ content: string; ++}; ++ ++export type DiffLine = (DiffLineDeleted | DiffLineInserted | DiffLineContext) & DiffLineContent; ++ ++export interface DiffBlock { ++ oldStartLine: number; ++ oldStartLine2?: number; ++ newStartLine: number; ++ header: string; ++ lines: DiffLine[]; ++} ++ ++export interface DiffFileName { ++ oldName: string; ++ newName: string; ++} ++ ++export interface DiffFile extends DiffFileName { ++ addedLines: number; ++ deletedLines: number; ++ isCombined: boolean; ++ isGitDiff: boolean; ++ language: string; ++ blocks: DiffBlock[]; ++ oldMode?: string | string[]; ++ newMode?: string; ++ deletedFileMode?: string; ++ newFileMode?: string; ++ isDeleted?: boolean; ++ isNew?: boolean; ++ isCopy?: boolean; ++ isRename?: boolean; ++ isBinary?: boolean; ++ unchangedPercentage?: number; ++ changedPercentage?: number; ++ checksumBefore?: string | string[]; ++ checksumAfter?: string; ++ mode?: string; ++} ++ ++export enum OutputFormatType { ++ LINE_BY_LINE = "line-by-line", ++ SIDE_BY_SIDE = "side-by-side" ++} ++ ++export enum LineMatchingType { ++ LINES = "lines", ++ WORDS = "words", ++ NONE = "none" ++} ++ ++export enum DiffStyleType { ++ WORD = "word", ++ CHAR = "char" ++} +diff --git a/src/ui/js/diff2html-ui.js b/src/ui/js/diff2html-ui.js +deleted file mode 100644 +index 979939b5..00000000 +--- a/src/ui/js/diff2html-ui.js ++++ /dev/null +@@ -1,219 +0,0 @@ +-/* +- * +- * Diff to HTML (diff2html-ui.js) +- * Author: rtfpessoa +- * +- * Depends on: [ jQuery ] +- * Optional dependencies on: [ highlight.js ] +- * +- */ +- +-/*global $, hljs, Diff2Html*/ +- +-(function() { +- var highlightJS = require('./highlight.js-internals.js').HighlightJS; +- +- var diffJson = null; +- var defaultTarget = 'body'; +- var currentSelectionColumnId = -1; +- +- function Diff2HtmlUI(config) { +- var cfg = config || {}; +- +- if (cfg.diff) { +- diffJson = Diff2Html.getJsonFromDiff(cfg.diff); +- } else if (cfg.json) { +- diffJson = cfg.json; +- } +- +- this._initSelection(); +- } +- +- Diff2HtmlUI.prototype.draw = function(targetId, config) { +- var cfg = config || {}; +- cfg.inputFormat = 'json'; +- var $target = this._getTarget(targetId); +- $target.html(Diff2Html.getPrettyHtml(diffJson, cfg)); +- +- if (cfg.synchronisedScroll) { +- this.synchronisedScroll($target, cfg); +- } +- }; +- +- Diff2HtmlUI.prototype.synchronisedScroll = function(targetId) { +- var $target = this._getTarget(targetId); +- $target.find('.d2h-file-side-diff').scroll(function() { +- var $this = $(this); +- $this.closest('.d2h-file-wrapper').find('.d2h-file-side-diff') +- .scrollLeft($this.scrollLeft()); +- }); +- }; +- +- Diff2HtmlUI.prototype.fileListCloseable = function(targetId, startVisible) { +- var $target = this._getTarget(targetId); +- +- var hashTag = this._getHashTag(); +- +- var $showBtn = $target.find('.d2h-show'); +- var $hideBtn = $target.find('.d2h-hide'); +- var $fileList = $target.find('.d2h-file-list'); +- +- if (hashTag === 'files-summary-show') show(); +- else if (hashTag === 'files-summary-hide') hide(); +- else if (startVisible) show(); +- else hide(); +- +- $showBtn.click(show); +- $hideBtn.click(hide); +- +- function show() { +- $showBtn.hide(); +- $hideBtn.show(); +- $fileList.show(); +- } +- +- function hide() { +- $hideBtn.hide(); +- $showBtn.show(); +- $fileList.hide(); +- } +- }; +- +- Diff2HtmlUI.prototype.highlightCode = function(targetId) { +- var that = this; +- +- var $target = that._getTarget(targetId); +- +- // collect all the diff files and execute the highlight on their lines +- var $files = $target.find('.d2h-file-wrapper'); +- $files.map(function(_i, file) { +- var oldLinesState; +- var newLinesState; +- var $file = $(file); +- var language = $file.data('lang'); +- +- // collect all the code lines and execute the highlight on them +- var $codeLines = $file.find('.d2h-code-line-ctn'); +- $codeLines.map(function(_j, line) { +- var $line = $(line); +- var text = line.textContent; +- var lineParent = line.parentNode; +- +- var lineState; +- if (lineParent.className.indexOf('d2h-del') !== -1) { +- lineState = oldLinesState; +- } else { +- lineState = newLinesState; +- } +- +- var result = hljs.getLanguage(language) ? hljs.highlight(language, text, true, lineState) : hljs.highlightAuto(text); +- +- if (lineParent.className.indexOf('d2h-del') !== -1) { +- oldLinesState = result.top; +- } else if (lineParent.className.indexOf('d2h-ins') !== -1) { +- newLinesState = result.top; +- } else { +- oldLinesState = result.top; +- newLinesState = result.top; +- } +- +- var originalStream = highlightJS.nodeStream(line); +- if (originalStream.length) { +- var resultNode = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); +- resultNode.innerHTML = result.value; +- result.value = highlightJS.mergeStreams(originalStream, highlightJS.nodeStream(resultNode), text); +- } +- +- $line.addClass('hljs'); +- $line.addClass(result.language); +- $line.html(result.value); +- }); +- }); +- }; +- +- Diff2HtmlUI.prototype._getTarget = function(targetId) { +- var $target; +- +- if (typeof targetId === 'object' && targetId instanceof jQuery) { +- $target = targetId; +- } else if (typeof targetId === 'string') { +- $target = $(targetId); +- } else { +- console.error("Wrong target provided! Falling back to default value 'body'."); +- console.log('Please provide a jQuery object or a valid DOM query string.'); +- $target = $(defaultTarget); +- } +- +- return $target; +- }; +- +- Diff2HtmlUI.prototype._getHashTag = function() { +- var docUrl = document.URL; +- var hashTagIndex = docUrl.indexOf('#'); +- +- var hashTag = null; +- if (hashTagIndex !== -1) { +- hashTag = docUrl.substr(hashTagIndex + 1); +- } +- +- return hashTag; +- }; +- +- Diff2HtmlUI.prototype._distinct = function(collection) { +- return collection.filter(function(v, i) { +- return collection.indexOf(v) === i; +- }); +- }; +- +- Diff2HtmlUI.prototype._initSelection = function() { +- var body = $('body'); +- var that = this; +- +- body.on('mousedown', '.d2h-diff-table', function(event) { +- var target = $(event.target); +- var table = target.closest('.d2h-diff-table'); +- +- if (target.closest('.d2h-code-line,.d2h-code-side-line').length) { +- table.removeClass('selecting-left'); +- table.addClass('selecting-right'); +- currentSelectionColumnId = 1; +- } else if (target.closest('.d2h-code-linenumber,.d2h-code-side-linenumber').length) { +- table.removeClass('selecting-right'); +- table.addClass('selecting-left'); +- currentSelectionColumnId = 0; +- } +- }); +- +- body.on('copy', '.d2h-diff-table', function(event) { +- var clipboardData = event.originalEvent.clipboardData; +- var text = that._getSelectedText(); +- clipboardData.setData('text', text); +- event.preventDefault(); +- }); +- }; +- +- Diff2HtmlUI.prototype._getSelectedText = function() { +- var sel = window.getSelection(); +- var range = sel.getRangeAt(0); +- var doc = range.cloneContents(); +- var nodes = doc.querySelectorAll('tr'); +- var text = ''; +- var idx = currentSelectionColumnId; +- +- if (nodes.length === 0) { +- text = doc.textContent; +- } else { +- [].forEach.call(nodes, function(tr, i) { +- var td = tr.cells[tr.cells.length === 1 ? 0 : idx]; +- text += (i ? '\n' : '') + td.textContent.replace(/(?:\r\n|\r|\n)/g, ''); +- }); +- } +- +- return text; +- }; +- +- module.exports.Diff2HtmlUI = Diff2HtmlUI; +- +- // Expose diff2html in the browser +- global.Diff2HtmlUI = Diff2HtmlUI; +-})(); +diff --git a/src/ui/js/diff2html-ui.ts b/src/ui/js/diff2html-ui.ts +new file mode 100644 +index 00000000..d64bc873 +--- /dev/null ++++ b/src/ui/js/diff2html-ui.ts +@@ -0,0 +1,223 @@ ++import HighlightJS from "highlight.js"; ++import * as HighlightJSInternals from "./highlight.js-internals"; ++import { html, Diff2HtmlConfig, defaultDiff2HtmlConfig } from "../../diff2html"; ++import { DiffFile } from "../../types"; ++ ++export interface Diff2HtmlUIConfig extends Diff2HtmlConfig { ++ synchronisedScroll?: boolean; ++ highlight?: boolean; ++ fileListToggle?: boolean; ++ fileListStartVisible?: boolean; ++ smartSelection?: boolean; ++} ++ ++export const defaultDiff2HtmlUIConfig = { ++ ...defaultDiff2HtmlConfig, ++ synchronisedScroll: true, ++ highlight: true, ++ fileListToggle: true, ++ fileListStartVisible: false, ++ smartSelection: true ++}; ++ ++export class Diff2HtmlUI { ++ readonly config: typeof defaultDiff2HtmlUIConfig; ++ readonly diffHtml: string; ++ targetElement: HTMLElement; ++ currentSelectionColumnId = -1; ++ ++ constructor(diffInput: string | DiffFile[], target: HTMLElement, config: Diff2HtmlUIConfig = {}) { ++ this.config = { ...defaultDiff2HtmlUIConfig, ...config }; ++ this.diffHtml = html(diffInput, this.config); ++ this.targetElement = target; ++ } ++ ++ draw(): void { ++ this.targetElement.innerHTML = this.diffHtml; ++ if (this.config.smartSelection) this.initSelection(); ++ if (this.config.synchronisedScroll) this.synchronisedScroll(); ++ if (this.config.highlight) this.highlightCode(); ++ if (this.config.fileListToggle) this.fileListToggle(this.config.fileListStartVisible); ++ } ++ ++ synchronisedScroll(): void { ++ this.targetElement.querySelectorAll(".d2h-file-wrapper").forEach(wrapper => { ++ const [left, right] = [].slice.call(wrapper.querySelectorAll(".d2h-file-side-diff")) as HTMLElement[]; ++ if (left === undefined || right === undefined) return; ++ const onScroll = (event: Event): void => { ++ if (event === null || event.target === null) return; ++ if (event.target === left) { ++ right.scrollTop = left.scrollTop; ++ right.scrollLeft = left.scrollLeft; ++ } else { ++ left.scrollTop = right.scrollTop; ++ left.scrollLeft = right.scrollLeft; ++ } ++ }; ++ left.addEventListener("scroll", onScroll); ++ right.addEventListener("scroll", onScroll); ++ }); ++ } ++ ++ fileListToggle(startVisible: boolean): void { ++ const hashTag = this.getHashTag(); ++ ++ const showBtn = this.targetElement.querySelector(".d2h-show") as HTMLElement; ++ const hideBtn = this.targetElement.querySelector(".d2h-hide") as HTMLElement; ++ const fileList = this.targetElement.querySelector(".d2h-file-list") as HTMLElement; ++ ++ if (showBtn === null || hideBtn === null || fileList === null) return; ++ ++ function show(): void { ++ showBtn.style.display = "none"; ++ hideBtn.style.display = "inline"; ++ fileList.style.display = "block"; ++ } ++ ++ function hide(): void { ++ showBtn.style.display = "inline"; ++ hideBtn.style.display = "none"; ++ fileList.style.display = "none"; ++ } ++ ++ showBtn.addEventListener("click", () => show()); ++ hideBtn.addEventListener("click", () => hide()); ++ ++ if (hashTag === "files-summary-show") show(); ++ else if (hashTag === "files-summary-hide") hide(); ++ else if (startVisible) show(); ++ else hide(); ++ } ++ ++ highlightCode(): void { ++ // Collect all the diff files and execute the highlight on their lines ++ const files = this.targetElement.querySelectorAll(".d2h-file-wrapper"); ++ files.forEach(file => { ++ let oldLinesState: HighlightJS.ICompiledMode; ++ let newLinesState: HighlightJS.ICompiledMode; ++ ++ // Collect all the code lines and execute the highlight on them ++ const codeLines = file.querySelectorAll(".d2h-code-line-ctn"); ++ codeLines.forEach(line => { ++ const text = line.textContent; ++ const lineParent = line.parentNode as HTMLElement; ++ ++ if (lineParent === null || text === null) return; ++ ++ const lineState = lineParent.className.indexOf("d2h-del") !== -1 ? oldLinesState : newLinesState; ++ ++ const language = file.getAttribute("data-lang"); ++ const result = ++ language && HighlightJS.getLanguage(language) ++ ? HighlightJS.highlight(language, text, true, lineState) ++ : HighlightJS.highlightAuto(text); ++ ++ if (this.instanceOfIHighlightResult(result)) { ++ if (lineParent.className.indexOf("d2h-del") !== -1) { ++ oldLinesState = result.top; ++ } else if (lineParent.className.indexOf("d2h-ins") !== -1) { ++ newLinesState = result.top; ++ } else { ++ oldLinesState = result.top; ++ newLinesState = result.top; ++ } ++ } ++ ++ const originalStream = HighlightJSInternals.nodeStream(line); ++ if (originalStream.length) { ++ const resultNode = document.createElementNS("http://www.w3.org/1999/xhtml", "div"); ++ resultNode.innerHTML = result.value; ++ result.value = HighlightJSInternals.mergeStreams( ++ originalStream, ++ HighlightJSInternals.nodeStream(resultNode), ++ text ++ ); ++ } ++ ++ line.classList.add("hljs"); ++ line.classList.add("result.language"); ++ line.innerHTML = result.value; ++ }); ++ }); ++ } ++ ++ private instanceOfIHighlightResult( ++ object: HighlightJS.IHighlightResult | HighlightJS.IAutoHighlightResult ++ ): object is HighlightJS.IHighlightResult { ++ return "top" in object; ++ } ++ ++ private getHashTag(): string | null { ++ const docUrl = document.URL; ++ const hashTagIndex = docUrl.indexOf("#"); ++ ++ let hashTag = null; ++ if (hashTagIndex !== -1) { ++ hashTag = docUrl.substr(hashTagIndex + 1); ++ } ++ ++ return hashTag; ++ } ++ ++ private initSelection(): void { ++ const body = document.getElementsByTagName("body")[0]; ++ const diffTable = body.getElementsByClassName("d2h-diff-table")[0]; ++ ++ diffTable.addEventListener("mousedown", event => { ++ if (event === null || event.target === null) return; ++ ++ const mouseEvent = event as MouseEvent; ++ const target = mouseEvent.target as HTMLElement; ++ const table = target.closest(".d2h-diff-table"); ++ ++ if (table !== null) { ++ if (target.closest(".d2h-code-line,.d2h-code-side-line") !== null) { ++ table.classList.remove("selecting-left"); ++ table.classList.add("selecting-right"); ++ this.currentSelectionColumnId = 1; ++ } else if (target.closest(".d2h-code-linenumber,.d2h-code-side-linenumber") !== null) { ++ table.classList.remove("selecting-right"); ++ table.classList.add("selecting-left"); ++ this.currentSelectionColumnId = 0; ++ } ++ } ++ }); ++ ++ diffTable.addEventListener("copy", event => { ++ const clipboardEvent = event as ClipboardEvent; ++ const clipboardData = clipboardEvent.clipboardData; ++ const text = this.getSelectedText(); ++ ++ if (clipboardData === null || text === undefined) return; ++ ++ clipboardData.setData("text", text); ++ event.preventDefault(); ++ }); ++ } ++ ++ private getSelectedText(): string | undefined { ++ const sel = window.getSelection(); ++ ++ if (sel === null) return; ++ ++ const range = sel.getRangeAt(0); ++ const doc = range.cloneContents(); ++ const nodes = doc.querySelectorAll("tr"); ++ const idx = this.currentSelectionColumnId; ++ ++ let text = ""; ++ if (nodes.length === 0) { ++ text = doc.textContent || ""; ++ } else { ++ nodes.forEach((tr, i) => { ++ const td = tr.cells[tr.cells.length === 1 ? 0 : idx]; ++ ++ if (td === undefined || td.textContent === null) return; ++ ++ text += (i ? "\n" : "") + td.textContent.replace(/(?:\r\n|\r|\n)/g, ""); ++ }); ++ } ++ ++ return text; ++ } ++} +diff --git a/src/ui/js/highlight.js-internals.js b/src/ui/js/highlight.js-internals.js +deleted file mode 100644 +index 52a1ccd9..00000000 +--- a/src/ui/js/highlight.js-internals.js ++++ /dev/null +@@ -1,140 +0,0 @@ +-/* +- * +- * highlight.js +- * Author: isagalaev +- * +- */ +- +-(function() { +- function HighlightJS() { +- } +- +- /* +- * Copied from Highlight.js Private API +- * Will be removed when this part of the API is exposed +- */ +- +- /* Utility vars */ +- +- var ArrayProto = []; +- +- /* Utility functions */ +- +- function escape(value) { +- return value.replace(/&/gm, '&').replace(//gm, '>'); +- } +- +- function tag(node) { +- return node.nodeName.toLowerCase(); +- } +- +- /* Stream merging */ +- +- HighlightJS.prototype.nodeStream = function(node) { +- var result = []; +- (function _nodeStream(node, offset) { +- for (var child = node.firstChild; child; child = child.nextSibling) { +- if (child.nodeType === 3) { +- offset += child.nodeValue.length; +- } else if (child.nodeType === 1) { +- result.push({ +- event: 'start', +- offset: offset, +- node: child +- }); +- offset = _nodeStream(child, offset); +- // Prevent void elements from having an end tag that would actually +- // double them in the output. There are more void elements in HTML +- // but we list only those realistically expected in code display. +- if (!tag(child).match(/br|hr|img|input/)) { +- result.push({ +- event: 'stop', +- offset: offset, +- node: child +- }); +- } +- } +- } +- return offset; +- })(node, 0); +- return result; +- }; +- +- HighlightJS.prototype.mergeStreams = function(original, highlighted, value) { +- var processed = 0; +- var result = ''; +- var nodeStack = []; +- +- function selectStream() { +- if (!original.length || !highlighted.length) { +- return original.length ? original : highlighted; +- } +- if (original[0].offset !== highlighted[0].offset) { +- return (original[0].offset < highlighted[0].offset) ? original : highlighted; +- } +- +- /* +- To avoid starting the stream just before it should stop the order is +- ensured that original always starts first and closes last: +- if (event1 == 'start' && event2 == 'start') +- return original; +- if (event1 == 'start' && event2 == 'stop') +- return highlighted; +- if (event1 == 'stop' && event2 == 'start') +- return original; +- if (event1 == 'stop' && event2 == 'stop') +- return highlighted; +- ... which is collapsed to: +- */ +- return highlighted[0].event === 'start' ? original : highlighted; +- } +- +- function open(node) { +- function attr_str(a) { +- return ' ' + a.nodeName + '="' + escape(a.value) + '"'; +- } +- +- result += '<' + tag(node) + ArrayProto.map.call(node.attributes, attr_str).join('') + '>'; +- } +- +- function close(node) { +- result += ''; +- } +- +- function render(event) { +- (event.event === 'start' ? open : close)(event.node); +- } +- +- while (original.length || highlighted.length) { +- var stream = selectStream(); +- result += escape(value.substring(processed, stream[0].offset)); +- processed = stream[0].offset; +- if (stream === original) { +- /* +- On any opening or closing tag of the original markup we first close +- the entire highlighted node stack, then render the original tag along +- with all the following original tags at the same offset and then +- reopen all the tags on the highlighted stack. +- */ +- nodeStack.reverse().forEach(close); +- do { +- render(stream.splice(0, 1)[0]); +- stream = selectStream(); +- } while (stream === original && stream.length && stream[0].offset === processed); +- nodeStack.reverse().forEach(open); +- } else { +- if (stream[0].event === 'start') { +- nodeStack.push(stream[0].node); +- } else { +- nodeStack.pop(); +- } +- render(stream.splice(0, 1)[0]); +- } +- } +- return result + escape(value.substr(processed)); +- }; +- +- /* **** Highlight.js Private API **** */ +- +- module.exports.HighlightJS = new HighlightJS(); +-})(); +diff --git a/src/ui/js/highlight.js-internals.ts b/src/ui/js/highlight.js-internals.ts +new file mode 100644 +index 00000000..740d75da +--- /dev/null ++++ b/src/ui/js/highlight.js-internals.ts +@@ -0,0 +1,134 @@ ++/* ++ * Copied from Highlight.js Private API ++ * Will be removed when this part of the API is exposed ++ */ ++ ++/* Utility functions */ ++ ++function escape(value: string): string { ++ return value ++ .replace(/&/gm, "&") ++ .replace(//gm, ">"); ++} ++ ++function tag(node: Node): string { ++ return node.nodeName.toLowerCase(); ++} ++ ++/* Stream merging */ ++ ++type NodeEvent = { ++ event: "start" | "stop"; ++ offset: number; ++ node: Node; ++}; ++ ++export function nodeStream(node: Node): NodeEvent[] { ++ const result: NodeEvent[] = []; ++ ++ const nodeStream = (node: Node, offset: number): number => { ++ for (let child = node.firstChild; child; child = child.nextSibling) { ++ if (child.nodeType === 3 && child.nodeValue !== null) { ++ offset += child.nodeValue.length; ++ } else if (child.nodeType === 1) { ++ result.push({ ++ event: "start", ++ offset: offset, ++ node: child ++ }); ++ offset = nodeStream(child, offset); ++ // Prevent void elements from having an end tag that would actually ++ // double them in the output. There are more void elements in HTML ++ // but we list only those realistically expected in code display. ++ if (!tag(child).match(/br|hr|img|input/)) { ++ result.push({ ++ event: "stop", ++ offset: offset, ++ node: child ++ }); ++ } ++ } ++ } ++ return offset; ++ }; ++ ++ nodeStream(node, 0); ++ ++ return result; ++} ++ ++export function mergeStreams(original: NodeEvent[], highlighted: NodeEvent[], value: string): string { ++ let processed = 0; ++ let result = ""; ++ const nodeStack = []; ++ ++ function selectStream(): NodeEvent[] { ++ if (!original.length || !highlighted.length) { ++ return original.length ? original : highlighted; ++ } ++ if (original[0].offset !== highlighted[0].offset) { ++ return original[0].offset < highlighted[0].offset ? original : highlighted; ++ } ++ ++ /* ++ To avoid starting the stream just before it should stop the order is ++ ensured that original always starts first and closes last: ++ if (event1 == 'start' && event2 == 'start') ++ return original; ++ if (event1 == 'start' && event2 == 'stop') ++ return highlighted; ++ if (event1 == 'stop' && event2 == 'start') ++ return original; ++ if (event1 == 'stop' && event2 == 'stop') ++ return highlighted; ++ ... which is collapsed to: ++ */ ++ return highlighted[0].event === "start" ? original : highlighted; ++ } ++ ++ function open(node: Node): void { ++ const htmlNode = node as HTMLElement; ++ result += `<${tag(node)} ${[].map ++ .call(htmlNode.attributes, (attr: Attr) => `${attr.nodeName}="${escape(attr.value)}"`) ++ .join(" ")}>`; ++ } ++ ++ function close(node: Node): void { ++ result += ""; ++ } ++ ++ function render(event: NodeEvent): void { ++ (event.event === "start" ? open : close)(event.node); ++ } ++ ++ while (original.length || highlighted.length) { ++ let stream = selectStream(); ++ result += escape(value.substring(processed, stream[0].offset)); ++ processed = stream[0].offset; ++ if (stream === original) { ++ /* ++ On any opening or closing tag of the original markup we first close ++ the entire highlighted node stack, then render the original tag along ++ with all the following original tags at the same offset and then ++ reopen all the tags on the highlighted stack. ++ */ ++ nodeStack.reverse().forEach(close); ++ do { ++ render(stream.splice(0, 1)[0]); ++ stream = selectStream(); ++ } while (stream === original && stream.length && stream[0].offset === processed); ++ nodeStack.reverse().forEach(open); ++ } else { ++ if (stream[0].event === "start") { ++ nodeStack.push(stream[0].node); ++ } else { ++ nodeStack.pop(); ++ } ++ render(stream.splice(0, 1)[0]); ++ } ++ } ++ return result + escape(value.substr(processed)); ++} ++ ++/* **** Highlight.js Private API **** */ +diff --git a/src/utils.js b/src/utils.js +deleted file mode 100644 +index 395d2678..00000000 +--- a/src/utils.js ++++ /dev/null +@@ -1,48 +0,0 @@ +-/* +- * +- * Utils (utils.js) +- * Author: rtfpessoa +- * +- */ +- +-(function() { +- var merge = require('merge'); +- +- function Utils() { +- } +- +- Utils.prototype.escape = function(str) { +- return str.slice(0) +- .replace(/&/g, '&') +- .replace(//g, '>') +- .replace(/"/g, '"') +- .replace(/'/g, ''') +- .replace(/\//g, '/'); +- }; +- +- Utils.prototype.startsWith = function(str, start) { +- if (typeof start === 'object') { +- var result = false; +- start.forEach(function(s) { +- if (str.indexOf(s) === 0) { +- result = true; +- } +- }); +- +- return result; +- } +- +- return str && str.indexOf(start) === 0; +- }; +- +- Utils.prototype.valueOrEmpty = function(value) { +- return value || ''; +- }; +- +- Utils.prototype.safeConfig = function(cfg, defaultConfig) { +- return merge.recursive(true, defaultConfig, cfg); +- }; +- +- module.exports.Utils = new Utils(); +-})(); +diff --git a/src/utils.ts b/src/utils.ts +new file mode 100644 +index 00000000..649f23a8 +--- /dev/null ++++ b/src/utils.ts +@@ -0,0 +1,54 @@ ++const specials = [ ++ // Order matters for these ++ "-", ++ "[", ++ "]", ++ // Order doesn't matter for any of these ++ "/", ++ "{", ++ "}", ++ "(", ++ ")", ++ "*", ++ "+", ++ "?", ++ ".", ++ "\\", ++ "^", ++ "$", ++ "|" ++]; ++ ++// All characters will be escaped with '\' ++// even though only some strictly require it when inside of [] ++const regex = RegExp("[" + specials.join("\\") + "]", "g"); ++ ++/** ++ * Escapes all required characters for safe usage inside a RegExp ++ */ ++export function escapeForRegExp(str: string): string { ++ return str.replace(regex, "\\$&"); ++} ++ ++/** ++ * Converts all '\' in @path to unix style '/' ++ */ ++export function unifyPath(path: string): string { ++ return path ? path.replace(/\\/g, "/") : path; ++} ++ ++/** ++ * Create unique number identifier for @text ++ */ ++export function hashCode(text: string): number { ++ let i, chr, len; ++ let hash = 0; ++ ++ for (i = 0, len = text.length; i < len; i++) { ++ chr = text.charCodeAt(i); ++ hash = (hash << 5) - hash + chr; ++ hash |= 0; // Convert to 32bit integer ++ } ++ ++ return hash; ++} +diff --git a/test/diff-parser-tests.js b/test/diff-parser-tests.js +deleted file mode 100644 +index 2574c19d..00000000 +--- a/test/diff-parser-tests.js ++++ /dev/null +@@ -1,743 +0,0 @@ +-var assert = require('assert'); +- +-var DiffParser = require('../src/diff-parser.js').DiffParser; +- +-describe('DiffParser', function() { +- describe('generateDiffJson', function() { +- it('should parse unix with \n diff', function() { +- var diff = +- 'diff --git a/sample b/sample\n' + +- 'index 0000001..0ddf2ba\n' + +- '--- a/sample\n' + +- '+++ b/sample\n' + +- '@@ -1 +1 @@\n' + +- '-test\n' + +- '+test1r\n'; +- checkDiffSample(diff); +- }); +- +- it('should parse windows with \r\n diff', function() { +- var diff = +- 'diff --git a/sample b/sample\r\n' + +- 'index 0000001..0ddf2ba\r\n' + +- '--- a/sample\r\n' + +- '+++ b/sample\r\n' + +- '@@ -1 +1 @@\r\n' + +- '-test\r\n' + +- '+test1r\r\n'; +- checkDiffSample(diff); +- }); +- +- it('should parse old os x with \r diff', function() { +- var diff = +- 'diff --git a/sample b/sample\r' + +- 'index 0000001..0ddf2ba\r' + +- '--- a/sample\r' + +- '+++ b/sample\r' + +- '@@ -1 +1 @@\r' + +- '-test\r' + +- '+test1r\r'; +- checkDiffSample(diff); +- }); +- +- it('should parse mixed eols diff', function() { +- var diff = +- 'diff --git a/sample b/sample\n' + +- 'index 0000001..0ddf2ba\r\n' + +- '--- a/sample\r' + +- '+++ b/sample\r\n' + +- '@@ -1 +1 @@\n' + +- '-test\r' + +- '+test1r\n'; +- checkDiffSample(diff); +- }); +- +- function checkDiffSample(diff) { +- var result = DiffParser.generateDiffJson(diff); +- var file1 = result[0]; +- assert.equal(1, result.length); +- assert.equal(1, file1.addedLines); +- assert.equal(1, file1.deletedLines); +- assert.equal('sample', file1.oldName); +- assert.equal('sample', file1.newName); +- assert.equal(1, file1.blocks.length); +- } +- +- it('should parse diff with special characters', function() { +- var diff = +- 'diff --git "a/bla with \ttab.scala" "b/bla with \ttab.scala"\n' + +- 'index 4c679d7..e9bd385 100644\n' + +- '--- "a/bla with \ttab.scala"\n' + +- '+++ "b/bla with \ttab.scala"\n' + +- '@@ -1 +1,2 @@\n' + +- '-cenas\n' + +- '+cenas com ananas\n' + +- '+bananas'; +- +- var result = DiffParser.generateDiffJson(diff); +- var file1 = result[0]; +- assert.equal(1, result.length); +- assert.equal(2, file1.addedLines); +- assert.equal(1, file1.deletedLines); +- assert.equal('bla with \ttab.scala', file1.oldName); +- assert.equal('bla with \ttab.scala', file1.newName); +- assert.equal(1, file1.blocks.length); +- }); +- +- it('should parse diff with prefix', function() { +- var diff = +- 'diff --git "\tbla with \ttab.scala" "\tbla with \ttab.scala"\n' + +- 'index 4c679d7..e9bd385 100644\n' + +- '--- "\tbla with \ttab.scala"\n' + +- '+++ "\tbla with \ttab.scala"\n' + +- '@@ -1 +1,2 @@\n' + +- '-cenas\n' + +- '+cenas com ananas\n' + +- '+bananas'; +- +- var result = DiffParser.generateDiffJson(diff, {'srcPrefix': '\t', 'dstPrefix': '\t'}); +- var file1 = result[0]; +- assert.equal(1, result.length); +- assert.equal(2, file1.addedLines); +- assert.equal(1, file1.deletedLines); +- assert.equal('bla with \ttab.scala', file1.oldName); +- assert.equal('bla with \ttab.scala', file1.newName); +- assert.equal(1, file1.blocks.length); +- }); +- +- it('should parse diff with deleted file', function() { +- var diff = +- 'diff --git a/src/var/strundefined.js b/src/var/strundefined.js\n' + +- 'deleted file mode 100644\n' + +- 'index 04e16b0..0000000\n' + +- '--- a/src/var/strundefined.js\n' + +- '+++ /dev/null\n' + +- '@@ -1,3 +0,0 @@\n' + +- '-define(function() {\n' + +- '- return typeof undefined;\n' + +- '-});\n'; +- +- var result = DiffParser.generateDiffJson(diff); +- assert.equal(1, result.length); +- +- var file1 = result[0]; +- assert.equal(false, file1.isCombined); +- assert.equal(0, file1.addedLines); +- assert.equal(3, file1.deletedLines); +- assert.equal('src/var/strundefined.js', file1.oldName); +- assert.equal('/dev/null', file1.newName); +- assert.equal(1, file1.blocks.length); +- assert.equal(true, file1.isDeleted); +- assert.equal('04e16b0', file1.checksumBefore); +- assert.equal('0000000', file1.checksumAfter); +- }); +- +- it('should parse diff with new file', function() { +- var diff = +- 'diff --git a/test.js b/test.js\n' + +- 'new file mode 100644\n' + +- 'index 0000000..e1e22ec\n' + +- '--- /dev/null\n' + +- '+++ b/test.js\n' + +- '@@ -0,0 +1,5 @@\n' + +- "+var parser = require('./source/git-parser');\n" + +- '+\n' + +- '+var patchLineList = [ false, false, false, false ];\n' + +- '+\n' + +- '+console.log(parser.parsePatchDiffResult(text, patchLineList));\n'; +- +- var result = DiffParser.generateDiffJson(diff); +- assert.equal(1, result.length); +- +- var file1 = result[0]; +- assert.equal(false, file1.isCombined); +- assert.equal(5, file1.addedLines); +- assert.equal(0, file1.deletedLines); +- assert.equal('/dev/null', file1.oldName); +- assert.equal('test.js', file1.newName); +- assert.equal(1, file1.blocks.length); +- assert.equal(true, file1.isNew); +- assert.equal(100644, file1.newFileMode); +- assert.equal('0000000', file1.checksumBefore); +- assert.equal('e1e22ec', file1.checksumAfter); +- }); +- +- it('should parse diff with nested diff', function() { +- var diff = +- 'diff --git a/src/offset.js b/src/offset.js\n' + +- 'index cc6ffb4..fa51f18 100644\n' + +- '--- a/src/offset.js\n' + +- '+++ b/src/offset.js\n' + +- '@@ -1,6 +1,5 @@\n' + +- "+var parser = require('./source/git-parser');\n" + +- '+\n' + +- "+var text = 'diff --git a/components/app/app.html b/components/app/app.html\\nindex ecb7a95..027bd9b 100644\\n--- a/components/app/app.html\\n+++ b/components/app/app.html\\n@@ -52,0 +53,3 @@\\n+\\n+\\n+\\n@@ -56,0 +60,3 @@\\n+\\n+\\n+\\n'\n" + +- '+var patchLineList = [ false, false, false, false ];\n' + +- '+\n' + +- '+console.log(parser.parsePatchDiffResult(text, patchLineList));\n'; +- +- var result = DiffParser.generateDiffJson(diff); +- assert.equal(1, result.length); +- +- var file1 = result[0]; +- assert.equal(false, file1.isCombined); +- assert.equal(6, file1.addedLines); +- assert.equal(0, file1.deletedLines); +- assert.equal('src/offset.js', file1.oldName); +- assert.equal('src/offset.js', file1.newName); +- assert.equal(1, file1.blocks.length); +- assert.equal(6, file1.blocks[0].lines.length); +- assert.equal('cc6ffb4', file1.checksumBefore); +- assert.equal('fa51f18', file1.checksumAfter); +- }); +- +- it('should parse diff with multiple blocks', function() { +- var diff = +- 'diff --git a/src/attributes/classes.js b/src/attributes/classes.js\n' + +- 'index c617824..c8d1393 100644\n' + +- '--- a/src/attributes/classes.js\n' + +- '+++ b/src/attributes/classes.js\n' + +- '@@ -1,10 +1,9 @@\n' + +- ' define([\n' + +- ' "../core",\n' + +- ' "../var/rnotwhite",\n' + +- '- "../var/strundefined",\n' + +- ' "../data/var/dataPriv",\n' + +- ' "../core/init"\n' + +- '-], function( jQuery, rnotwhite, strundefined, dataPriv ) {\n' + +- '+], function( jQuery, rnotwhite, dataPriv ) {\n' + +- ' \n' + +- ' var rclass = /[\\t\\r\\n\\f]/g;\n' + +- ' \n' + +- '@@ -128,7 +127,7 @@ jQuery.fn.extend({\n' + +- ' }\n' + +- ' \n' + +- ' // Toggle whole class name\n' + +- '- } else if ( type === strundefined || type === "boolean" ) {\n' + +- '+ } else if ( value === undefined || type === "boolean" ) {\n' + +- ' if ( this.className ) {\n' + +- ' // store className if set\n' + +- ' dataPriv.set( this, "__className__", this.className );\n'; +- +- var result = DiffParser.generateDiffJson(diff); +- assert.equal(1, result.length); +- +- var file1 = result[0]; +- assert.equal(false, file1.isCombined); +- assert.equal(2, file1.addedLines); +- assert.equal(3, file1.deletedLines); +- assert.equal('src/attributes/classes.js', file1.oldName); +- assert.equal('src/attributes/classes.js', file1.newName); +- assert.equal(2, file1.blocks.length); +- assert.equal(11, file1.blocks[0].lines.length); +- assert.equal(8, file1.blocks[1].lines.length); +- assert.equal('c617824', file1.checksumBefore); +- assert.equal('c8d1393', file1.checksumAfter); +- }); +- +- it('should parse diff with multiple files', function() { +- var diff = +- 'diff --git a/src/core/init.js b/src/core/init.js\n' + +- 'index e49196a..50f310c 100644\n' + +- '--- a/src/core/init.js\n' + +- '+++ b/src/core/init.js\n' + +- '@@ -101,7 +101,7 @@ var rootjQuery,\n' + +- ' // HANDLE: $(function)\n' + +- ' // Shortcut for document ready\n' + +- ' } else if ( jQuery.isFunction( selector ) ) {\n' + +- '- return typeof rootjQuery.ready !== "undefined" ?\n' + +- '+ return rootjQuery.ready !== undefined ?\n' + +- ' rootjQuery.ready( selector ) :\n' + +- ' // Execute immediately if ready is not present\n' + +- ' selector( jQuery );\n' + +- 'diff --git a/src/event.js b/src/event.js\n' + +- 'index 7336f4d..6183f70 100644\n' + +- '--- a/src/event.js\n' + +- '+++ b/src/event.js\n' + +- '@@ -1,6 +1,5 @@\n' + +- ' define([\n' + +- ' "./core",\n' + +- '- "./var/strundefined",\n' + +- ' "./var/rnotwhite",\n' + +- ' "./var/hasOwn",\n' + +- ' "./var/slice",\n'; +- +- var result = DiffParser.generateDiffJson(diff); +- assert.equal(2, result.length); +- +- var file1 = result[0]; +- assert.equal(false, file1.isCombined); +- assert.equal(1, file1.addedLines); +- assert.equal(1, file1.deletedLines); +- assert.equal('src/core/init.js', file1.oldName); +- assert.equal('src/core/init.js', file1.newName); +- assert.equal(1, file1.blocks.length); +- assert.equal(8, file1.blocks[0].lines.length); +- assert.equal('e49196a', file1.checksumBefore); +- assert.equal('50f310c', file1.checksumAfter); +- +- var file2 = result[1]; +- assert.equal(false, file2.isCombined); +- assert.equal(0, file2.addedLines); +- assert.equal(1, file2.deletedLines); +- assert.equal('src/event.js', file2.oldName); +- assert.equal('src/event.js', file2.newName); +- assert.equal(1, file2.blocks.length); +- assert.equal(6, file2.blocks[0].lines.length); +- assert.equal('7336f4d', file2.checksumBefore); +- assert.equal('6183f70', file2.checksumAfter); +- }); +- +- it('should parse combined diff', function() { +- var diff = +- 'diff --combined describe.c\n' + +- 'index fabadb8,cc95eb0..4866510\n' + +- '--- a/describe.c\n' + +- '+++ b/describe.c\n' + +- '@@@ -98,20 -98,12 +98,20 @@@\n' + +- ' return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;\n' + +- ' }\n' + +- ' \n' + +- '- static void describe(char *arg)\n' + +- ' -static void describe(struct commit *cmit, int last_one)\n' + +- '++static void describe(char *arg, int last_one)\n' + +- ' {\n' + +- ' + unsigned char sha1[20];\n' + +- ' + struct commit *cmit;\n' + +- ' struct commit_list *list;\n' + +- ' static int initialized = 0;\n' + +- ' struct commit_name *n;\n' + +- ' \n' + +- ' + if (get_sha1(arg, sha1) < 0)\n' + +- ' + usage(describe_usage);\n' + +- ' + cmit = lookup_commit_reference(sha1);\n' + +- ' + if (!cmit)\n' + +- ' + usage(describe_usage);\n' + +- ' +\n' + +- ' if (!initialized) {\n' + +- ' initialized = 1;\n' + +- ' for_each_ref(get_name);\n'; +- +- var result = DiffParser.generateDiffJson(diff); +- assert.equal(1, result.length); +- +- var file1 = result[0]; +- assert.equal(true, file1.isCombined); +- assert.equal(9, file1.addedLines); +- assert.equal(2, file1.deletedLines); +- assert.equal('describe.c', file1.oldName); +- assert.equal('describe.c', file1.newName); +- assert.equal(1, file1.blocks.length); +- assert.equal(22, file1.blocks[0].lines.length); +- assert.deepEqual(['4866510', 'cc95eb0'].sort(), file1.checksumBefore.sort()); +- assert.equal('fabadb8', file1.checksumAfter); +- }); +- +- it('should parse diffs with copied files', function() { +- var diff = +- 'diff --git a/index.js b/more-index.js\n' + +- 'dissimilarity index 5%\n' + +- 'copy from index.js\n' + +- 'copy to more-index.js\n'; +- +- var result = DiffParser.generateDiffJson(diff); +- assert.equal(1, result.length); +- +- var file1 = result[0]; +- assert.equal(0, file1.addedLines); +- assert.equal(0, file1.deletedLines); +- assert.equal('index.js', file1.oldName); +- assert.equal('more-index.js', file1.newName); +- assert.equal(0, file1.blocks.length); +- assert.equal(true, file1.isCopy); +- assert.equal(5, file1.changedPercentage); +- }); +- +- it('should parse diffs with moved files', function() { +- var diff = +- 'diff --git a/more-index.js b/other-index.js\n' + +- 'similarity index 86%\n' + +- 'rename from more-index.js\n' + +- 'rename to other-index.js\n'; +- +- var result = DiffParser.generateDiffJson(diff); +- assert.equal(1, result.length); +- +- var file1 = result[0]; +- assert.equal(0, file1.addedLines); +- assert.equal(0, file1.deletedLines); +- assert.equal('more-index.js', file1.oldName); +- assert.equal('other-index.js', file1.newName); +- assert.equal(0, file1.blocks.length); +- assert.equal(true, file1.isRename); +- assert.equal(86, file1.unchangedPercentage); +- }); +- +- it('should parse diffs correct line numbers', function() { +- var diff = +- 'diff --git a/sample b/sample\n' + +- 'index 0000001..0ddf2ba\n' + +- '--- a/sample\n' + +- '+++ b/sample\n' + +- '@@ -1 +1,2 @@\n' + +- '-test\n' + +- '+test1r\n'; +- +- var result = DiffParser.generateDiffJson(diff); +- assert.equal(1, result.length); +- +- var file1 = result[0]; +- assert.equal(1, file1.addedLines); +- assert.equal(1, file1.deletedLines); +- assert.equal('sample', file1.oldName); +- assert.equal('sample', file1.newName); +- assert.equal(1, file1.blocks.length); +- assert.equal(2, file1.blocks[0].lines.length); +- assert.equal(1, file1.blocks[0].lines[0].oldNumber); +- assert.equal(null, file1.blocks[0].lines[0].newNumber); +- assert.equal(null, file1.blocks[0].lines[1].oldNumber); +- assert.equal(1, file1.blocks[0].lines[1].newNumber); +- }); +- +- it('should parse unified non git diff and strip timestamps off the headers', function() { +- var diffs = [ +- // 2 hours ahead of GMT +- '--- a/sample.js 2016-10-25 11:37:14.000000000 +0200\n' + +- '+++ b/sample.js 2016-10-25 11:37:14.000000000 +0200\n' + +- '@@ -1 +1,2 @@\n' + +- '-test\n' + +- '+test1r\n' + +- '+test2r\n', +- // 2 hours behind GMT +- '--- a/sample.js 2016-10-25 11:37:14.000000000 -0200\n' + +- '+++ b/sample.js 2016-10-25 11:37:14.000000000 -0200\n' + +- '@@ -1 +1,2 @@\n' + +- '-test\n' + +- '+test1r\n' + +- '+test2r\n' +- ]; +- +- diffs.forEach(function(diff) { +- var result = DiffParser.generateDiffJson(diff); +- var file1 = result[0]; +- assert.equal(1, result.length); +- assert.equal(2, file1.addedLines); +- assert.equal(1, file1.deletedLines); +- assert.equal('sample.js', file1.oldName); +- assert.equal('sample.js', file1.newName); +- assert.equal(1, file1.blocks.length); +- +- var linesContent = file1.blocks[0].lines.map(function(line) { +- return line.content; +- }); +- assert.deepEqual(linesContent, ['-test', '+test1r', '+test2r']); +- }); +- }); +- +- it('should parse unified non git diff', function() { +- var diff = +- '--- a/sample.js\n' + +- '+++ b/sample.js\n' + +- '@@ -1 +1,2 @@\n' + +- '-test\n' + +- '+test1r\n' + +- '+test2r\n'; +- +- var result = DiffParser.generateDiffJson(diff); +- var file1 = result[0]; +- assert.equal(1, result.length); +- assert.equal(2, file1.addedLines); +- assert.equal(1, file1.deletedLines); +- assert.equal('sample.js', file1.oldName); +- assert.equal('sample.js', file1.newName); +- assert.equal(1, file1.blocks.length); +- +- var linesContent = file1.blocks[0].lines.map(function(line) { +- return line.content; +- }); +- assert.deepEqual(linesContent, ['-test', '+test1r', '+test2r']); +- }); +- +- it('should parse unified diff with multiple hunks and files', function() { +- var diff = +- '--- sample.js\n' + +- '+++ sample.js\n' + +- '@@ -1 +1,2 @@\n' + +- '-test\n' + +- '@@ -10 +20,2 @@\n' + +- '+test\n' + +- '--- sample1.js\n' + +- '+++ sample1.js\n' + +- '@@ -1 +1,2 @@\n' + +- '+test1'; +- +- var result = DiffParser.generateDiffJson(diff); +- assert.equal(2, result.length); +- +- var file1 = result[0]; +- assert.equal(1, file1.addedLines); +- assert.equal(1, file1.deletedLines); +- assert.equal('sample.js', file1.oldName); +- assert.equal('sample.js', file1.newName); +- assert.equal(2, file1.blocks.length); +- +- var linesContent1 = file1.blocks[0].lines.map(function(line) { +- return line.content; +- }); +- assert.deepEqual(linesContent1, ['-test']); +- +- var linesContent2 = file1.blocks[1].lines.map(function(line) { +- return line.content; +- }); +- assert.deepEqual(linesContent2, ['+test']); +- +- var file2 = result[1]; +- assert.equal(1, file2.addedLines); +- assert.equal(0, file2.deletedLines); +- assert.equal('sample1.js', file2.oldName); +- assert.equal('sample1.js', file2.newName); +- assert.equal(1, file2.blocks.length); +- +- var linesContent = file2.blocks[0].lines.map(function(line) { +- return line.content; +- }); +- assert.deepEqual(linesContent, ['+test1']); +- }); +- +- it('should parse diff with --- and +++ in the context lines', function() { +- var diff = +- '--- sample.js\n' + +- '+++ sample.js\n' + +- '@@ -1,8 +1,8 @@\n' + +- ' test\n' + +- ' \n' + +- '-- 1\n' + +- '--- 1\n' + +- '---- 1\n' + +- ' \n' + +- '++ 2\n' + +- '+++ 2\n' + +- '++++ 2'; +- +- var result = DiffParser.generateDiffJson(diff); +- var file1 = result[0]; +- assert.equal(1, result.length); +- assert.equal(3, file1.addedLines); +- assert.equal(3, file1.deletedLines); +- assert.equal('sample.js', file1.oldName); +- assert.equal('sample.js', file1.newName); +- assert.equal(1, file1.blocks.length); +- +- var linesContent = file1.blocks[0].lines.map(function(line) { +- return line.content; +- }); +- assert.deepEqual(linesContent, +- [' test', ' ', '-- 1', '--- 1', '---- 1', ' ', '++ 2', '+++ 2', '++++ 2']); +- }); +- +- it('should parse diff without proper hunk headers', function() { +- var diff = +- '--- sample.js\n' + +- '+++ sample.js\n' + +- '@@ @@\n' + +- ' test'; +- +- var result = DiffParser.generateDiffJson(diff); +- var file1 = result[0]; +- assert.equal(1, result.length); +- assert.equal(0, file1.addedLines); +- assert.equal(0, file1.deletedLines); +- assert.equal('sample.js', file1.oldName); +- assert.equal('sample.js', file1.newName); +- assert.equal(1, file1.blocks.length); +- +- var linesContent = file1.blocks[0].lines.map(function(line) { +- return line.content; +- }); +- assert.deepEqual(linesContent, [' test']); +- }); +- +- it('should parse binary file diff', function() { +- var diff = +- 'diff --git a/last-changes-config.png b/last-changes-config.png\n' + +- 'index 322248b..56fc1f2 100644\n' + +- '--- a/last-changes-config.png\n' + +- '+++ b/last-changes-config.png\n' + +- 'Binary files differ'; +- +- var result = DiffParser.generateDiffJson(diff); +- var file1 = result[0]; +- assert.equal(1, result.length); +- assert.equal(0, file1.addedLines); +- assert.equal(0, file1.deletedLines); +- assert.equal('last-changes-config.png', file1.oldName); +- assert.equal('last-changes-config.png', file1.newName); +- assert.equal(1, file1.blocks.length); +- assert.equal(0, file1.blocks[0].lines.length); +- assert.equal('Binary files differ', file1.blocks[0].header); +- }); +- +- it('should parse diff with --find-renames', function() { +- var diff = +- 'diff --git a/src/test-bar.js b/src/test-baz.js\n' + +- 'similarity index 98%\n' + +- 'rename from src/test-bar.js\n' + +- 'rename to src/test-baz.js\n' + +- 'index e01513b..f14a870 100644\n' + +- '--- a/src/test-bar.js\n' + +- '+++ b/src/test-baz.js\n' + +- '@@ -1,4 +1,32 @@\n' + +- ' function foo() {\n' + +- '-var bar = "Whoops!";\n' + +- '+var baz = "Whoops!";\n' + +- ' }\n' + +- ' '; +- +- var result = DiffParser.generateDiffJson(diff); +- var file1 = result[0]; +- assert.equal(1, result.length); +- assert.equal(1, file1.addedLines); +- assert.equal(1, file1.deletedLines); +- assert.equal('src/test-bar.js', file1.oldName); +- assert.equal('src/test-baz.js', file1.newName); +- assert.equal(1, file1.blocks.length); +- assert.equal(5, file1.blocks[0].lines.length); +- var linesContent = file1.blocks[0].lines.map(function(line) { +- return line.content; +- }); +- assert.deepEqual(linesContent, +- [' function foo() {', '-var bar = "Whoops!";', '+var baz = "Whoops!";', ' }', ' ']); +- }); +- +- it('should parse diff with prefix', function() { +- var diff = +- 'diff --git "\tTest.scala" "\tScalaTest.scala"\n' + +- 'similarity index 88%\n' + +- 'rename from Test.scala\n' + +- 'rename to ScalaTest.scala\n' + +- 'index 7d1f9bf..8b13271 100644\n' + +- '--- "\tTest.scala"\n' + +- '+++ "\tScalaTest.scala"\n' + +- '@@ -1,6 +1,8 @@\n' + +- ' class Test {\n' + +- ' \n' + +- ' def method1 = ???\n' + +- '+\n' + +- '+ def method2 = ???\n' + +- ' \n' + +- ' def myMethod = ???\n' + +- ' \n' + +- '@@ -10,7 +12,6 @@ class Test {\n' + +- ' \n' + +- ' def + = ???\n' + +- ' \n' + +- '- def |> = ???\n' + +- ' \n' + +- ' }\n' + +- ' \n' + +- 'diff --git "\ttardis.png" "\ttardis.png"\n' + +- 'new file mode 100644\n' + +- 'index 0000000..d503a29\n' + +- 'Binary files /dev/null and "\ttardis.png" differ\n' + +- 'diff --git a/src/test-bar.js b/src/test-baz.js\n' + +- 'similarity index 98%\n' + +- 'rename from src/test-bar.js\n' + +- 'rename to src/test-baz.js\n' + +- 'index e01513b..f14a870 100644\n' + +- '--- a/src/test-bar.js\n' + +- '+++ b/src/test-baz.js\n' + +- '@@ -1,4 +1,32 @@\n' + +- ' function foo() {\n' + +- '-var bar = "Whoops!";\n' + +- '+var baz = "Whoops!";\n' + +- ' }\n' + +- ' '; +- +- var result = DiffParser.generateDiffJson(diff, {'srcPrefix': '\t', 'dstPrefix': '\t'}); +- assert.equal(3, result.length); +- +- var file1 = result[0]; +- assert.equal(2, file1.addedLines); +- assert.equal(1, file1.deletedLines); +- assert.equal('Test.scala', file1.oldName); +- assert.equal('ScalaTest.scala', file1.newName); +- assert.equal(2, file1.blocks.length); +- assert.equal(8, file1.blocks[0].lines.length); +- assert.equal(7, file1.blocks[1].lines.length); +- +- var file2 = result[1]; +- assert.equal('/dev/null', file2.oldName); +- assert.equal('tardis.png', file2.newName); +- +- var file3 = result[2]; +- assert.equal(1, file3.addedLines); +- assert.equal(1, file3.deletedLines); +- assert.equal('src/test-bar.js', file3.oldName); +- assert.equal('src/test-baz.js', file3.newName); +- assert.equal(1, file3.blocks.length); +- assert.equal(5, file3.blocks[0].lines.length); +- var linesContent = file3.blocks[0].lines.map(function(line) { +- return line.content; +- }); +- assert.deepEqual(linesContent, +- [' function foo() {', '-var bar = "Whoops!";', '+var baz = "Whoops!";', ' }', ' ']); +- }); +- +- it('should parse binary with content', function() { +- var diff = +- 'diff --git a/favicon.png b/favicon.png\n' + +- 'deleted file mode 100644\n' + +- 'index 2a9d516a5647205d7be510dd0dff93a3663eff6f..0000000000000000000000000000000000000000\n' + +- 'GIT binary patch\n' + +- 'literal 0\n' + +- 'HcmV?d00001\n' + +- '\n' + +- 'literal 471\n' + +- 'zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ\n' + +- 'za0`JjqPVOAS4ANVKzqmCp=Cty@U^(7zk!jHsvT~YI{F^=Ex6g|gox78w\n' + +- 'z+Sn2Du3GS9U7qU`1*NYYlJi3u-!-_B#8k9H0\n' + +- 'zGl{FnZs<2$wz5^=Q2h-1XI^s{LQL1#T4epqNPC%Orl(tD_@!*EY++~^Lt2<2&!&%=\n' + +- 'z`m>(TYj6uS7jDdt=eH>iOyQg(QMR<-Fw8)Dk^ZG)XQTuzEgl{`GpS?Cfq9818R9~=\n' + +- 'z{&h9@9n8F^?|qusoPy{k#%tVHzu7H$t26CR`BJZk*Ixf&u36WuS=?6m2^ho-p00i_\n' + +- 'I>zopr0Nz-&lmGw#\n' + +- 'diff --git a/src/test-bar.js b/src/test-baz.js\n' + +- 'similarity index 98%\n' + +- 'rename from src/test-bar.js\n' + +- 'rename to src/test-baz.js\n' + +- 'index e01513b..f14a870 100644\n' + +- '--- a/src/test-bar.js\n' + +- '+++ b/src/test-baz.js\n' + +- '@@ -1,4 +1,32 @@\n' + +- ' function foo() {\n' + +- '-var bar = "Whoops!";\n' + +- '+var baz = "Whoops!";\n' + +- ' }\n' + +- ' '; +- +- var result = DiffParser.generateDiffJson(diff); +- assert.equal(2, result.length); +- +- var file1 = result[0]; +- assert.equal('favicon.png', file1.oldName); +- assert.equal('favicon.png', file1.newName); +- assert.equal(1, file1.blocks.length); +- assert.equal(0, file1.blocks[0].lines.length); +- +- var file2 = result[1]; +- assert.equal(1, file2.addedLines); +- assert.equal(1, file2.deletedLines); +- assert.equal('src/test-bar.js', file2.oldName); +- assert.equal('src/test-baz.js', file2.newName); +- assert.equal(1, file2.blocks.length); +- assert.equal(5, file2.blocks[0].lines.length); +- var linesContent = file2.blocks[0].lines.map(function(line) { +- return line.content; +- }); +- assert.deepEqual(linesContent, +- [' function foo() {', '-var bar = "Whoops!";', '+var baz = "Whoops!";', ' }', ' ']); +- }); +- }); +-}); +diff --git a/test/file-list-printer-tests.js b/test/file-list-printer-tests.js +deleted file mode 100644 +index 55c6cfed..00000000 +--- a/test/file-list-printer-tests.js ++++ /dev/null +@@ -1,145 +0,0 @@ +-var assert = require('assert'); +-var FileListPrinter = require('../src/file-list-printer.js').FileListPrinter; +- +-describe('FileListPrinter', function() { +- describe('generateFileList', function() { +- it('should expose old and new files to templates', function() { +- var files = [{ +- addedlines: 12, +- deletedlines: 41, +- language: 'js', +- oldName: 'my/file/name.js', +- newName: 'my/file/name.js' +- }, { +- addedLines: 12, +- deletedLines: 41, +- language: 'js', +- oldName: 'my/file/name1.js', +- newName: 'my/file/name2.js' +- }, { +- addedLines: 12, +- deletedLines: 0, +- language: 'js', +- oldName: 'dev/null', +- newName: 'my/file/name.js', +- isNew: true +- }, { +- addedLines: 0, +- deletedLines: 41, +- language: 'js', +- oldName: 'my/file/name.js', +- newName: 'dev/null', +- isDeleted: true +- }]; +- +- var fileListPrinter = new FileListPrinter({ +- rawTemplates: { +- 'file-summary-wrapper': '{{{files}}}', +- 'file-summary-line': '{{oldName}}, {{newName}}, {{fileName}}' +- } +- }); +- +- var fileHtml = fileListPrinter.generateFileList(files); +- var expected = 'my/file/name.js, my/file/name.js, my/file/name.js\n' + +- 'my/file/name1.js, my/file/name2.js, my/file/{name1.js → name2.js}\n' + +- 'dev/null, my/file/name.js, my/file/name.js\n' + +- 'my/file/name.js, dev/null, my/file/name.js'; +- +- assert.equal(expected, fileHtml); +- }); +- +- it('should work for all kinds of files', function() { +- var files = [{ +- addedLines: 12, +- deletedLines: 41, +- language: 'js', +- oldName: 'my/file/name.js', +- newName: 'my/file/name.js' +- }, { +- addedLines: 12, +- deletedLines: 41, +- language: 'js', +- oldName: 'my/file/name1.js', +- newName: 'my/file/name2.js' +- }, { +- addedLines: 12, +- deletedLines: 0, +- language: 'js', +- oldName: 'dev/null', +- newName: 'my/file/name.js', +- isNew: true +- }, { +- addedLines: 0, +- deletedLines: 41, +- language: 'js', +- oldName: 'my/file/name.js', +- newName: 'dev/null', +- isDeleted: true +- }]; +- +- var fileListPrinter = new FileListPrinter(); +- var fileHtml = fileListPrinter.generateFileList(files); +- +- var expected = +- '
    \n' + +- '
    \n' + +- ' Files changed (4)\n' + +- ' hide\n' + +- ' show\n' + +- '
    \n' + +- '
      \n' + +- '
    1. \n' + +- ' \n' + +- ' my/file/name.js\n' + +- ' \n' + +- ' +12\n' + +- ' -41\n' + +- ' \n' + +- ' \n' + +- '
    2. \n' + +- '
    3. \n' + +- ' \n' + +- ' my/file/{name1.js → name2.js}\n' + +- ' \n' + +- ' +12\n' + +- ' -41\n' + +- ' \n' + +- ' \n' + +- '
    4. \n' + +- '
    5. \n' + +- ' \n' + +- ' my/file/name.js\n' + +- ' \n' + +- ' +12\n' + +- ' -0\n' + +- ' \n' + +- ' \n' + +- '
    6. \n' + +- '
    7. \n' + +- ' \n' + +- ' my/file/name.js\n' + +- ' \n' + +- ' +0\n' + +- ' -41\n' + +- ' \n' + +- ' \n' + +- '
    8. \n' + +- '
    \n' + +- '
    '; +- +- assert.equal(expected, fileHtml); +- }); +- }); +-}); +diff --git a/test/hogan-cache-tests.js b/test/hogan-cache-tests.js +deleted file mode 100644 +index a34839c0..00000000 +--- a/test/hogan-cache-tests.js ++++ /dev/null +@@ -1,70 +0,0 @@ +-var assert = require('assert'); +- +-var HoganJsUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(); +-var diffParser = require('../src/diff-parser.js').DiffParser; +- +-describe('HoganJsUtils', function() { +- describe('render', function() { +- var emptyDiffHtml = +- '\n' + +- ' \n' + +- '
    \n' + +- ' File without changes\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- it('should render view', function() { +- var result = HoganJsUtils.render('generic', 'empty-diff', { +- contentClass: 'd2h-code-line', +- diffParser: diffParser +- }); +- assert.equal(emptyDiffHtml, result); +- }); +- +- it('should render view without cache', function() { +- var result = HoganJsUtils.render('generic', 'empty-diff', { +- contentClass: 'd2h-code-line', +- diffParser: diffParser +- }, {noCache: true}); +- assert.equal(emptyDiffHtml, result); +- }); +- +- it('should return null if template is missing', function() { +- var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)({noCache: true}); +- var result = hoganUtils.render('generic', 'missing-template', {}); +- assert.equal(null, result); +- }); +- +- it('should allow templates to be overridden with compiled templates', function() { +- var emptyDiffTemplate = HoganJsUtils.compile('

    {{myName}}

    '); +- +- var config = {templates: {'generic-empty-diff': emptyDiffTemplate}}; +- var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(config); +- var result = hoganUtils.render('generic', 'empty-diff', {myName: 'Rodrigo Fernandes'}); +- assert.equal('

    Rodrigo Fernandes

    ', result); +- }); +- +- it('should allow templates to be overridden with uncompiled templates', function() { +- var emptyDiffTemplate = '

    {{myName}}

    '; +- +- var config = {rawTemplates: {'generic-empty-diff': emptyDiffTemplate}}; +- var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(config); +- var result = hoganUtils.render('generic', 'empty-diff', {myName: 'Rodrigo Fernandes'}); +- assert.equal('

    Rodrigo Fernandes

    ', result); +- }); +- +- it('should allow templates to be overridden giving priority to compiled templates', function() { +- var emptyDiffTemplate = HoganJsUtils.compile('

    {{myName}}

    '); +- var emptyDiffTemplateUncompiled = '

    Not used!

    '; +- +- var config = { +- templates: {'generic-empty-diff': emptyDiffTemplate}, +- rawTemplates: {'generic-empty-diff': emptyDiffTemplateUncompiled} +- }; +- var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(config); +- var result = hoganUtils.render('generic', 'empty-diff', {myName: 'Rodrigo Fernandes'}); +- assert.equal('

    Rodrigo Fernandes

    ', result); +- }); +- }); +-}); +diff --git a/test/line-by-line-tests.js b/test/line-by-line-tests.js +deleted file mode 100644 +index 72d37118..00000000 +--- a/test/line-by-line-tests.js ++++ /dev/null +@@ -1,604 +0,0 @@ +-var assert = require('assert'); +- +-var LineByLinePrinter = require('../src/line-by-line-printer.js').LineByLinePrinter; +- +-describe('LineByLinePrinter', function() { +- describe('_generateEmptyDiff', function() { +- it('should return an empty diff', function() { +- var lineByLinePrinter = new LineByLinePrinter({}); +- var fileHtml = lineByLinePrinter._generateEmptyDiff(); +- var expected = '\n' + +- ' \n' + +- '
    \n' + +- ' File without changes\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expected, fileHtml); +- }); +- }); +- +- describe('makeLineHtml', function() { +- it('should work for insertions', function() { +- var diffParser = require('../src/diff-parser.js').DiffParser; +- var lineByLinePrinter = new LineByLinePrinter({}); +- var fileHtml = lineByLinePrinter.makeLineHtml(false, +- diffParser.LINE_TYPE.INSERTS, '', 30, 'test', '+'); +- fileHtml = fileHtml.replace(/\n\n+/g, '\n'); +- var expected = '\n' + +- ' \n' + +- '
    \n' + +- '
    30
    \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' test\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expected, fileHtml); +- }); +- +- it('should work for deletions', function() { +- var diffParser = require('../src/diff-parser.js').DiffParser; +- var lineByLinePrinter = new LineByLinePrinter({}); +- var fileHtml = lineByLinePrinter.makeLineHtml(false, +- diffParser.LINE_TYPE.DELETES, 30, '', 'test', '-'); +- fileHtml = fileHtml.replace(/\n\n+/g, '\n'); +- var expected = '\n' + +- ' \n' + +- '
    30
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' -\n' + +- ' test\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expected, fileHtml); +- }); +- +- it('should convert indents into non breakin spaces (2 white spaces)', function() { +- var diffParser = require('../src/diff-parser.js').DiffParser; +- var lineByLinePrinter = new LineByLinePrinter({}); +- var fileHtml = lineByLinePrinter.makeLineHtml(false, +- diffParser.LINE_TYPE.INSERTS, '', 30, ' test', '+'); +- fileHtml = fileHtml.replace(/\n\n+/g, '\n'); +- var expected = '\n' + +- ' \n' + +- '
    \n' + +- '
    30
    \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' test\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expected, fileHtml); +- }); +- +- it('should convert indents into non breakin spaces (4 white spaces)', function() { +- var diffParser = require('../src/diff-parser.js').DiffParser; +- var lineByLinePrinter = new LineByLinePrinter({}); +- var fileHtml = lineByLinePrinter.makeLineHtml(false, +- diffParser.LINE_TYPE.INSERTS, '', 30, ' test', '+'); +- fileHtml = fileHtml.replace(/\n\n+/g, '\n'); +- var expected = '\n' + +- ' \n' + +- '
    \n' + +- '
    30
    \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' test\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expected, fileHtml); +- }); +- +- it('should preserve tabs', function() { +- var diffParser = require('../src/diff-parser.js').DiffParser; +- var lineByLinePrinter = new LineByLinePrinter({}); +- var fileHtml = lineByLinePrinter.makeLineHtml(false, +- diffParser.LINE_TYPE.INSERTS, '', 30, '\ttest', '+'); +- fileHtml = fileHtml.replace(/\n\n+/g, '\n'); +- var expected = '\n' + +- ' \n' + +- '
    \n' + +- '' + +- '
    30
    \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' \ttest\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expected, fileHtml); +- }); +- }); +- +- describe('makeFileDiffHtml', function() { +- it('should work for simple file', function() { +- var lineByLinePrinter = new LineByLinePrinter({}); +- +- var file = { +- addedLines: 12, +- deletedLines: 41, +- language: 'js', +- oldName: 'my/file/name.js', +- newName: 'my/file/name.js' +- }; +- var diffs = 'Random Html'; +- +- var fileHtml = lineByLinePrinter.makeFileDiffHtml(file, diffs); +- +- var expected = +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' my/file/name.js\n' + +- ' CHANGED\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- ' Random Html\n' + +- ' \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    '; +- +- assert.equal(expected, fileHtml); +- }); +- it('should work for simple added file', function() { +- var lineByLinePrinter = new LineByLinePrinter({}); +- +- var file = { +- addedLines: 12, +- deletedLines: 0, +- language: 'js', +- oldName: 'dev/null', +- newName: 'my/file/name.js', +- isNew: true +- }; +- var diffs = 'Random Html'; +- +- var fileHtml = lineByLinePrinter.makeFileDiffHtml(file, diffs); +- +- var expected = +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' my/file/name.js\n' + +- ' ADDED\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- ' Random Html\n' + +- ' \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    '; +- +- assert.equal(expected, fileHtml); +- }); +- it('should work for simple deleted file', function() { +- var lineByLinePrinter = new LineByLinePrinter({}); +- +- var file = { +- addedLines: 0, +- deletedLines: 41, +- language: 'js', +- oldName: 'my/file/name.js', +- newName: 'dev/null', +- isDeleted: true +- }; +- var diffs = 'Random Html'; +- +- var fileHtml = lineByLinePrinter.makeFileDiffHtml(file, diffs); +- +- var expected = +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' my/file/name.js\n' + +- ' DELETED\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- ' Random Html\n' + +- ' \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    '; +- +- assert.equal(expected, fileHtml); +- }); +- it('should work for simple renamed file', function() { +- var lineByLinePrinter = new LineByLinePrinter({}); +- +- var file = { +- addedLines: 12, +- deletedLines: 41, +- language: 'js', +- oldName: 'my/file/name1.js', +- newName: 'my/file/name2.js', +- isRename: true +- }; +- var diffs = 'Random Html'; +- +- var fileHtml = lineByLinePrinter.makeFileDiffHtml(file, diffs); +- +- var expected = +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' my/file/{name1.js → name2.js}\n' + +- ' RENAMED\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- ' Random Html\n' + +- ' \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    '; +- +- assert.equal(expected, fileHtml); +- }); +- it('should return empty when option renderNothingWhenEmpty is true and file blocks not present', function() { +- var lineByLinePrinter = new LineByLinePrinter({ +- renderNothingWhenEmpty: true +- }); +- +- var file = { +- blocks: [] +- }; +- +- var diffs = 'Random Html'; +- +- var fileHtml = lineByLinePrinter.makeFileDiffHtml(file, diffs); +- +- var expected = ''; +- +- assert.equal(expected, fileHtml); +- }); +- }); +- +- describe('makeLineByLineHtmlWrapper', function() { +- it('should work for simple content', function() { +- var lineByLinePrinter = new LineByLinePrinter({}); +- var fileHtml = lineByLinePrinter.makeLineByLineHtmlWrapper('Random Html'); +- +- var expected = +- '
    \n' + +- ' Random Html\n' + +- '
    '; +- +- assert.equal(expected, fileHtml); +- }); +- }); +- +- describe('generateLineByLineJsonHtml', function() { +- it('should work for list of files', function() { +- var exampleJson = [ +- { +- blocks: [ +- { +- lines: [ +- { +- content: '-test', +- type: 'd2h-del', +- oldNumber: 1, +- newNumber: null +- }, +- { +- content: '+test1r', +- type: 'd2h-ins', +- oldNumber: null, +- newNumber: 1 +- } +- ], +- oldStartLine: '1', +- oldStartLine2: null, +- newStartLine: '1', +- header: '@@ -1 +1 @@' +- } +- ], +- deletedLines: 1, +- addedLines: 1, +- checksumBefore: '0000001', +- checksumAfter: '0ddf2ba', +- oldName: 'sample', +- language: undefined, +- newName: 'sample', +- isCombined: false +- } +- ]; +- +- var lineByLinePrinter = new LineByLinePrinter({matching: 'lines'}); +- var html = lineByLinePrinter.generateLineByLineJsonHtml(exampleJson); +- var expected = +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' sample\n' + +- ' CHANGED\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- '\n' + +- ' \n' + +- ' \n' + +- '\n' + +- ' \n' + +- ' \n' + +- '\n' + +- ' \n' + +- '
    \n' + +- '
    @@ -1 +1 @@
    \n' + +- '
    \n' + +- '
    1
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' -\n' + +- ' test\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    1
    \n' + +- '
    \n' + +- '
    \n' + +- ' +\n' + +- ' test1r\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    '; +- +- assert.equal(expected, html); +- }); +- +- it('should work for empty blocks', function() { +- var exampleJson = [{ +- blocks: [], +- deletedLines: 0, +- addedLines: 0, +- oldName: 'sample', +- language: 'js', +- newName: 'sample', +- isCombined: false +- }]; +- +- var lineByLinePrinter = new LineByLinePrinter({ renderNothingWhenEmpty: false }); +- var html = lineByLinePrinter.generateLineByLineJsonHtml(exampleJson); +- var expected = +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' sample\n' + +- ' CHANGED\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- '\n' + +- ' \n' + +- '
    \n' + +- '
    \n' + +- ' File without changes\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    '; +- +- assert.equal(expected, html); +- }); +- }); +- +- describe('_processLines', function() { +- it('should work for simple block header', function() { +- var lineByLinePrinter = new LineByLinePrinter({}); +- var oldLines = [{ +- content: '-test', +- type: 'd2h-del', +- oldNumber: 1, +- newNumber: null +- }]; +- var newLines = [{ +- content: '+test1r', +- type: 'd2h-ins', +- oldNumber: null, +- newNumber: 1 +- }]; +- +- var html = lineByLinePrinter._processLines(false, oldLines, newLines); +- +- var expected = +- '\n' + +- ' \n' + +- '
    1
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' -\n' + +- ' test\n' + +- '
    \n' + +- ' \n' + +- '\n' + +- ' \n' + +- '
    \n' + +- '
    1
    \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' test1r\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expected, html); +- }); +- }); +- +- describe('_generateFileHtml', function() { +- it('should work for simple file', function() { +- var lineByLinePrinter = new LineByLinePrinter({}); +- var file = { +- blocks: [ +- { +- lines: [ +- { +- content: ' one context line', +- type: 'd2h-cntx', +- oldNumber: 1, +- newNumber: 1 +- }, +- { +- content: '-test', +- type: 'd2h-del', +- oldNumber: 2, +- newNumber: null +- }, +- { +- content: '+test1r', +- type: 'd2h-ins', +- oldNumber: null, +- newNumber: 2 +- }, +- { +- content: '+test2r', +- type: 'd2h-ins', +- oldNumber: null, +- newNumber: 3 +- } +- ], +- oldStartLine: '1', +- oldStartLine2: null, +- newStartLine: '1', +- header: '@@ -1 +1 @@' +- } +- ], +- deletedLines: 1, +- addedLines: 1, +- checksumBefore: '0000001', +- checksumAfter: '0ddf2ba', +- oldName: 'sample', +- language: undefined, +- newName: 'sample', +- isCombined: false +- }; +- +- var html = lineByLinePrinter._generateFileHtml(file); +- +- var expected = +- '\n' + +- ' \n' + +- ' \n' + +- '
    @@ -1 +1 @@
    \n' + +- ' \n' + +- '\n' + +- ' \n' + +- '
    1
    \n' + +- '
    1
    \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- '  \n' + +- ' one context line\n' + +- '
    \n' + +- ' \n' + +- '\n' + +- ' \n' + +- '
    2
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' -\n' + +- ' test\n' + +- '
    \n' + +- ' \n' + +- '\n' + +- ' \n' + +- '
    \n' + +- '
    2
    \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' test1r\n' + +- '
    \n' + +- ' \n' + +- '\n' + +- ' \n' + +- '
    \n' + +- '
    3
    \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' test2r\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expected, html); +- }); +- }); +-}); +diff --git a/test/printer-utils-tests.js b/test/printer-utils-tests.js +deleted file mode 100644 +index b3c8213c..00000000 +--- a/test/printer-utils-tests.js ++++ /dev/null +@@ -1,140 +0,0 @@ +-var assert = require('assert'); +- +-var PrinterUtils = require('../src/printer-utils.js').PrinterUtils; +- +-describe('Utils', function() { +- describe('getHtmlId', function() { +- it('should generate file unique id', function() { +- var result = PrinterUtils.getHtmlId({ +- oldName: 'sample.js', +- newName: 'sample.js' +- }); +- assert.equal('d2h-960013', result); +- }); +- it('should generate file unique id for empty hashes', function() { +- var result = PrinterUtils.getHtmlId({ +- oldName: 'sample.js', +- newName: 'sample.js' +- }); +- assert.equal('d2h-960013', result); +- }); +- }); +- +- describe('getDiffName', function() { +- it('should generate the file name for a changed file', function() { +- var result = PrinterUtils.getDiffName({ +- oldName: 'sample.js', +- newName: 'sample.js' +- }); +- assert.equal('sample.js', result); +- }); +- it('should generate the file name for a changed file and full rename', function() { +- var result = PrinterUtils.getDiffName({ +- oldName: 'sample1.js', +- newName: 'sample2.js' +- }); +- assert.equal('sample1.js → sample2.js', result); +- }); +- it('should generate the file name for a changed file and prefix rename', function() { +- var result = PrinterUtils.getDiffName({ +- oldName: 'src/path/sample.js', +- newName: 'source/path/sample.js' +- }); +- assert.equal('{src → source}/path/sample.js', result); +- }); +- it('should generate the file name for a changed file and suffix rename', function() { +- var result = PrinterUtils.getDiffName({ +- oldName: 'src/path/sample1.js', +- newName: 'src/path/sample2.js' +- }); +- assert.equal('src/path/{sample1.js → sample2.js}', result); +- }); +- it('should generate the file name for a changed file and middle rename', function() { +- var result = PrinterUtils.getDiffName({ +- oldName: 'src/really/big/path/sample.js', +- newName: 'src/small/path/sample.js' +- }); +- assert.equal('src/{really/big → small}/path/sample.js', result); +- }); +- it('should generate the file name for a deleted file', function() { +- var result = PrinterUtils.getDiffName({ +- oldName: 'src/my/file.js', +- newName: '/dev/null' +- }); +- assert.equal('src/my/file.js', result); +- }); +- it('should generate the file name for a new file', function() { +- var result = PrinterUtils.getDiffName({ +- oldName: '/dev/null', +- newName: 'src/my/file.js' +- }); +- assert.equal('src/my/file.js', result); +- }); +- it('should generate handle undefined filename', function() { +- var result = PrinterUtils.getDiffName({}); +- assert.equal('unknown/file/path', result); +- }); +- }); +- +- describe('diffHighlight', function() { +- it('should highlight two lines', function() { +- var result = PrinterUtils.diffHighlight( +- '-var myVar = 2;', +- '+var myVariable = 3;', +- {matching: 'words'} +- ); +- +- assert.deepEqual({ +- first: { +- prefix: '-', +- line: 'var myVar = 2;' +- }, +- second: { +- prefix: '+', +- line: 'var myVariable = 3;' +- } +- }, result); +- }); +- it('should highlight two lines char by char', function() { +- var result = PrinterUtils.diffHighlight( +- '-var myVar = 2;', +- '+var myVariable = 3;', +- { diffStyle: 'char' } +- ); +- +- assert.deepEqual({ +- first: { +- prefix: '-', +- line: 'var myVar = 2;' +- }, +- second: { +- prefix: '+', +- line: 'var myVariable = 3;' +- } +- }, result); +- }); +- it('should highlight combined diff lines', function() { +- var result = PrinterUtils.diffHighlight( +- ' -var myVar = 2;', +- ' +var myVariable = 3;', +- { +- diffStyle: 'word', +- isCombined: true, +- matching: 'words', +- matchWordsThreshold: 1.00 +- } +- ); +- +- assert.deepEqual({ +- first: { +- prefix: ' -', +- line: 'var myVar = 2;' +- }, +- second: { +- prefix: ' +', +- line: 'var myVariable = 3;' +- } +- }, result); +- }); +- }); +-}); +diff --git a/test/side-by-side-printer-tests.js b/test/side-by-side-printer-tests.js +deleted file mode 100644 +index ee10c390..00000000 +--- a/test/side-by-side-printer-tests.js ++++ /dev/null +@@ -1,404 +0,0 @@ +-var assert = require('assert'); +- +-var SideBySidePrinter = require('../src/side-by-side-printer.js').SideBySidePrinter; +- +-describe('SideBySidePrinter', function() { +- describe('generateEmptyDiff', function() { +- it('should return an empty diff', function() { +- var sideBySidePrinter = new SideBySidePrinter({}); +- var fileHtml = sideBySidePrinter.generateEmptyDiff(); +- var expectedRight = ''; +- var expectedLeft = '\n' + +- ' \n' + +- '
    \n' + +- ' File without changes\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expectedRight, fileHtml.right); +- assert.equal(expectedLeft, fileHtml.left); +- }); +- }); +- +- describe('generateSideBySideFileHtml', function() { +- it('should generate lines with the right prefixes', function() { +- var sideBySidePrinter = new SideBySidePrinter({}); +- +- var file = { +- 'blocks': [ +- { +- 'lines': [ +- { +- 'content': ' context', +- 'type': 'd2h-cntx', +- 'oldNumber': 19, +- 'newNumber': 19 +- }, +- { +- 'content': '-removed', +- 'type': 'd2h-del', +- 'oldNumber': 20, +- 'newNumber': null +- }, +- { +- 'content': '+added', +- 'type': 'd2h-ins', +- 'oldNumber': null, +- 'newNumber': 20 +- }, +- { +- 'content': '+another added', +- 'type': 'd2h-ins', +- 'oldNumber': null, +- 'newNumber': 21 +- } +- ], +- 'oldStartLine': '19', +- 'newStartLine': '19', +- 'header': '@@ -19,7 +19,7 @@' +- } +- ], +- 'deletedLines': 1, +- 'addedLines': 1, +- 'checksumBefore': 'fc56817', +- 'checksumAfter': 'e8e7e49', +- 'mode': '100644', +- 'oldName': 'coverage.init', +- 'language': 'init', +- 'newName': 'coverage.init', +- 'isCombined': false +- }; +- +- var fileHtml = sideBySidePrinter.generateSideBySideFileHtml(file); +- +- var expectedLeft = +- '\n' + +- ' \n' + +- ' \n' + +- '
    @@ -19,7 +19,7 @@
    \n' + +- ' \n' + +- '\n' + +- ' \n' + +- ' 19\n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- '  \n' + +- ' context\n' + +- '
    \n' + +- ' \n' + +- '\n' + +- ' \n' + +- ' 20\n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' -\n' + +- ' removed\n' + +- '
    \n' + +- ' \n' + +- '\n' + +- ' \n' + +- ' ' + +- '\n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- '  \n' + +- '  \n' + +- '
    \n' + +- ' \n' + +- ''; +- +- var expectedRight = +- '\n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' \n' + +- '\n' + +- ' \n' + +- ' 19\n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- '  \n' + +- ' context\n' + +- '
    \n' + +- ' \n' + +- '\n' + +- ' \n' + +- ' 20\n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' added\n' + +- '
    \n' + +- ' \n' + +- '\n' + +- ' \n' + +- ' 21\n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' another added\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expectedLeft, fileHtml.left); +- assert.equal(expectedRight, fileHtml.right); +- }); +- }); +- +- describe('generateSingleLineHtml', function() { +- it('should work for insertions', function() { +- var diffParser = require('../src/diff-parser.js').DiffParser; +- var sideBySidePrinter = new SideBySidePrinter({}); +- var fileHtml = sideBySidePrinter.generateSingleLineHtml(false, +- diffParser.LINE_TYPE.INSERTS, 30, 'test', '+'); +- var expected = '\n' + +- ' \n' + +- ' 30\n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' test\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expected, fileHtml); +- }); +- it('should work for deletions', function() { +- var diffParser = require('../src/diff-parser.js').DiffParser; +- var sideBySidePrinter = new SideBySidePrinter({}); +- var fileHtml = sideBySidePrinter.generateSingleLineHtml(false, +- diffParser.LINE_TYPE.DELETES, 30, 'test', '-'); +- var expected = '\n' + +- ' \n' + +- ' 30\n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' -\n' + +- ' test\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expected, fileHtml); +- }); +- }); +- +- describe('generateSideBySideJsonHtml', function() { +- it('should work for list of files', function() { +- var exampleJson = [ +- { +- blocks: [ +- { +- lines: [ +- { +- content: '-test', +- type: 'd2h-del', +- oldNumber: 1, +- newNumber: null +- }, +- { +- content: '+test1r', +- type: 'd2h-ins', +- oldNumber: null, +- newNumber: 1 +- } +- ], +- oldStartLine: '1', +- oldStartLine2: null, +- newStartLine: '1', +- header: '@@ -1 +1 @@' +- } +- ], +- deletedLines: 1, +- addedLines: 1, +- checksumBefore: '0000001', +- checksumAfter: '0ddf2ba', +- oldName: 'sample', +- language: undefined, +- newName: 'sample', +- isCombined: false +- } +- ]; +- +- var sideBySidePrinter = new SideBySidePrinter({matching: 'lines'}); +- var html = sideBySidePrinter.generateSideBySideJsonHtml(exampleJson); +- var expected = +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' sample\n' + +- ' CHANGED\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- '\n' + +- ' \n' + +- ' \n' + +- '\n' + +- ' \n' + +- '
    \n' + +- '
    @@ -1 +1 @@
    \n' + +- '
    \n' + +- ' 1\n' + +- ' \n' + +- '
    \n' + +- ' -\n' + +- ' test\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- '\n' + +- ' \n' + +- ' \n' + +- '\n' + +- ' \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' 1\n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' test1r\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    '; +- +- assert.equal(expected, html); +- }); +- it('should work for files without blocks', function() { +- var exampleJson = [{ +- blocks: [], +- oldName: 'sample', +- language: 'js', +- newName: 'sample', +- isCombined: false +- }]; +- +- var sideBySidePrinter = new SideBySidePrinter(); +- var html = sideBySidePrinter.generateSideBySideJsonHtml(exampleJson); +- var expected = +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' sample\n' + +- ' CHANGED\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- '\n' + +- ' \n' + +- '
    \n' + +- '
    \n' + +- ' File without changes\n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    \n' + +- '
    '; +- +- assert.equal(expected, html); +- }); +- }); +- +- describe('processLines', function() { +- it('should process file lines', function() { +- var oldLines = [{ +- content: '-test', +- type: 'd2h-del', +- oldNumber: 1, +- newNumber: null +- }]; +- +- var newLines = [{ +- content: '+test1r', +- type: 'd2h-ins', +- oldNumber: null, +- newNumber: 1 +- }]; +- +- var sideBySidePrinter = new SideBySidePrinter({matching: 'lines'}); +- var html = sideBySidePrinter.processLines(false, oldLines, newLines); +- var expectedLeft = +- '\n' + +- ' \n' + +- ' 1\n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' -\n' + +- ' test\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- var expectedRight = +- '\n' + +- ' \n' + +- ' 1\n' + +- ' \n' + +- ' \n' + +- '
    \n' + +- ' +\n' + +- ' test1r\n' + +- '
    \n' + +- ' \n' + +- ''; +- +- assert.equal(expectedLeft, html.left); +- assert.equal(expectedRight, html.right); +- }); +- }); +-}); +diff --git a/test/utils-tests.js b/test/utils-tests.js +deleted file mode 100644 +index fec64a91..00000000 +--- a/test/utils-tests.js ++++ /dev/null +@@ -1,25 +0,0 @@ +-var assert = require('assert'); +- +-var Utils = require('../src/utils.js').Utils; +- +-describe('Utils', function() { +- describe('escape', function() { +- it('should escape & with &', function() { +- var result = Utils.escape('&'); +- assert.equal('&', result); +- }); +- it('should escape < with <', function() { +- var result = Utils.escape('<'); +- assert.equal('<', result); +- }); +- it('should escape > with >', function() { +- var result = Utils.escape('>'); +- assert.equal('>', result); +- }); +- it('should escape a string with multiple problematic characters', function() { +- var result = Utils.escape('\tlink text'); +- var expected = '<a href="#">\tlink text</a>'; +- assert.equal(expected, result); +- }); +- }); +-}); +diff --git a/tsconfig.json b/tsconfig.json +new file mode 100644 +index 00000000..5d8b11ca +--- /dev/null ++++ b/tsconfig.json +@@ -0,0 +1,28 @@ ++{ ++ "compilerOptions": { ++ "outDir": "./_target", ++ "target": "es5", ++ "module": "commonjs", ++ "moduleResolution": "node", ++ "lib": ["es2015", "dom"], ++ "allowJs": false, ++ "declaration": true, ++ "declarationMap": true, ++ "strictNullChecks": true, ++ "removeComments": true, ++ "preserveConstEnums": true, ++ "sourceMap": true, ++ "alwaysStrict": true, ++ "strict": true, ++ "noImplicitAny": true, ++ "noImplicitThis": true, ++ "noUnusedParameters": true, ++ "noUnusedLocals": true, ++ "noImplicitReturns": true, ++ "noFallthroughCasesInSwitch": true, ++ "forceConsistentCasingInFileNames": true, ++ "esModuleInterop": true ++ }, ++ "include": ["./src/**/*", "./typings/**/*"], ++ "exclude": ["node_modules", "./src/__tests__/*"] ++} +diff --git a/typings/merge.d.ts b/typings/merge.d.ts +new file mode 100644 +index 00000000..98816823 +--- /dev/null ++++ b/typings/merge.d.ts +@@ -0,0 +1,3 @@ ++declare module "merge" { ++ export function recursive(clone: boolean, ...items: object[]): object; ++} +diff --git a/webpack.bundles.ts b/webpack.bundles.ts +new file mode 100644 +index 00000000..61d1896c +--- /dev/null ++++ b/webpack.bundles.ts +@@ -0,0 +1,60 @@ ++import path from "path"; ++ ++import webpack from "webpack"; ++ ++const minimize = process.env.WEBPACK_MINIFY === "true"; ++ ++const diff2htmlBrowserConfig: webpack.Configuration = { ++ mode: "production", ++ optimization: { minimize: minimize }, ++ module: { ++ rules: [ ++ { ++ test: /\.tsx?$/, ++ use: "ts-loader", ++ exclude: /node_modules/ ++ } ++ ] ++ }, ++ resolve: { ++ extensions: [".tsx", ".ts", ".jsx", ".js"] ++ }, ++ entry: "./src/diff2html.ts", ++ output: { ++ path: path.resolve(__dirname, "bundles/js"), ++ libraryTarget: "umd", ++ globalObject: "this", ++ library: "Diff2Html", ++ filename: `diff2html${minimize ? ".min" : ""}.js`, ++ umdNamedDefine: true ++ } ++}; ++ ++const diff2htmlUIBrowserConfig: webpack.Configuration = { ++ mode: "production", ++ optimization: { minimize: minimize }, ++ module: { ++ rules: [ ++ { ++ test: /\.tsx?$/, ++ use: "ts-loader", ++ exclude: /node_modules/ ++ } ++ ] ++ }, ++ resolve: { ++ extensions: [".tsx", ".ts", ".jsx", ".js"] ++ }, ++ entry: "./src/ui/js/diff2html-ui.ts", ++ output: { ++ path: path.resolve(__dirname, "bundles/js"), ++ libraryTarget: "umd", ++ globalObject: "this", ++ filename: `diff2html-ui${minimize ? ".min" : ""}.js`, ++ umdNamedDefine: true ++ } ++}; ++ ++const config: webpack.Configuration[] = [diff2htmlBrowserConfig, diff2htmlUIBrowserConfig]; ++ ++export default config; +diff --git a/webpack.website.ts b/webpack.website.ts +new file mode 100644 +index 00000000..f8a6b9a8 +--- /dev/null ++++ b/webpack.website.ts +@@ -0,0 +1,170 @@ ++import path from "path"; ++ ++import webpack from "webpack"; ++import { Plugin } from "postcss"; ++import HtmlWebpackPlugin from "html-webpack-plugin"; ++import MiniCssExtractPlugin from "mini-css-extract-plugin"; ++import autoprefixer from "autoprefixer"; ++import CopyWebpackPlugin from "copy-webpack-plugin"; ++ ++const isDevelopment = process.env.NODE_ENV !== "production"; ++const minimize = process.env.WEBPACK_MINIFY === "true"; ++ ++const pages = ["index", "demo"]; ++ ++const config: webpack.Configuration[] = pages.map(page => { ++ return { ++ devServer: { ++ port: 3000, ++ open: true, ++ contentBase: path.join(__dirname, "./website") ++ }, ++ entry: { ++ [page]: `./website/templates/pages/${page}/${page}.ts` ++ }, ++ output: { ++ path: path.resolve(__dirname, "./docs") ++ }, ++ resolve: { ++ extensions: [".tsx", ".ts", ".jsx", ".js"] ++ }, ++ optimization: { minimize }, ++ module: { ++ rules: [ ++ { ++ test: /\.tsx?$/, ++ use: "ts-loader", ++ exclude: /node_modules/ ++ }, ++ { ++ test: /\.handlebars$/, ++ loader: "handlebars-loader", ++ options: { ++ precompileOptions: { ++ knownHelpersOnly: false ++ }, ++ helperDirs: [path.join(__dirname, "website/templates/helpers")], ++ partialDirs: [path.join(__dirname, "website/templates")] ++ } ++ }, ++ { ++ test: /\.(css)$/, ++ use: [ ++ MiniCssExtractPlugin.loader, ++ { ++ loader: "css-loader", ++ options: { ++ sourceMap: isDevelopment ++ } ++ }, ++ { ++ loader: "postcss-loader", ++ options: { ++ autoprefixer: { ++ browsers: ["last 2 versions"] ++ }, ++ sourceMap: isDevelopment, ++ plugins: (): Plugin[] => [autoprefixer] ++ } ++ } ++ ] ++ }, ++ { ++ test: /\.(html)$/, ++ use: { ++ loader: "html-loader", ++ options: { ++ attrs: ["img:src"] ++ } ++ } ++ }, ++ { ++ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, ++ use: [ ++ { ++ loader: "url-loader", ++ options: { ++ limit: 1000, ++ mimetype: "application/font-woff" ++ } ++ } ++ ] ++ }, ++ { ++ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, ++ loader: "file-loader" ++ }, ++ { ++ test: /\.(jpeg|jpg|png|gif)$/, ++ use: [ ++ { ++ loader: "file-loader", ++ options: { ++ name: "[name].[ext]", ++ outputPath: "images/", ++ useRelativePath: true ++ } ++ }, ++ { ++ loader: "image-webpack-loader", ++ options: { ++ mozjpeg: { ++ progressive: true, ++ quality: 65 ++ }, ++ optipng: { ++ enabled: true ++ }, ++ pngquant: { ++ quality: [0.65, 0.9], ++ speed: 4 ++ }, ++ gifsicle: { ++ interlaced: false ++ }, ++ webp: { ++ quality: 75 ++ } ++ } ++ } ++ ] ++ } ++ ] ++ }, ++ plugins: [ ++ new MiniCssExtractPlugin({ ++ filename: "[name].css", ++ chunkFilename: "[id].css" ++ }), ++ new HtmlWebpackPlugin({ ++ hash: true, ++ inject: true, ++ title: `${page} page`, ++ filename: `${page}.html`, ++ template: `./website/templates/pages/${page}/${page}.handlebars`, ++ minify: !isDevelopment && { ++ html5: true, ++ collapseWhitespace: true, ++ caseSensitive: true, ++ removeEmptyElements: false, ++ removeComments: true, ++ removeRedundantAttributes: true, ++ useShortDoctype: true, ++ removeEmptyAttributes: true, ++ removeStyleLinkTypeAttributes: true, ++ keepClosingSlash: true, ++ minifyJS: true, ++ minifyCSS: true, ++ minifyURLs: true ++ } ++ }), ++ new CopyWebpackPlugin([ ++ { from: "website/favicon.ico", to: "favicon.ico" }, ++ { from: "website/robots.txt", to: "robots.txt" }, ++ { from: "website/sitemap.xml", to: "sitemap.xml" } ++ ]) ++ ] ++ }; ++}); ++ ++export default config; +diff --git a/website/CNAME b/website/CNAME +deleted file mode 100644 +index 62ff2fdd..00000000 +--- a/website/CNAME ++++ /dev/null +@@ -1 +0,0 @@ +-diff2html.xyz +\ No newline at end of file +diff --git a/website/img/snapshot-1.png b/website/img/snapshot-1.png +deleted file mode 100644 +index d52efdaf..00000000 +Binary files a/website/img/snapshot-1.png and /dev/null differ +diff --git a/website/img/snapshot-2.png b/website/img/snapshot-2.png +deleted file mode 100644 +index fb52e799..00000000 +Binary files a/website/img/snapshot-2.png and /dev/null differ +diff --git a/website/img/snapshot-3.png b/website/img/snapshot-3.png +deleted file mode 100644 +index afe3a0f1..00000000 +Binary files a/website/img/snapshot-3.png and /dev/null differ +diff --git a/website/main.css b/website/main.css +index c25a95f7..0d3ad50c 100644 +--- a/website/main.css ++++ b/website/main.css +@@ -255,94 +255,6 @@ + + } + +-.screenshot { +- display: block; +- overflow: hidden; +-} +- +-.screenshot > img { +- width: 100% +-} +- +-.screenshots-fan { +- margin-top: 50px +-} +- +-.screenshots-fan .screenshot { +- position: relative; +- width: auto; +- display: inline-block; +- text-align: center; +-} +- +-.screenshots-fan .screenshot:last-child, .screenshots-fan .screenshot:first-child { +- z-index: 2 +-} +- +-.screenshots-fan .screenshot { +- z-index: 3 +-} +- +-@media (min-width: 768px) { +- .screenshots-fan { +- position: relative; +- overflow: hidden; +- margin-top: 60px; +- height: 200px +- } +- +- .screenshots-fan .screenshot { +- height: auto; +- top: 10px; +- width: 350px +- } +- +- .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { +- width: 250px; +- position: absolute; +- top: 65px +- } +- +- .screenshots-fan .screenshot:first-child { +- left: 10px +- } +- +- .screenshots-fan .screenshot:last-child { +- left: auto; +- right: 10px +- } +-} +- +-@media (min-width: 992px) { +- .screenshots-fan { +- margin-top: 60px; +- height: 240px +- } +- +- .screenshots-fan .screenshot { +- width: 400px +- } +- +- .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { +- width: 300px +- } +-} +- +-@media (min-width: 1200px) { +- .screenshots-fan { +- margin-top: 80px; +- height: 380px +- } +- +- .screenshots-fan .screenshot { +- width: 550px +- } +- +- .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { +- width: 450px +- } +-} +- + body { + font-size: 16px; + font-family: Roboto, sans-serif; +diff --git a/website/main.ts b/website/main.ts +new file mode 100644 +index 00000000..35216688 +--- /dev/null ++++ b/website/main.ts +@@ -0,0 +1 @@ ++import "bootstrap/dist/css/bootstrap.css"; +diff --git a/website/templates/helpers/block.ts b/website/templates/helpers/block.ts +new file mode 100644 +index 00000000..192a61c0 +--- /dev/null ++++ b/website/templates/helpers/block.ts +@@ -0,0 +1,15 @@ ++import handlebars, { HelperOptions } from "handlebars"; ++ ++const loadPartial = (name: string): handlebars.Template => { ++ let partial = handlebars.partials[name]; ++ if (typeof partial === "string") { ++ partial = handlebars.compile(partial); ++ handlebars.partials[name] = partial; ++ } ++ return partial; ++}; ++ ++export default (name: string, options: HelperOptions): string => { ++ const partial = loadPartial(name) || options.fn; ++ return partial(this, { data: options.hash }); ++}; +diff --git a/website/templates/helpers/partial.ts b/website/templates/helpers/partial.ts +new file mode 100644 +index 00000000..108eba31 +--- /dev/null ++++ b/website/templates/helpers/partial.ts +@@ -0,0 +1,5 @@ ++import handlebars, { HelperOptions } from "handlebars"; ++ ++export default (name: string, options: HelperOptions): void => { ++ handlebars.registerPartial(name, options.fn); ++}; +diff --git a/website/templates/pages/demo/content.handlebars b/website/templates/pages/demo/content.handlebars +new file mode 100644 +index 00000000..d2640b07 +--- /dev/null ++++ b/website/templates/pages/demo/content.handlebars +@@ -0,0 +1,95 @@ ++

    Diff Prettifier ++ ++ ++

    ++

    GitHub, Bitbucket and GitLab commit and pull request compatible

    ++

    Just paste the GitHub, Bitbucket or GitLab commit, pull request or merge request url ++ or any other git or unified compatible diff and we will render a pretty html representation of it ++ with code syntax highlight and line similarity matching for better code reviews. ++

    ++

    Options:

    ++
    ++
    ++ ++
    ++
    ++ ++
    ++
    ++ ++
    ++
    ++ ++
    ++
    ++ ++
    ++
    ++
    ++
    ++ ++ Load ++
    ++
    ++
    ++
    ++
    ++

    Help:

    ++
      ++
    • ++ Why should I use this instead of GitHub, Bitbucket or GitLab? ++

      Code Syntax Highlight

      ++

      Line similarity match (similar lines are together)

      ++

      Line by Line and Side by Side diffs

      ++

      Supports any git and unified compatible diffs

      ++

      Easy code selection

      ++
    • ++
    • ++ What urls are supported? ++

      Any GitHub, Bitbucket or GitLab Commit, Pull Request or Merge Request urls.

      ++

      Any Git or Unified Raw Diff or Patch urls.

      ++
    • ++
    • ++ Can I send a custom url for a friend, colleague or co-worker? ++

      Just add a url parameter called diff to current url using as value your Commit, Pull Request, Merge Request, Diff ++ or Patch url.

      ++

      ex: https://diff2html.xyz/demo.html ++

      ++
    • ++
    • ++ Why can't I paste a diff? ++

      diffy.org is an amazing tool created by pbu88 ++ to share your diffs and uses diff2html under the hood.

      ++

      Also, diff2html cli can directly publish diffs to diffy.org

      ++
    • ++
    ++
    ++

    Thank you

    ++

    I want to thank kevinsimper for this great idea, ++ providing better diff support for existing online services. ++

    +\ No newline at end of file +diff --git a/website/templates/pages/demo/demo-assets.partial.mustache b/website/templates/pages/demo/demo-assets.partial.mustache +deleted file mode 100644 +index 6cac9341..00000000 +--- a/website/templates/pages/demo/demo-assets.partial.mustache ++++ /dev/null +@@ -1,5 +0,0 @@ +- +- +- +- +- +diff --git a/website/templates/pages/demo/demo-scripts.partial.mustache b/website/templates/pages/demo/demo-scripts.partial.mustache +deleted file mode 100644 +index b1cd3133..00000000 +--- a/website/templates/pages/demo/demo-scripts.partial.mustache ++++ /dev/null +@@ -1,9 +0,0 @@ +- +- +- +- +- +- +- +- +- +diff --git a/website/templates/pages/demo/demo.css b/website/templates/pages/demo/demo.css +new file mode 100644 +index 00000000..72ef256f +--- /dev/null ++++ b/website/templates/pages/demo/demo.css +@@ -0,0 +1 @@ ++@import url("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/github.min.css"); +diff --git a/website/templates/pages/demo/demo.handlebars b/website/templates/pages/demo/demo.handlebars +new file mode 100644 +index 00000000..0087900b +--- /dev/null ++++ b/website/templates/pages/demo/demo.handlebars +@@ -0,0 +1,4 @@ ++{{#partial "content"}} ++{{> content}} ++{{/partial}} ++{{> ../../template}} +\ No newline at end of file +diff --git a/website/templates/pages/demo/demo.js b/website/templates/pages/demo/demo.js +deleted file mode 100644 +index f2b13262..00000000 +--- a/website/templates/pages/demo/demo.js ++++ /dev/null +@@ -1,233 +0,0 @@ +-/* global Diff2HtmlUI */ +- +-/* +- * Example URLs: +- * +- * https://github.com/rtfpessoa/diff2html/commit/7d02e67f3b3386ac5d804f974d025cd7a1165839 +- * https://github.com/rtfpessoa/diff2html/pull/106 +- * +- * https://gitlab.com/gitlab-org/gitlab-ce/commit/4e963fed42ad518caa7353d361a38a1250c99c41 +- * https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6763 +- * +- * https://bitbucket.org/atlassian/amps/commits/52c38116f12475f75af4a147b7a7685478b83eca +- * https://bitbucket.org/atlassian/amps/pull-requests/236 +- */ +- +-$(document).ready(function() { +- // Improves browser compatibility +- require('whatwg-fetch'); +- +- var searchParam = 'diff'; +- +- var $container = $('.container'); +- var $url = $('#url'); +- var $outputFormat = $('#diff-url-options-output-format'); +- var $showFiles = $('#diff-url-options-show-files'); +- var $matching = $('#diff-url-options-matching'); +- var $wordsThreshold = $('#diff-url-options-match-words-threshold'); +- var $matchingMaxComparisons = $('#diff-url-options-matching-max-comparisons'); +- +- if (window.location.search) { +- var url = getUrlFromSearch(window.location.search); +- $url.val(url); +- smartDraw(url); +- } +- +- bind(); +- +- $outputFormat +- .add($showFiles) +- .add($matching) +- .add($wordsThreshold) +- .add($matchingMaxComparisons) +- .change(function(e) { +- console.log(''); +- console.log(e); +- console.log(''); +- smartDraw(null, true); +- }); +- +- function getUrlFromSearch(search) { +- try { +- return search +- .split('?')[1] +- .split(searchParam + '=')[1] +- .split('&')[0]; +- } catch (_ignore) { +- } +- +- return null; +- } +- +- function getParamsFromSearch(search) { +- var map = {}; +- try { +- search +- .split('?')[1] +- .split('&') +- .map(function(e) { +- var values = e.split('='); +- map[values[0]] = values[1]; +- }); +- } catch (_ignore) { +- } +- +- return map; +- } +- +- function bind() { +- $('#url-btn').click(function(e) { +- e.preventDefault(); +- var url = $url.val(); +- smartDraw(url); +- }); +- +- $url.on('paste', function(e) { +- var url = e.originalEvent.clipboardData.getData('Text'); +- smartDraw(url); +- }); +- } +- +- function prepareUrl(url) { +- var fetchUrl; +- var headers = new Headers(); +- +- var githubCommitUrl = /^https?:\/\/(?:www\.)?github\.com\/(.*?)\/(.*?)\/commit\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; +- var githubPrUrl = /^https?:\/\/(?:www\.)?github\.com\/(.*?)\/(.*?)\/pull\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; +- +- var gitlabCommitUrl = /^https?:\/\/(?:www\.)?gitlab\.com\/(.*?)\/(.*?)\/commit\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; +- var gitlabPrUrl = /^https?:\/\/(?:www\.)?gitlab\.com\/(.*?)\/(.*?)\/merge_requests\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; +- +- var bitbucketCommitUrl = /^https?:\/\/(?:www\.)?bitbucket\.org\/(.*?)\/(.*?)\/commits\/(.*?)(?:\/raw)?(?:\/.*)?$/; +- var bitbucketPrUrl = /^https?:\/\/(?:www\.)?bitbucket\.org\/(.*?)\/(.*?)\/pull-requests\/(.*?)(?:\/.*)?$/; +- +- function gitLabUrlGen(userName, projectName, type, value) { +- return 'https://crossorigin.me/https://gitlab.com/' + userName + '/' + projectName + '/' + type + '/' + value + '.diff'; +- } +- +- function gitHubUrlGen(userName, projectName, type, value) { +- headers.append('Accept', 'application/vnd.github.v3.diff'); +- return 'https://api.github.com/repos/' + userName + '/' + projectName + '/' + type + '/' + value; +- } +- +- function bitbucketUrlGen(userName, projectName, type, value) { +- var baseUrl = 'https://bitbucket.org/api/2.0/repositories/'; +- if (type === 'pullrequests') { +- return baseUrl + userName + '/' + projectName + '/pullrequests/' + value + '/diff'; +- } +- return baseUrl + userName + '/' + projectName + '/diff/' + value; +- } +- +- var values; +- if ((values = githubCommitUrl.exec(url))) { +- fetchUrl = gitHubUrlGen(values[1], values[2], 'commits', values[3]); +- } else if ((values = githubPrUrl.exec(url))) { +- fetchUrl = gitHubUrlGen(values[1], values[2], 'pulls', values[3]); +- } else if ((values = gitlabCommitUrl.exec(url))) { +- fetchUrl = gitLabUrlGen(values[1], values[2], 'commit', values[3]); +- } else if ((values = gitlabPrUrl.exec(url))) { +- fetchUrl = gitLabUrlGen(values[1], values[2], 'merge_requests', values[3]); +- } else if ((values = bitbucketCommitUrl.exec(url))) { +- fetchUrl = bitbucketUrlGen(values[1], values[2], 'commit', values[3]); +- } else if ((values = bitbucketPrUrl.exec(url))) { +- fetchUrl = bitbucketUrlGen(values[1], values[2], 'pullrequests', values[3]); +- } else { +- console.info('Could not parse url, using the provided url.'); +- fetchUrl = 'https://crossorigin.me/' + url; +- } +- +- return { +- originalUrl: url, +- url: fetchUrl, +- headers: headers +- }; +- } +- +- function smartDraw(urlOpt, forced) { +- var url = urlOpt || $url.val(); +- var req = prepareUrl(url); +- draw(req, forced); +- } +- +- function draw(req, forced) { +- if (!validateUrl(req.url)) { +- console.error('Invalid url provided!'); +- return; +- } +- +- if (validateUrl(req.originalUrl)) updateUrl(req.originalUrl); +- +- var outputFormat = $outputFormat.val(); +- var showFiles = $showFiles.is(':checked'); +- var matching = $matching.val(); +- var wordsThreshold = $wordsThreshold.val(); +- var matchingMaxComparisons = $matchingMaxComparisons.val(); +- +- fetch(req.url, { +- method: 'GET', +- headers: req.headers, +- mode: 'cors', +- cache: 'default' +- }) +- .then(function(res) { +- return res.text(); +- }) +- .then(function(data) { +- var container = '#url-diff-container'; +- var diff2htmlUi = new Diff2HtmlUI({diff: data}); +- +- if (outputFormat === 'side-by-side') { +- $container.css({'width': '100%'}); +- } else { +- $container.css({'width': ''}); +- } +- +- var params = getParamsFromSearch(window.location.search); +- delete params[searchParam]; +- +- if (forced) { +- params['outputFormat'] = outputFormat; +- params['showFiles'] = showFiles; +- params['matching'] = matching; +- params['wordsThreshold'] = wordsThreshold; +- params['matchingMaxComparisons'] = matchingMaxComparisons; +- } else { +- params['outputFormat'] = params['outputFormat'] || outputFormat; +- params['showFiles'] = String(params['showFiles']) !== 'false' || (params['showFiles'] === null && showFiles); +- params['matching'] = params['matching'] || matching; +- params['wordsThreshold'] = params['wordsThreshold'] || wordsThreshold; +- params['matchingMaxComparisons'] = params['matchingMaxComparisons'] || matchingMaxComparisons; +- +- $outputFormat.val(params['outputFormat']); +- $showFiles.prop('checked', params['showFiles']); +- $matching.val(params['matching']); +- $wordsThreshold.val(params['wordsThreshold']); +- $matchingMaxComparisons.val(params['matchingMaxComparisons']); +- } +- +- params['synchronisedScroll'] = params['synchronisedScroll'] || true; +- +- diff2htmlUi.draw(container, params); +- diff2htmlUi.fileListCloseable(container, params['fileListCloseable'] || false); +- if (params['highlight'] === undefined || params['highlight']) { +- diff2htmlUi.highlightCode(container); +- } +- }); +- } +- +- function validateUrl(url) { +- return /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(url); +- } +- +- function updateUrl(url) { +- var params = getParamsFromSearch(window.location.search); +- +- if (params[searchParam] === url) return; +- +- params[searchParam] = url; +- +- var paramString = Object.keys(params).map(function(k) { return k + '=' + params[k]; }).join('&'); +- +- window.location = 'demo.html?' + paramString; +- } +-}); +diff --git a/website/templates/pages/demo/demo.partial.mustache b/website/templates/pages/demo/demo.partial.mustache +deleted file mode 100644 +index 17970635..00000000 +--- a/website/templates/pages/demo/demo.partial.mustache ++++ /dev/null +@@ -1,96 +0,0 @@ +-

    Diff Prettifier +- +- +-

    +-

    GitHub, Bitbucket and GitLab commit and pull request compatible

    +-

    Just paste the GitHub, Bitbucket or GitLab commit, pull request or merge request url +- or any other git or unified compatible diff and we will render a pretty html representation of it +- with code syntax highlight and line similarity matching for better code reviews. +-

    +-

    Options:

    +-
    +-
    +- +-
    +-
    +- +-
    +-
    +- +-
    +-
    +- +-
    +-
    +- +-
    +-
    +-
    +-
    +- +- Load +-
    +-
    +-
    +-
    +-
    +-

    Help:

    +-
      +-
    • +- Why should I use this instead of GitHub, Bitbucket or GitLab? +-

      Code Syntax Highlight

      +-

      Line similarity match (similar lines are together)

      +-

      Line by Line and Side by Side diffs

      +-

      Supports any git and unified compatible diffs

      +-

      Easy code selection

      +-
    • +-
    • +- What urls are supported? +-

      Any GitHub, Bitbucket or GitLab Commit, Pull Request or Merge Request urls.

      +-

      Any Git or Unified Raw Diff or Patch urls.

      +-
    • +-
    • +- Can I send a custom url for a friend, colleague or co-worker? +-

      Just add a url parameter called diff to current url using as value your Commit, Pull Request, Merge Request, Diff +- or Patch url.

      +-

      ex: https://diff2html.xyz/{{ demoUrl }} +-

      +-
    • +-
    • +- Why can't I paste a diff? +-

      diffy.org is an amazing tool created by pbu88 +- to share your diffs and uses diff2html under the hood.

      +-

      Also, diff2html cli can directly publish diffs to diffy.org

      +-
    • +-
    +-
    +-

    Thank you

    +-

    I want to thank kevinsimper for this great idea, +- providing better diff support for existing online services. +-

    +diff --git a/website/templates/pages/demo/demo.ts b/website/templates/pages/demo/demo.ts +new file mode 100644 +index 00000000..30730e9f +--- /dev/null ++++ b/website/templates/pages/demo/demo.ts +@@ -0,0 +1,287 @@ ++import { Diff2HtmlUI, defaultDiff2HtmlUIConfig, Diff2HtmlUIConfig } from "../../../../src/ui/js/diff2html-ui"; ++ ++import "../../../main.ts"; ++import "../../../main.css"; ++import "./demo.css"; ++import "../../../../src/ui/css/diff2html.css"; ++ ++/* ++ * Example URLs: ++ * ++ * https://github.com/rtfpessoa/diff2html/commit/7d02e67f3b3386ac5d804f974d025cd7a1165839 ++ * https://github.com/rtfpessoa/diff2html/pull/106 ++ * ++ * https://gitlab.com/gitlab-org/gitlab-ce/commit/4e963fed42ad518caa7353d361a38a1250c99c41 ++ * https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6763 ++ * ++ * https://bitbucket.org/atlassian/amps/commits/52c38116f12475f75af4a147b7a7685478b83eca ++ * https://bitbucket.org/atlassian/amps/pull-requests/236 ++ */ ++ ++type URLParams = { ++ diff?: string; ++ [key: string]: string | boolean | number | undefined; ++}; ++ ++const searchParam = "diff"; ++ ++function getParamsFromSearch(search: string): URLParams { ++ try { ++ return search ++ .split("?")[1] ++ .split("&") ++ .reduce((urlParams, e) => { ++ const values = e.split("="); ++ return { ++ ...urlParams, ++ [values[0]]: values[1] ++ }; ++ }, {}); ++ } catch (_ignore) { ++ return {}; ++ } ++} ++ ++function validateUrl(url: string): boolean { ++ return /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( ++ url ++ ); ++} ++ ++type Request = { ++ url: string; ++ headers: Headers; ++}; ++ ++function prepareRequest(url: string): Request { ++ if (!validateUrl(url)) { ++ const errorMsg = "Invalid url provided!"; ++ console.error(errorMsg); ++ throw new Error(errorMsg); ++ } ++ ++ let fetchUrl; ++ const headers = new Headers(); ++ ++ const githubCommitUrl = /^https?:\/\/(?:www\.)?github\.com\/(.*?)\/(.*?)\/commit\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; ++ const githubPrUrl = /^https?:\/\/(?:www\.)?github\.com\/(.*?)\/(.*?)\/pull\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; ++ ++ const gitlabCommitUrl = /^https?:\/\/(?:www\.)?gitlab\.com\/(.*?)\/(.*?)\/commit\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; ++ const gitlabPrUrl = /^https?:\/\/(?:www\.)?gitlab\.com\/(.*?)\/(.*?)\/merge_requests\/(.*?)(?:\.diff)?(?:\.patch)?(?:\/.*)?$/; ++ ++ const bitbucketCommitUrl = /^https?:\/\/(?:www\.)?bitbucket\.org\/(.*?)\/(.*?)\/commits\/(.*?)(?:\/raw)?(?:\/.*)?$/; ++ const bitbucketPrUrl = /^https?:\/\/(?:www\.)?bitbucket\.org\/(.*?)\/(.*?)\/pull-requests\/(.*?)(?:\/.*)?$/; ++ ++ function gitLabUrlGen(userName: string, projectName: string, type: string, value: string): string { ++ return ( ++ "https://crossorigin.me/https://gitlab.com/" + userName + "/" + projectName + "/" + type + "/" + value + ".diff" ++ ); ++ } ++ ++ function gitHubUrlGen(userName: string, projectName: string, type: string, value: string): string { ++ headers.append("Accept", "application/vnd.github.v3.diff"); ++ return "https://api.github.com/repos/" + userName + "/" + projectName + "/" + type + "/" + value; ++ } ++ ++ function bitbucketUrlGen(userName: string, projectName: string, type: string, value: string): string { ++ const baseUrl = "https://bitbucket.org/api/2.0/repositories/"; ++ if (type === "pullrequests") { ++ return baseUrl + userName + "/" + projectName + "/pullrequests/" + value + "/diff"; ++ } ++ return baseUrl + userName + "/" + projectName + "/diff/" + value; ++ } ++ ++ let values; ++ if ((values = githubCommitUrl.exec(url))) { ++ fetchUrl = gitHubUrlGen(values[1], values[2], "commits", values[3]); ++ } else if ((values = githubPrUrl.exec(url))) { ++ fetchUrl = gitHubUrlGen(values[1], values[2], "pulls", values[3]); ++ } else if ((values = gitlabCommitUrl.exec(url))) { ++ fetchUrl = gitLabUrlGen(values[1], values[2], "commit", values[3]); ++ } else if ((values = gitlabPrUrl.exec(url))) { ++ fetchUrl = gitLabUrlGen(values[1], values[2], "merge_requests", values[3]); ++ } else if ((values = bitbucketCommitUrl.exec(url))) { ++ fetchUrl = bitbucketUrlGen(values[1], values[2], "commit", values[3]); ++ } else if ((values = bitbucketPrUrl.exec(url))) { ++ fetchUrl = bitbucketUrlGen(values[1], values[2], "pullrequests", values[3]); ++ } else { ++ console.info("Could not parse url, using the provided url."); ++ fetchUrl = "https://crossorigin.me/" + url; ++ } ++ ++ return { ++ url: fetchUrl, ++ headers: headers ++ }; ++} ++ ++function getConfiguration(urlParams: URLParams): Diff2HtmlUIConfig { ++ // Removing `diff` form `urlParams` to avoid being inserted ++ // eslint-disable-next-line @typescript-eslint/no-unused-vars ++ const { diff, ...urlParamsRest } = urlParams; ++ const config: URLParams = { ++ ...defaultDiff2HtmlUIConfig, ++ ...urlParamsRest ++ }; ++ ++ return Object.entries(config).reduce((object, [k, v]) => { ++ const newObject = !Number.isNaN(Number(v)) ++ ? { [k]: Number(v) } ++ : v === "true" || v === "false" ++ ? { [k]: Boolean(v) } ++ : { [k]: v }; ++ return { ...object, ...newObject }; ++ }, {}); ++} ++ ++async function getDiff(request: Request): Promise { ++ try { ++ const result = await fetch(request.url, { ++ method: "GET", ++ headers: request.headers, ++ mode: "cors", ++ cache: "default" ++ }); ++ return result.text(); ++ } catch (error) { ++ console.error("Failed to retrieve diff", error); ++ throw error; ++ } ++} ++ ++function draw(diffString: string, config: Diff2HtmlUIConfig, elements: Elements): void { ++ const diff2htmlUi = new Diff2HtmlUI(diffString, elements.structure.diffTarget, config); ++ ++ if (config.outputFormat === "side-by-side") { ++ elements.structure.container.style.width = "100%"; ++ } else { ++ elements.structure.container.style.width = ""; ++ } ++ ++ diff2htmlUi.draw(); ++} ++ ++async function prepareInitialState(elements: Elements): Promise<[Diff2HtmlUIConfig, string]> { ++ const urlParams = getParamsFromSearch(window.location.search); ++ const currentUrl = (urlParams && urlParams[searchParam]) || "https://github.com/rtfpessoa/diff2html/pull/106"; ++ ++ if (currentUrl !== elements.url.input.value) elements.url.input.value = currentUrl; ++ ++ const request = prepareRequest(currentUrl); ++ ++ const initialConfiguration = getConfiguration(urlParams); ++ const initialDiff = await getDiff(request); ++ ++ return [initialConfiguration, initialDiff]; ++} ++ ++function updateBrowserUrl(config: Diff2HtmlUIConfig, newDiffUrl: string): void { ++ if (history.pushState) { ++ const paramString = Object.entries(config) ++ .map(([k, v]) => k + "=" + v) ++ .join("&"); ++ const newPageUrl = ++ window.location.protocol + ++ "//" + ++ window.location.host + ++ window.location.pathname + ++ "?" + ++ paramString + ++ "&" + ++ searchParam + ++ "=" + ++ newDiffUrl; ++ window.history.pushState({ path: newPageUrl }, "", newPageUrl); ++ } ++} ++ ++type Elements = { ++ structure: { ++ container: HTMLElement; ++ diffTarget: HTMLElement; ++ }; ++ url: { ++ input: HTMLInputElement; ++ button: HTMLElement; ++ }; ++ options: { ++ outputFormat: HTMLInputElement; ++ matching: HTMLInputElement; ++ wordsThreshold: HTMLInputElement; ++ matchingMaxComparisons: HTMLInputElement; ++ }; ++ checkboxes: { ++ drawFileList: HTMLInputElement; ++ }; ++}; ++ ++document.addEventListener("DOMContentLoaded", async () => { ++ // Improves browser compatibility ++ require("whatwg-fetch"); ++ ++ const drawAndUpdateUrl = async ( ++ diffUrl: string, ++ diffString: string, ++ config: Diff2HtmlUIConfig, ++ elements: Elements ++ ): Promise => { ++ updateBrowserUrl(config, diffUrl); ++ const newRequest = prepareRequest(diffUrl); ++ diffString = await getDiff(newRequest); ++ draw(diffString, config, elements); ++ }; ++ ++ const elements: Elements = { ++ structure: { ++ container: document.getElementsByClassName("container")[0] as HTMLElement, ++ diffTarget: document.getElementById("url-diff-container") as HTMLElement ++ }, ++ url: { ++ input: document.getElementById("url") as HTMLInputElement, ++ button: document.getElementById("url-btn") as HTMLElement ++ }, ++ options: { ++ outputFormat: document.getElementById("diff-url-options-output-format") as HTMLInputElement, ++ matching: document.getElementById("diff-url-options-matching") as HTMLInputElement, ++ wordsThreshold: document.getElementById("diff-url-options-match-words-threshold") as HTMLInputElement, ++ matchingMaxComparisons: document.getElementById("diff-url-options-matching-max-comparisons") as HTMLInputElement ++ }, ++ checkboxes: { ++ drawFileList: document.getElementById("diff-url-options-show-files") as HTMLInputElement ++ } ++ }; ++ ++ let [config, diffString] = await prepareInitialState(elements); ++ ++ // Update HTML inputs from any changes in URL ++ config.outputFormat && (elements.options.outputFormat.value = config.outputFormat); ++ config.drawFileList && (elements.checkboxes.drawFileList.checked = config.drawFileList); ++ config.matching && (elements.options.matching.value = config.matching); ++ config.matchWordsThreshold && (elements.options.wordsThreshold.value = config.matchWordsThreshold.toString()); ++ config.matchingMaxComparisons && ++ (elements.options.matchingMaxComparisons.value = config.matchingMaxComparisons.toString()); ++ ++ Object.entries(elements.options).forEach(([option, element]) => ++ element.addEventListener("change", () => { ++ config = { ...config, [option]: element.value }; ++ drawAndUpdateUrl(elements.url.input.value, diffString, config, elements); ++ }) ++ ); ++ ++ Object.entries(elements.checkboxes).forEach(([option, checkbox]) => ++ checkbox.addEventListener("change", () => { ++ config = { ...config, [option]: checkbox.checked }; ++ drawAndUpdateUrl(elements.url.input.value, diffString, config, elements); ++ }) ++ ); ++ ++ elements.url.button.addEventListener("click", async e => { ++ e.preventDefault(); ++ const newDiffUrl = elements.url.input.value; ++ const newRequest = prepareRequest(newDiffUrl); ++ diffString = await getDiff(newRequest); ++ drawAndUpdateUrl(newDiffUrl, diffString, config, elements); ++ }); ++ ++ return drawAndUpdateUrl(elements.url.input.value, diffString, config, elements); ++}); +diff --git a/website/templates/pages/index/content.handlebars b/website/templates/pages/index/content.handlebars +new file mode 100644 +index 00000000..04f44c62 +--- /dev/null ++++ b/website/templates/pages/index/content.handlebars +@@ -0,0 +1,295 @@ ++
    ++ ++ diff2html ++ ++

    Diff parser and pretty html generator

    ++

    Better diffs, unmatched reviews.

    ++

    Demo

    ++ ++
    ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
    ++
    ++ ++
    ++
    ++
    ++

    Each diff provides a comprehensive visualization of the code changes, ++ helping developers identify problems and better understand the changes.

    ++
    ++
    ++ ++
    ++
    ++ ++ ++ ++
    Line by Line and Side by Side changes
    ++

    Each diff features a line by line and side by side preview of your ++ changes.

    ++
    ++ ++
    ++ ++ ++ ++
    Code syntax highlight
    ++

    All the code changes are syntax highlighted using highlight.js, ++ providing more readability.

    ++
    ++ ++
    ++ ++ ++ ++
    Line similarity matching
    ++

    Similar lines are paired, allowing for easier change tracking.

    ++
    ++
    ++ ++
    ++
    ++
    ++
    ++

    Install with Bower

    ++

    You can install and manage diff2html's CSS and JS using Bower:

    ++
    ++

    > $ bower install ++ diff2html

    ++ Copy ++
    ++
    ++
    ++
    ++
    ++

    Install with npm

    ++

    You can also install diff2html using npm:

    ++
    ++

    > $ npm install ++ diff2html

    ++ Copy ++
    ++
    ++
    ++ ++
    ++
    ++ ++
    ++
    ++

    With command line integration

    ++

    We work hard to make sure you can have your diffs in a simple and flexible ++ way. Go here full ++ documentation.

    ++
    ++
    ++
    ++

    ++ > $ npm install -g ++ diff2html-cli
    ++ diff2html cli installed! ++

    ++

    ++ > $ diff2html
    ++ Previous commit changes on your browser ++

    ++

    ++ > $ is that it?
    ++ Yup, it's that simple.
    ++

    ++
    ++
    ++
    ++ ++
    ++
    ++
    ++
    ++

    Projects using diff2html

    ++
    ++
    ++
    ++
    ++
    ++
    ++
    diff2html-cli
    ++

    diff2html from your terminal to the browser.

    ++ ++ View GitHub ++ ++
    ++
    ++
    ++
    ++
    ++
    ++
    Codacy
    ++

    Check code style, security, duplication, complexity and coverage on every ++ change.

    ++ ++ Website ++ ++
    ++
    ++
    ++
    ++
    ++
    ++
    Ungit
    ++

    The easiest way to use git. On any platform. Anywhere.

    ++ ++ View GitHub ++ ++
    ++
    ++
    ++
    ++
    ++
    ++
    Diffy
    ++

    Share your diffs and explain your ideas without committing.

    ++ ++ Website ++ ++
    ++
    ++
    ++
    ++
    ++
    ++
    diff-pane
    ++

    Atom - Diff two panes.

    ++ ++ View GitHub ++ ++
    ++
    ++
    ++
    ++
    ++
    ++
    node-giff
    ++

    Display git diff on browser.

    ++ ++ View GitHub ++ ++
    ++
    ++
    ++
    ++
    ++
    ++
    edgar-monitor
    ++

    A module that processes new Edgar filings and sends out ++ notifications.

    ++ ++ View GitHub ++ ++
    ++
    ++
    ++
    ++
    ++
    ++
    node-git
    ++

    Execute Git Command by Node.js.

    ++ ++ View GitHub ++ ++
    ++
    ++
    ++
    ++
    ++
    ++
    Jenkins
    ++

    Show diffs between builds

    ++ ++ Website ++ ++
    ++
    ++
    ++
    ++
    ++
    ++
    Light Review
    ++

    Code Reviews with maximum control for the leading developers

    ++ ++ Website ++ ++
    ++
    ++
    ++
    ++
    ++
    ++
    Simple Git
    ++

    A simple package to be able to drive GIT

    ++ ++ View GitHub ++ ++
    ++
    ++
    ++
    ++
    ++
    ++ ++
    ++
    ++

    Open Source

    ++

    diff2html is open source. ++ If you'd like to be part of the diff2html community or help us improve, ++ find us on GitHub and ++ Gitter. Need any help? ++

    ++ ++ Read more in the Docs ++ ++
    ++
    ++ ++
    +\ No newline at end of file +diff --git a/docs/img/snapshot-1.png b/website/templates/pages/index/images/snapshot-1.png +similarity index 100% +rename from docs/img/snapshot-1.png +rename to website/templates/pages/index/images/snapshot-1.png +diff --git a/docs/img/snapshot-2.png b/website/templates/pages/index/images/snapshot-2.png +similarity index 100% +rename from docs/img/snapshot-2.png +rename to website/templates/pages/index/images/snapshot-2.png +diff --git a/docs/img/snapshot-3.png b/website/templates/pages/index/images/snapshot-3.png +similarity index 100% +rename from docs/img/snapshot-3.png +rename to website/templates/pages/index/images/snapshot-3.png +diff --git a/website/templates/pages/index/index-scripts.partial.mustache b/website/templates/pages/index/index-scripts.partial.mustache +deleted file mode 100644 +index 72675030..00000000 +--- a/website/templates/pages/index/index-scripts.partial.mustache ++++ /dev/null +@@ -1,5 +0,0 @@ +- +- +- +\ No newline at end of file +diff --git a/website/templates/pages/index/index.css b/website/templates/pages/index/index.css +new file mode 100644 +index 00000000..a8c64648 +--- /dev/null ++++ b/website/templates/pages/index/index.css +@@ -0,0 +1,111 @@ ++.screenshot { ++ display: block; ++ overflow: hidden; ++ } ++ ++ .screenshot > img { ++ width: 100% ++ } ++ ++ .screenshots-fan { ++ margin-top: 50px ++ } ++ ++ .screenshots-fan .screenshot { ++ position: relative; ++ width: auto; ++ display: inline-block; ++ text-align: center; ++ } ++ ++ .screenshots-fan .screenshot:last-child, .screenshots-fan .screenshot:first-child { ++ z-index: 2 ++ } ++ ++ .screenshots-fan .screenshot { ++ z-index: 3 ++ } ++ ++ @media (min-width: 768px) { ++ .screenshots-fan { ++ position: relative; ++ overflow: hidden; ++ margin-top: 60px; ++ height: 200px ++ } ++ ++ .screenshots-fan .screenshot { ++ height: auto; ++ top: 10px; ++ width: 350px ++ } ++ ++ .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { ++ width: 250px; ++ position: absolute; ++ top: 65px ++ } ++ ++ .screenshots-fan .screenshot:first-child { ++ left: 10px ++ } ++ ++ .screenshots-fan .screenshot:last-child { ++ left: auto; ++ right: 10px ++ } ++ } ++ ++ @media (min-width: 992px) { ++ .screenshots-fan { ++ margin-top: 60px; ++ height: 240px ++ } ++ ++ .screenshots-fan .screenshot { ++ width: 400px ++ } ++ ++ .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { ++ width: 300px ++ } ++ } ++ ++ @media (min-width: 1200px) { ++ .screenshots-fan { ++ margin-top: 80px; ++ height: 380px ++ } ++ ++ .screenshots-fan .screenshot { ++ width: 550px ++ } ++ ++ .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { ++ width: 450px ++ } ++ } ++ ++.img-snapshot1 { ++ background-image: url("./images/snapshot-1.png"); ++ background-repeat: no-repeat; ++ /* height: 50px; ++ width: 50px; */ ++ display: inline-block; ++} ++ ++.img-snapshot2 { ++ background-image: url("./images/snapshot-2.png"); ++ background-repeat: no-repeat; ++ /* height: 50px; ++ width: 50px; */ ++ display: inline-block; ++} ++ ++.img-snapshot3 { ++ background-image: url("./images/snapshot-3.png"); ++ background-repeat: no-repeat; ++ /* height: 50px; ++ width: 50px; */ ++ display: inline-block; ++} +diff --git a/website/templates/pages/index/index.handlebars b/website/templates/pages/index/index.handlebars +new file mode 100644 +index 00000000..0087900b +--- /dev/null ++++ b/website/templates/pages/index/index.handlebars +@@ -0,0 +1,4 @@ ++{{#partial "content"}} ++{{> content}} ++{{/partial}} ++{{> ../../template}} +\ No newline at end of file +diff --git a/website/templates/pages/index/index.partial.mustache b/website/templates/pages/index/index.partial.mustache +deleted file mode 100644 +index 42b77447..00000000 +--- a/website/templates/pages/index/index.partial.mustache ++++ /dev/null +@@ -1,286 +0,0 @@ +-
    +- +- diff2html +- +-

    Diff parser and pretty html generator

    +-

    Better diffs, unmatched reviews.

    +-

    Demo

    +- +-
    +- +- +- +- +- +- +- +- +- +-
    +-
    +- +-
    +-
    +-
    +-

    Each diff provides a comprehensive visualization of the code changes, +- helping developers identify problems and better understand the changes.

    +-
    +-
    +- +-
    +-
    +- +- +- +-
    Line by Line and Side by Side changes
    +-

    Each diff features a line by line and side by side preview of your +- changes.

    +-
    +- +-
    +- +- +- +-
    Code syntax highlight
    +-

    All the code changes are syntax highlighted using highlight.js, +- providing more readability.

    +-
    +- +-
    +- +- +- +-
    Line similarity matching
    +-

    Similar lines are paired, allowing for easier change tracking.

    +-
    +-
    +- +-
    +-
    +-
    +-
    +-

    Install with Bower

    +-

    You can install and manage diff2html's CSS and JS using Bower:

    +-
    +-

    > $ bower install diff2html

    +- Copy +-
    +-
    +-
    +-
    +-
    +-

    Install with npm

    +-

    You can also install diff2html using npm:

    +-
    +-

    > $ npm install diff2html

    +- Copy +-
    +-
    +-
    +- +-
    +-
    +- +-
    +-
    +-

    With command line integration

    +-

    We work hard to make sure you can have your diffs in a simple and flexible +- way. Go here full +- documentation.

    +-
    +-
    +-
    +-

    +- > $ npm install -g diff2html-cli
    +- diff2html cli installed! +-

    +-

    +- > $ diff2html
    +- Previous commit changes on your browser +-

    +-

    +- > $ is that it?
    +- Yup, it's that simple.
    +-

    +-
    +-
    +-
    +- +-
    +-
    +-
    +-
    +-

    Projects using diff2html

    +-
    +-
    +-
    +-
    +-
    +-
    +-
    diff2html-cli
    +-

    diff2html from your terminal to the browser.

    +- +- View GitHub +- +-
    +-
    +-
    +-
    +-
    +-
    +-
    Codacy
    +-

    Check code style, security, duplication, complexity and coverage on every change.

    +- +- Website +- +-
    +-
    +-
    +-
    +-
    +-
    +-
    Ungit
    +-

    The easiest way to use git. On any platform. Anywhere.

    +- +- View GitHub +- +-
    +-
    +-
    +-
    +-
    +-
    +-
    Diffy
    +-

    Share your diffs and explain your ideas without committing.

    +- +- Website +- +-
    +-
    +-
    +-
    +-
    +-
    +-
    diff-pane
    +-

    Atom - Diff two panes.

    +- +- View GitHub +- +-
    +-
    +-
    +-
    +-
    +-
    +-
    node-giff
    +-

    Display git diff on browser.

    +- +- View GitHub +- +-
    +-
    +-
    +-
    +-
    +-
    +-
    edgar-monitor
    +-

    A module that processes new Edgar filings and sends out +- notifications.

    +- +- View GitHub +- +-
    +-
    +-
    +-
    +-
    +-
    +-
    node-git
    +-

    Execute Git Command by Node.js.

    +- +- View GitHub +- +-
    +-
    +-
    +-
    +-
    +-
    +-
    Jenkins
    +-

    Show diffs between builds

    +- +- Website +- +-
    +-
    +-
    +-
    +-
    +-
    +-
    Light Review
    +-

    Code Reviews with maximum control for the leading developers

    +- +- Website +- +-
    +-
    +-
    +-
    +-
    +-
    +-
    Simple Git
    +-

    A simple package to be able to drive GIT

    +- +- View GitHub +- +-
    +-
    +-
    +-
    +-
    +-
    +- +-
    +-
    +-

    Open Source

    +-

    diff2html is open source. +- If you'd like to be part of the diff2html community or help us improve, +- find us on GitHub and +- Gitter. Need any help? +-

    +- +- Read more in the Docs +- +-
    +-
    +- +-
    +diff --git a/website/templates/pages/index/index.ts b/website/templates/pages/index/index.ts +new file mode 100644 +index 00000000..fbdc699a +--- /dev/null ++++ b/website/templates/pages/index/index.ts +@@ -0,0 +1,8 @@ ++import Clipboard from "clipboard"; ++ ++import "../../../main.ts"; ++import "../../../main.css"; ++import "./index.css"; ++ ++// eslint-disable-next-line no-new ++new Clipboard(document.getElementsByClassName("btn-clipboard")[0]); +diff --git a/website/templates/template.handlebars b/website/templates/template.handlebars +new file mode 100644 +index 00000000..883b1ccd +--- /dev/null ++++ b/website/templates/template.handlebars +@@ -0,0 +1,132 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ diff2html ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
    ++ ++
    ++ ++ ++ {{#block "content"}}{{/block}} ++
    ++ ++
    ++

    ++ Website originally designed and built by ++ @mdo, ++ @fat, and ++ @dhg, ++ adapted with by ++ @rtfpessoa. ++

    ++ ++
    ++ ++
    ++ ++ ++ ++ ++ ++ ++ +\ No newline at end of file +diff --git a/website/templates/template.mustache b/website/templates/template.mustache +deleted file mode 100644 +index 4052c643..00000000 +--- a/website/templates/template.mustache ++++ /dev/null +@@ -1,149 +0,0 @@ +- +- +- +- +- +- +- +- +- +- +- +- diff2html +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-{{#assets}} +-{{{assets}}} +- +-{{/assets}} +- +- +- +-
    +- +-
    +- +- +-{{{content}}} +- +-
    +- +-
    +-

    +- Website originally designed and built by +- @mdo, +- @fat, and +- @dhg, +- adapted with by +- @rtfpessoa. +-

    +- +-
    +- +-
    +- +- +- +- +- +- +- +-{{#scripts}} +-{{{scripts}}} +- +-{{/scripts}} +- +- +diff --git a/yarn.lock b/yarn.lock +index 0f6e710a..fff852ac 100644 +--- a/yarn.lock ++++ b/yarn.lock +@@ -2,13 +2,80 @@ + # yarn lockfile v1 + + +-"@babel/code-frame@^7.0.0": +- version "7.0.0" +- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" +- integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== ++"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": ++ version "7.5.5" ++ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" ++ integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + ++"@babel/core@^7.1.0": ++ version "7.7.4" ++ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.4.tgz#37e864532200cb6b50ee9a4045f5f817840166ab" ++ integrity sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ== ++ dependencies: ++ "@babel/code-frame" "^7.5.5" ++ "@babel/generator" "^7.7.4" ++ "@babel/helpers" "^7.7.4" ++ "@babel/parser" "^7.7.4" ++ "@babel/template" "^7.7.4" ++ "@babel/traverse" "^7.7.4" ++ "@babel/types" "^7.7.4" ++ convert-source-map "^1.7.0" ++ debug "^4.1.0" ++ json5 "^2.1.0" ++ lodash "^4.17.13" ++ resolve "^1.3.2" ++ semver "^5.4.1" ++ source-map "^0.5.0" ++ ++"@babel/generator@^7.4.0", "@babel/generator@^7.7.4": ++ version "7.7.4" ++ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369" ++ integrity sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg== ++ dependencies: ++ "@babel/types" "^7.7.4" ++ jsesc "^2.5.1" ++ lodash "^4.17.13" ++ source-map "^0.5.0" ++ ++"@babel/helper-function-name@^7.7.4": ++ version "7.7.4" ++ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" ++ integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ== ++ dependencies: ++ "@babel/helper-get-function-arity" "^7.7.4" ++ "@babel/template" "^7.7.4" ++ "@babel/types" "^7.7.4" ++ ++"@babel/helper-get-function-arity@^7.7.4": ++ version "7.7.4" ++ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" ++ integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA== ++ dependencies: ++ "@babel/types" "^7.7.4" ++ ++"@babel/helper-plugin-utils@^7.0.0": ++ version "7.0.0" ++ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" ++ integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== ++ ++"@babel/helper-split-export-declaration@^7.7.4": ++ version "7.7.4" ++ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" ++ integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug== ++ dependencies: ++ "@babel/types" "^7.7.4" ++ ++"@babel/helpers@^7.7.4": ++ version "7.7.4" ++ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302" ++ integrity sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg== ++ dependencies: ++ "@babel/template" "^7.7.4" ++ "@babel/traverse" "^7.7.4" ++ "@babel/types" "^7.7.4" ++ + "@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" +@@ -18,6 +85,217 @@ + esutils "^2.0.2" + js-tokens "^4.0.0" + ++"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.4": ++ version "7.7.4" ++ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.4.tgz#75ab2d7110c2cf2fa949959afb05fa346d2231bb" ++ integrity sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g== ++ ++"@babel/plugin-syntax-object-rest-spread@^7.0.0": ++ version "7.7.4" ++ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46" ++ integrity sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg== ++ dependencies: ++ "@babel/helper-plugin-utils" "^7.0.0" ++ ++"@babel/template@^7.4.0", "@babel/template@^7.7.4": ++ version "7.7.4" ++ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" ++ integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw== ++ dependencies: ++ "@babel/code-frame" "^7.0.0" ++ "@babel/parser" "^7.7.4" ++ "@babel/types" "^7.7.4" ++ ++"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.4": ++ version "7.7.4" ++ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" ++ integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== ++ dependencies: ++ "@babel/code-frame" "^7.5.5" ++ "@babel/generator" "^7.7.4" ++ "@babel/helper-function-name" "^7.7.4" ++ "@babel/helper-split-export-declaration" "^7.7.4" ++ "@babel/parser" "^7.7.4" ++ "@babel/types" "^7.7.4" ++ debug "^4.1.0" ++ globals "^11.1.0" ++ lodash "^4.17.13" ++ ++"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.7.4": ++ version "7.7.4" ++ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" ++ integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== ++ dependencies: ++ esutils "^2.0.2" ++ lodash "^4.17.13" ++ to-fast-properties "^2.0.0" ++ ++"@cnakazawa/watch@^1.0.3": ++ version "1.0.3" ++ resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" ++ integrity sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA== ++ dependencies: ++ exec-sh "^0.3.2" ++ minimist "^1.2.0" ++ ++"@csstools/convert-colors@^1.4.0": ++ version "1.4.0" ++ resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" ++ integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== ++ ++"@csstools/normalize.css@^10.1.0": ++ version "10.1.0" ++ resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-10.1.0.tgz#f0950bba18819512d42f7197e56c518aa491cf18" ++ integrity sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg== ++ ++"@jest/console@^24.7.1", "@jest/console@^24.9.0": ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" ++ integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ== ++ dependencies: ++ "@jest/source-map" "^24.9.0" ++ chalk "^2.0.1" ++ slash "^2.0.0" ++ ++"@jest/core@^24.9.0": ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.9.0.tgz#2ceccd0b93181f9c4850e74f2a9ad43d351369c4" ++ integrity sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A== ++ dependencies: ++ "@jest/console" "^24.7.1" ++ "@jest/reporters" "^24.9.0" ++ "@jest/test-result" "^24.9.0" ++ "@jest/transform" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ ansi-escapes "^3.0.0" ++ chalk "^2.0.1" ++ exit "^0.1.2" ++ graceful-fs "^4.1.15" ++ jest-changed-files "^24.9.0" ++ jest-config "^24.9.0" ++ jest-haste-map "^24.9.0" ++ jest-message-util "^24.9.0" ++ jest-regex-util "^24.3.0" ++ jest-resolve "^24.9.0" ++ jest-resolve-dependencies "^24.9.0" ++ jest-runner "^24.9.0" ++ jest-runtime "^24.9.0" ++ jest-snapshot "^24.9.0" ++ jest-util "^24.9.0" ++ jest-validate "^24.9.0" ++ jest-watcher "^24.9.0" ++ micromatch "^3.1.10" ++ p-each-series "^1.0.0" ++ realpath-native "^1.1.0" ++ rimraf "^2.5.4" ++ slash "^2.0.0" ++ strip-ansi "^5.0.0" ++ ++"@jest/environment@^24.9.0": ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.9.0.tgz#21e3afa2d65c0586cbd6cbefe208bafade44ab18" ++ integrity sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ== ++ dependencies: ++ "@jest/fake-timers" "^24.9.0" ++ "@jest/transform" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ jest-mock "^24.9.0" ++ ++"@jest/fake-timers@^24.9.0": ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.9.0.tgz#ba3e6bf0eecd09a636049896434d306636540c93" ++ integrity sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A== ++ dependencies: ++ "@jest/types" "^24.9.0" ++ jest-message-util "^24.9.0" ++ jest-mock "^24.9.0" ++ ++"@jest/reporters@^24.9.0": ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.9.0.tgz#86660eff8e2b9661d042a8e98a028b8d631a5b43" ++ integrity sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw== ++ dependencies: ++ "@jest/environment" "^24.9.0" ++ "@jest/test-result" "^24.9.0" ++ "@jest/transform" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ chalk "^2.0.1" ++ exit "^0.1.2" ++ glob "^7.1.2" ++ istanbul-lib-coverage "^2.0.2" ++ istanbul-lib-instrument "^3.0.1" ++ istanbul-lib-report "^2.0.4" ++ istanbul-lib-source-maps "^3.0.1" ++ istanbul-reports "^2.2.6" ++ jest-haste-map "^24.9.0" ++ jest-resolve "^24.9.0" ++ jest-runtime "^24.9.0" ++ jest-util "^24.9.0" ++ jest-worker "^24.6.0" ++ node-notifier "^5.4.2" ++ slash "^2.0.0" ++ source-map "^0.6.0" ++ string-length "^2.0.0" ++ ++"@jest/source-map@^24.3.0", "@jest/source-map@^24.9.0": ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714" ++ integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg== ++ dependencies: ++ callsites "^3.0.0" ++ graceful-fs "^4.1.15" ++ source-map "^0.6.0" ++ ++"@jest/test-result@^24.9.0": ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca" ++ integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA== ++ dependencies: ++ "@jest/console" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ "@types/istanbul-lib-coverage" "^2.0.0" ++ ++"@jest/test-sequencer@^24.9.0": ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz#f8f334f35b625a4f2f355f2fe7e6036dad2e6b31" ++ integrity sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A== ++ dependencies: ++ "@jest/test-result" "^24.9.0" ++ jest-haste-map "^24.9.0" ++ jest-runner "^24.9.0" ++ jest-runtime "^24.9.0" ++ ++"@jest/transform@^24.9.0": ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.9.0.tgz#4ae2768b296553fadab09e9ec119543c90b16c56" ++ integrity sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ== ++ dependencies: ++ "@babel/core" "^7.1.0" ++ "@jest/types" "^24.9.0" ++ babel-plugin-istanbul "^5.1.0" ++ chalk "^2.0.1" ++ convert-source-map "^1.4.0" ++ fast-json-stable-stringify "^2.0.0" ++ graceful-fs "^4.1.15" ++ jest-haste-map "^24.9.0" ++ jest-regex-util "^24.9.0" ++ jest-util "^24.9.0" ++ micromatch "^3.1.10" ++ pirates "^4.0.1" ++ realpath-native "^1.1.0" ++ slash "^2.0.0" ++ source-map "^0.6.1" ++ write-file-atomic "2.4.1" ++ ++"@jest/types@^24.9.0": ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59" ++ integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw== ++ dependencies: ++ "@types/istanbul-lib-coverage" "^2.0.0" ++ "@types/istanbul-reports" "^1.1.1" ++ "@types/yargs" "^13.0.0" ++ + "@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" +@@ -26,11 +304,119 @@ + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + ++"@nodelib/fs.scandir@2.1.3": ++ version "2.1.3" ++ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" ++ integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== ++ dependencies: ++ "@nodelib/fs.stat" "2.0.3" ++ run-parallel "^1.1.9" ++ ++"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": ++ version "2.0.3" ++ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" ++ integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== ++ + "@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + ++"@nodelib/fs.walk@^1.2.3": ++ version "1.2.4" ++ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" ++ integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== ++ dependencies: ++ "@nodelib/fs.scandir" "2.1.3" ++ fastq "^1.6.0" ++ ++"@sindresorhus/is@^0.7.0": ++ version "0.7.0" ++ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" ++ integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== ++ ++"@types/anymatch@*": ++ version "1.3.1" ++ resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" ++ integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== ++ ++"@types/autoprefixer@9.6.1": ++ version "9.6.1" ++ resolved "https://registry.yarnpkg.com/@types/autoprefixer/-/autoprefixer-9.6.1.tgz#8bfaf43d18f5cd59a269b7a2364e690cadcdf210" ++ integrity sha512-9aofAxm/OWxzu/Fq7lU/m2rX03f9Sr1OXF/3kEp6FNFYRFLgFcIUjxhNGgWqc5KMpXbkqxlJmc7wfab7jFj2dw== ++ dependencies: ++ "@types/browserslist" "*" ++ postcss "7.x.x" ++ ++"@types/babel__core@^7.1.0": ++ version "7.1.3" ++ resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30" ++ integrity sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA== ++ dependencies: ++ "@babel/parser" "^7.1.0" ++ "@babel/types" "^7.0.0" ++ "@types/babel__generator" "*" ++ "@types/babel__template" "*" ++ "@types/babel__traverse" "*" ++ ++"@types/babel__generator@*": ++ version "7.6.0" ++ resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.0.tgz#f1ec1c104d1bb463556ecb724018ab788d0c172a" ++ integrity sha512-c1mZUu4up5cp9KROs/QAw0gTeHrw/x7m52LcnvMxxOZ03DmLwPV0MlGmlgzV3cnSdjhJOZsj7E7FHeioai+egw== ++ dependencies: ++ "@babel/types" "^7.0.0" ++ ++"@types/babel__template@*": ++ version "7.0.2" ++ resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" ++ integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== ++ dependencies: ++ "@babel/parser" "^7.1.0" ++ "@babel/types" "^7.0.0" ++ ++"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": ++ version "7.0.8" ++ resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.8.tgz#479a4ee3e291a403a1096106013ec22cf9b64012" ++ integrity sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw== ++ dependencies: ++ "@babel/types" "^7.3.0" ++ ++"@types/browserslist@*": ++ version "4.4.0" ++ resolved "https://registry.yarnpkg.com/@types/browserslist/-/browserslist-4.4.0.tgz#e2a5f7f8c7e97afb39f50812a77e5230d3ca2353" ++ integrity sha512-hrIjWSu7Hh96/rKlpChe58qHEwIZ0+F5Zf4QNdvSVP5LUXbaJM04g9tBjo702VTNqPZr5znEJeqNR3nAV3vJPg== ++ ++"@types/clean-css@*": ++ version "4.2.1" ++ resolved "https://registry.yarnpkg.com/@types/clean-css/-/clean-css-4.2.1.tgz#cb0134241ec5e6ede1b5344bc829668fd9871a8d" ++ integrity sha512-A1HQhQ0hkvqqByJMgg+Wiv9p9XdoYEzuwm11SVo1mX2/4PSdhjcrUlilJQoqLscIheC51t1D5g+EFWCXZ2VTQQ== ++ dependencies: ++ "@types/node" "*" ++ ++"@types/clipboard@2.0.1": ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/@types/clipboard/-/clipboard-2.0.1.tgz#75a74086c293d75b12bc93ff13bc7797fef05a40" ++ integrity sha512-gJJX9Jjdt3bIAePQRRjYWG20dIhAgEqonguyHxXuqALxsoDsDLimihqrSg8fXgVTJ4KZCzkfglKtwsh/8dLfbA== ++ ++"@types/copy-webpack-plugin@5.0.0": ++ version "5.0.0" ++ resolved "https://registry.yarnpkg.com/@types/copy-webpack-plugin/-/copy-webpack-plugin-5.0.0.tgz#db7f9c9763b10b2af5c83f598fa9b5a13733b20b" ++ integrity sha512-yQHocgdgES7W5Q2UyxJ5cj/E6MrV1zq3MZ8jdApS9NJKqax+rux9IE3QAbBmNCGbgivEsejrkIq3Rm76JLubkg== ++ dependencies: ++ "@types/minimatch" "*" ++ "@types/node" "*" ++ "@types/webpack" "*" ++ ++"@types/diff@4.0.2": ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/@types/diff/-/diff-4.0.2.tgz#2e9bb89f9acc3ab0108f0f3dc4dbdcf2fff8a99c" ++ integrity sha512-mIenTfsIe586/yzsyfql69KRnA75S8SVXQbTLpDejRrjH0QSJcpu3AUOi/Vjnt9IOsXKxPhJfGpQUNMueIU1fQ== ++ ++"@types/eslint-visitor-keys@^1.0.0": ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" ++ integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== ++ + "@types/events@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" +@@ -45,84 +431,457 @@ + "@types/minimatch" "*" + "@types/node" "*" + ++"@types/highlight.js@9.12.3": ++ version "9.12.3" ++ resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.3.tgz#b672cfaac25cbbc634a0fd92c515f66faa18dbca" ++ integrity sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ== ++ ++"@types/hogan.js@3.0.0": ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/@types/hogan.js/-/hogan.js-3.0.0.tgz#bf26560f39a38224ab6d0491b06f72c8fbe0953d" ++ integrity sha512-djkvb/AN43c3lIGCojNQ1FBS9VqqKhcTns5RQnHw4xBT/csy0jAssAsOiJ8NfaaioZaeKYE7XkVRxE5NeSZcaA== ++ ++"@types/html-minifier@*": ++ version "3.5.3" ++ resolved "https://registry.yarnpkg.com/@types/html-minifier/-/html-minifier-3.5.3.tgz#5276845138db2cebc54c789e0aaf87621a21e84f" ++ integrity sha512-j1P/4PcWVVCPEy5lofcHnQ6BtXz9tHGiFPWzqm7TtGuWZEfCHEP446HlkSNc9fQgNJaJZ6ewPtp2aaFla/Uerg== ++ dependencies: ++ "@types/clean-css" "*" ++ "@types/relateurl" "*" ++ "@types/uglify-js" "*" ++ ++"@types/html-webpack-plugin@3.2.1": ++ version "3.2.1" ++ resolved "https://registry.yarnpkg.com/@types/html-webpack-plugin/-/html-webpack-plugin-3.2.1.tgz#d3401407261ec82cb0fc380df28e57c94e851e4d" ++ integrity sha512-H8Pj1/Urx6qlUednZpNsveDVUsO63gQdu5DLaAf9t7iG0iyK0OS4XKFG5v1PSG1Nek9S65BrPrKt8DfEib02ng== ++ dependencies: ++ "@types/html-minifier" "*" ++ "@types/tapable" "*" ++ "@types/webpack" "*" ++ ++"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" ++ integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg== ++ ++"@types/istanbul-lib-report@*": ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c" ++ integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg== ++ dependencies: ++ "@types/istanbul-lib-coverage" "*" ++ ++"@types/istanbul-reports@^1.1.1": ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a" ++ integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA== ++ dependencies: ++ "@types/istanbul-lib-coverage" "*" ++ "@types/istanbul-lib-report" "*" ++ ++"@types/jest@24.0.23": ++ version "24.0.23" ++ resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.23.tgz#046f8e2ade026fe831623e361a36b6fb9a4463e4" ++ integrity sha512-L7MBvwfNpe7yVPTXLn32df/EK+AMBFAFvZrRuArGs7npEWnlziUXK+5GMIUTI4NIuwok3XibsjXCs5HxviYXjg== ++ dependencies: ++ jest-diff "^24.3.0" ++ ++"@types/json-schema@^7.0.3": ++ version "7.0.3" ++ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" ++ integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== ++ ++"@types/mini-css-extract-plugin@0.8.0": ++ version "0.8.0" ++ resolved "https://registry.yarnpkg.com/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz#6a5d3459d40cb51f14059e9aa410c9e970656103" ++ integrity sha512-L7OKmXudo048RMw/NeLjJMNRAbyXG76b3uGZ49OKe03imYEplx0JzcM0goVNc7X1IeESf2Bk9RP+tS1U3OSmVg== ++ dependencies: ++ "@types/webpack" "*" ++ + "@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + +-"@types/node@*": +- version "12.6.2" +- resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.2.tgz#a5ccec6abb6060d5f20d256fb03ed743e9774999" +- integrity sha512-gojym4tX0FWeV2gsW4Xmzo5wxGjXGm550oVUII7f7G5o4BV6c7DBdiG1RRQd+y1bvqRyYtPfMK85UM95vsapqQ== ++"@types/mkdirp@0.5.2": ++ version "0.5.2" ++ resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" ++ integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== ++ dependencies: ++ "@types/node" "*" ++ ++"@types/node@*", "@types/node@12.12.12": ++ version "12.12.12" ++ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.12.tgz#529bc3e73dbb35dd9e90b0a1c83606a9d3264bdb" ++ integrity sha512-MGuvYJrPU0HUwqF7LqvIj50RZUX23Z+m583KBygKYUZLlZ88n6w28XRNJRJgsHukLEnLz6w6SvxZoLgbr5wLqQ== + +-JSONStream@^1.0.3: +- version "1.3.5" +- resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" +- integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== ++"@types/nopt@3.0.29": ++ version "3.0.29" ++ resolved "https://registry.yarnpkg.com/@types/nopt/-/nopt-3.0.29.tgz#f19df3db4c97ee1459a2740028320a71d70964ce" ++ integrity sha1-8Z3z20yX7hRZonQAKDIKcdcJZM4= ++ ++"@types/q@^1.5.1": ++ version "1.5.2" ++ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" ++ integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== ++ ++"@types/relateurl@*": ++ version "0.2.28" ++ resolved "https://registry.yarnpkg.com/@types/relateurl/-/relateurl-0.2.28.tgz#6bda7db8653fa62643f5ee69e9f69c11a392e3a6" ++ integrity sha1-a9p9uGU/piZD9e5p6facEaOS46Y= ++ ++"@types/source-list-map@*": ++ version "0.1.2" ++ resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" ++ integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== ++ ++"@types/stack-utils@^1.0.1": ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" ++ integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== ++ ++"@types/tapable@*": ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.4.tgz#b4ffc7dc97b498c969b360a41eee247f82616370" ++ integrity sha512-78AdXtlhpCHT0K3EytMpn4JNxaf5tbqbLcbIRoQIHzpTIyjpxLQKRoxU55ujBXAtg3Nl2h/XWvfDa9dsMOd0pQ== ++ ++"@types/uglify-js@*": ++ version "3.0.4" ++ resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.4.tgz#96beae23df6f561862a830b4288a49e86baac082" ++ integrity sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ== ++ dependencies: ++ source-map "^0.6.1" ++ ++"@types/webpack-sources@*": ++ version "0.1.5" ++ resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.5.tgz#be47c10f783d3d6efe1471ff7f042611bd464a92" ++ integrity sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w== ++ dependencies: ++ "@types/node" "*" ++ "@types/source-list-map" "*" ++ source-map "^0.6.1" ++ ++"@types/webpack@*", "@types/webpack@4.41.0": ++ version "4.41.0" ++ resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.0.tgz#b813a044d8b0dec7dfcd7622fdbe327bde06eb9a" ++ integrity sha512-tWkdf9nO0zFgAY/EumUKwrDUhraHKDqCPhwfFR/R8l0qnPdgb9le0Gzhvb7uzVpouuDGBgiE//ZdY+5jcZy2TA== + dependencies: +- jsonparse "^1.2.0" +- through ">=2.2.7 <3" ++ "@types/anymatch" "*" ++ "@types/node" "*" ++ "@types/tapable" "*" ++ "@types/uglify-js" "*" ++ "@types/webpack-sources" "*" ++ source-map "^0.6.0" ++ ++"@types/yargs-parser@*": ++ version "13.1.0" ++ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.1.0.tgz#c563aa192f39350a1d18da36c5a8da382bbd8228" ++ integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg== ++ ++"@types/yargs@^13.0.0": ++ version "13.0.3" ++ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.3.tgz#76482af3981d4412d65371a318f992d33464a380" ++ integrity sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ== ++ dependencies: ++ "@types/yargs-parser" "*" ++ ++"@typescript-eslint/eslint-plugin@2.8.0": ++ version "2.8.0" ++ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.8.0.tgz#eca584d46094ebebc3cb3e9fb625bfbc904a534d" ++ integrity sha512-ohqul5s6XEB0AzPWZCuJF5Fd6qC0b4+l5BGEnrlpmvXxvyymb8yw8Bs4YMF8usNAeuCJK87eFIHy8g8GFvOtGA== ++ dependencies: ++ "@typescript-eslint/experimental-utils" "2.8.0" ++ eslint-utils "^1.4.3" ++ functional-red-black-tree "^1.0.1" ++ regexpp "^3.0.0" ++ tsutils "^3.17.1" ++ ++"@typescript-eslint/experimental-utils@2.8.0", "@typescript-eslint/experimental-utils@^2.5.0": ++ version "2.8.0" ++ resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.8.0.tgz#208b4164d175587e9b03ce6fea97d55f19c30ca9" ++ integrity sha512-jZ05E4SxCbbXseQGXOKf3ESKcsGxT8Ucpkp1jiVp55MGhOvZB2twmWKf894PAuVQTCgbPbJz9ZbRDqtUWzP8xA== ++ dependencies: ++ "@types/json-schema" "^7.0.3" ++ "@typescript-eslint/typescript-estree" "2.8.0" ++ eslint-scope "^5.0.0" ++ ++"@typescript-eslint/parser@2.8.0": ++ version "2.8.0" ++ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.8.0.tgz#e10f7c40c8cf2fb19920c879311e6c46ad17bacb" ++ integrity sha512-NseXWzhkucq+JM2HgqAAoKEzGQMb5LuTRjFPLQzGIdLthXMNUfuiskbl7QSykvWW6mvzCtYbw1fYWGa2EIaekw== ++ dependencies: ++ "@types/eslint-visitor-keys" "^1.0.0" ++ "@typescript-eslint/experimental-utils" "2.8.0" ++ "@typescript-eslint/typescript-estree" "2.8.0" ++ eslint-visitor-keys "^1.1.0" ++ ++"@typescript-eslint/typescript-estree@2.8.0": ++ version "2.8.0" ++ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.8.0.tgz#fcc3fe6532840085d29b75432c8a59895876aeca" ++ integrity sha512-ksvjBDTdbAQ04cR5JyFSDX113k66FxH1tAXmi+dj6hufsl/G0eMc/f1GgLjEVPkYClDbRKv+rnBFuE5EusomUw== ++ dependencies: ++ debug "^4.1.1" ++ eslint-visitor-keys "^1.1.0" ++ glob "^7.1.6" ++ is-glob "^4.0.1" ++ lodash.unescape "4.0.1" ++ semver "^6.3.0" ++ tsutils "^3.17.1" ++ ++"@webassemblyjs/ast@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" ++ integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== ++ dependencies: ++ "@webassemblyjs/helper-module-context" "1.8.5" ++ "@webassemblyjs/helper-wasm-bytecode" "1.8.5" ++ "@webassemblyjs/wast-parser" "1.8.5" ++ ++"@webassemblyjs/floating-point-hex-parser@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" ++ integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== ++ ++"@webassemblyjs/helper-api-error@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" ++ integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== ++ ++"@webassemblyjs/helper-buffer@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" ++ integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== ++ ++"@webassemblyjs/helper-code-frame@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" ++ integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== ++ dependencies: ++ "@webassemblyjs/wast-printer" "1.8.5" ++ ++"@webassemblyjs/helper-fsm@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" ++ integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== ++ ++"@webassemblyjs/helper-module-context@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" ++ integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== ++ dependencies: ++ "@webassemblyjs/ast" "1.8.5" ++ mamacro "^0.0.3" ++ ++"@webassemblyjs/helper-wasm-bytecode@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" ++ integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== ++ ++"@webassemblyjs/helper-wasm-section@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" ++ integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== ++ dependencies: ++ "@webassemblyjs/ast" "1.8.5" ++ "@webassemblyjs/helper-buffer" "1.8.5" ++ "@webassemblyjs/helper-wasm-bytecode" "1.8.5" ++ "@webassemblyjs/wasm-gen" "1.8.5" ++ ++"@webassemblyjs/ieee754@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" ++ integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== ++ dependencies: ++ "@xtuc/ieee754" "^1.2.0" ++ ++"@webassemblyjs/leb128@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" ++ integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== ++ dependencies: ++ "@xtuc/long" "4.2.2" ++ ++"@webassemblyjs/utf8@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" ++ integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== ++ ++"@webassemblyjs/wasm-edit@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" ++ integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== ++ dependencies: ++ "@webassemblyjs/ast" "1.8.5" ++ "@webassemblyjs/helper-buffer" "1.8.5" ++ "@webassemblyjs/helper-wasm-bytecode" "1.8.5" ++ "@webassemblyjs/helper-wasm-section" "1.8.5" ++ "@webassemblyjs/wasm-gen" "1.8.5" ++ "@webassemblyjs/wasm-opt" "1.8.5" ++ "@webassemblyjs/wasm-parser" "1.8.5" ++ "@webassemblyjs/wast-printer" "1.8.5" ++ ++"@webassemblyjs/wasm-gen@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" ++ integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== ++ dependencies: ++ "@webassemblyjs/ast" "1.8.5" ++ "@webassemblyjs/helper-wasm-bytecode" "1.8.5" ++ "@webassemblyjs/ieee754" "1.8.5" ++ "@webassemblyjs/leb128" "1.8.5" ++ "@webassemblyjs/utf8" "1.8.5" ++ ++"@webassemblyjs/wasm-opt@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" ++ integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== ++ dependencies: ++ "@webassemblyjs/ast" "1.8.5" ++ "@webassemblyjs/helper-buffer" "1.8.5" ++ "@webassemblyjs/wasm-gen" "1.8.5" ++ "@webassemblyjs/wasm-parser" "1.8.5" ++ ++"@webassemblyjs/wasm-parser@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" ++ integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== ++ dependencies: ++ "@webassemblyjs/ast" "1.8.5" ++ "@webassemblyjs/helper-api-error" "1.8.5" ++ "@webassemblyjs/helper-wasm-bytecode" "1.8.5" ++ "@webassemblyjs/ieee754" "1.8.5" ++ "@webassemblyjs/leb128" "1.8.5" ++ "@webassemblyjs/utf8" "1.8.5" ++ ++"@webassemblyjs/wast-parser@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" ++ integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== ++ dependencies: ++ "@webassemblyjs/ast" "1.8.5" ++ "@webassemblyjs/floating-point-hex-parser" "1.8.5" ++ "@webassemblyjs/helper-api-error" "1.8.5" ++ "@webassemblyjs/helper-code-frame" "1.8.5" ++ "@webassemblyjs/helper-fsm" "1.8.5" ++ "@xtuc/long" "4.2.2" ++ ++"@webassemblyjs/wast-printer@1.8.5": ++ version "1.8.5" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" ++ integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== ++ dependencies: ++ "@webassemblyjs/ast" "1.8.5" ++ "@webassemblyjs/wast-parser" "1.8.5" ++ "@xtuc/long" "4.2.2" ++ ++"@xtuc/ieee754@^1.2.0": ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" ++ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== ++ ++"@xtuc/long@4.2.2": ++ version "4.2.2" ++ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" ++ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== ++ ++abab@^2.0.0: ++ version "2.0.3" ++ resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" ++ integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== + + abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +-abbrev@1.0.x: +- version "1.0.9" +- resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" +- integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= +- +-acorn-dynamic-import@^4.0.0: +- version "4.0.0" +- resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" +- integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== +- +-acorn-jsx@^5.0.0: +- version "5.0.1" +- resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" +- integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== ++accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: ++ version "1.3.7" ++ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" ++ integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== ++ dependencies: ++ mime-types "~2.1.24" ++ negotiator "0.6.2" + +-acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2, acorn-node@^1.6.1: +- version "1.7.0" +- resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.7.0.tgz#aac6a559d27af6176b076ab6fb13c5974c213e3b" +- integrity sha512-XhahLSsCB6X6CJbe+uNu3Mn9sJBNFxtBN9NLgAOQovfS6Kh0lDUtmlclhjn9CvEK7A7YyRU13PXlNcpSiLI9Yw== ++acorn-globals@^4.1.0: ++ version "4.3.4" ++ resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" ++ integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== + dependencies: +- acorn "^6.1.1" +- acorn-dynamic-import "^4.0.0" +- acorn-walk "^6.1.1" +- xtend "^4.0.1" ++ acorn "^6.0.1" ++ acorn-walk "^6.0.1" + +-acorn-walk@^6.1.1: ++acorn-jsx@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" ++ integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== ++ ++acorn-walk@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" + integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== + +-acorn@^6.0.7, acorn@^6.1.1: +- version "6.2.0" +- resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.0.tgz#67f0da2fc339d6cfb5d6fb244fd449f33cd8bbe3" +- integrity sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw== ++acorn@^5.5.3: ++ version "5.7.3" ++ resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" ++ integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== ++ ++acorn@^6.0.1, acorn@^6.2.1: ++ version "6.3.0" ++ resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" ++ integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== + +-ajv@^6.5.5, ajv@^6.9.1: +- version "6.10.1" +- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.1.tgz#ebf8d3af22552df9dd049bfbe50cc2390e823593" +- integrity sha512-w1YQaVGNC6t2UCPjEawK/vo/dG8OOrVtUmhBT1uJJYxbl5kU2Tj3v6LGqBcsysN1yhuCStJCCA3GqdvKY8sqXQ== ++acorn@^7.1.0: ++ version "7.1.0" ++ resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" ++ integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== ++ ++ajv-errors@^1.0.0: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" ++ integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== ++ ++ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: ++ version "3.4.1" ++ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" ++ integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== ++ ++ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: ++ version "6.10.2" ++ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" ++ integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +-amdefine@>=0.0.4: +- version "1.0.1" +- resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" +- integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= ++alphanum-sort@^1.0.0: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" ++ integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= + +-ansi-escapes@^3.2.0: ++ansi-colors@^3.0.0: ++ version "3.2.4" ++ resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" ++ integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== ++ ++ansi-escapes@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + ++ansi-escapes@^4.2.1: ++ version "4.3.0" ++ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" ++ integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== ++ dependencies: ++ type-fest "^0.8.1" ++ ++ansi-html@0.0.7: ++ version "0.0.7" ++ resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" ++ integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= ++ + ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" +@@ -133,11 +892,21 @@ ansi-regex@^3.0.0: + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +-ansi-regex@^4.1.0: ++ansi-regex@^4.0.0, ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + ++ansi-regex@^5.0.0: ++ version "5.0.0" ++ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" ++ integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== ++ ++ansi-styles@^2.2.1: ++ version "2.2.1" ++ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" ++ integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= ++ + ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" +@@ -158,11 +927,23 @@ apollojs@^1.3.0: + resolved "https://registry.yarnpkg.com/apollojs/-/apollojs-1.3.0.tgz#5f7b00304d9740e2a7be5b52c7c0807d51f9255e" + integrity sha1-X3sAME2XQOKnvltSx8CAfVH5JV4= + +-aproba@^1.0.3: ++aproba@^1.0.3, aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + ++arch@^2.1.0: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e" ++ integrity sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg== ++ ++archive-type@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/archive-type/-/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70" ++ integrity sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA= ++ dependencies: ++ file-type "^4.2.0" ++ + are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" +@@ -171,6 +952,11 @@ are-we-there-yet@~1.1.2: + delegates "^1.0.0" + readable-stream "^2.0.6" + ++arg@^4.1.0: ++ version "4.1.1" ++ resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.1.tgz#485f8e7c390ce4c5f78257dbea80d4be11feda4c" ++ integrity sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw== ++ + argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" +@@ -193,28 +979,46 @@ arr-union@^3.1.0: + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +-array-filter@~0.0.0: +- version "0.0.1" +- resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" +- integrity sha1-fajPLiZijtcygDWB/SH2fKzS7uw= ++array-equal@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" ++ integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= + +-array-map@~0.0.0: +- version "0.0.0" +- resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" +- integrity sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI= ++array-find-index@^1.0.1: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" ++ integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= + +-array-reduce@~0.0.0: +- version "0.0.0" +- resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" +- integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys= ++array-flatten@1.1.1: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" ++ integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= ++ ++array-flatten@^2.1.0: ++ version "2.1.2" ++ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" ++ integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== ++ ++array-includes@^3.0.3: ++ version "3.0.3" ++ resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" ++ integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= ++ dependencies: ++ define-properties "^1.1.2" ++ es-abstract "^1.7.0" + +-array-union@^1.0.2: ++array-union@^1.0.1, array-union@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= + dependencies: + array-uniq "^1.0.1" + ++array-union@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" ++ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== ++ + array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" +@@ -246,7 +1050,7 @@ assert-plus@1.0.0, assert-plus@^1.0.0: + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +-assert@^1.4.0: ++assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== +@@ -269,10 +1073,22 @@ async-each@^1.0.1: + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +-async@1.x: +- version "1.5.2" +- resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" +- integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= ++async-limiter@~1.0.0: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" ++ integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== ++ ++async@^2.6.2: ++ version "2.6.3" ++ resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" ++ integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== ++ dependencies: ++ lodash "^4.17.14" ++ ++async@~0.2.10: ++ version "0.2.10" ++ resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" ++ integrity sha1-trvgsGdLnXGXCMo43owjfLUmw9E= + + asynckit@^0.4.0: + version "0.4.0" +@@ -284,18 +1100,18 @@ atob@^2.1.1: + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +-autoprefixer@^9.6.0: +- version "9.6.1" +- resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.1.tgz#51967a02d2d2300bb01866c1611ec8348d355a47" +- integrity sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw== ++autoprefixer@9.7.2, autoprefixer@^9.6.1: ++ version "9.7.2" ++ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.2.tgz#26cf729fbb709323b40171a874304884dcceffed" ++ integrity sha512-LCAfcdej1182uVvPOZnytbq61AhnOZ/4JelDaJGDeNwewyU1AMaNthcHsyz1NRjTmd2FkurMckLWfkHg3Z//KA== + dependencies: +- browserslist "^4.6.3" +- caniuse-lite "^1.0.30000980" ++ browserslist "^4.7.3" ++ caniuse-lite "^1.0.30001010" + chalk "^2.4.2" + normalize-range "^0.1.2" + num2fraction "^1.2.2" +- postcss "^7.0.17" +- postcss-value-parser "^4.0.0" ++ postcss "^7.0.23" ++ postcss-value-parser "^4.0.2" + + aws-sign2@~0.7.0: + version "0.7.0" +@@ -307,15 +1123,53 @@ aws4@^1.8.0: + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + ++babel-jest@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54" ++ integrity sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw== ++ dependencies: ++ "@jest/transform" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ "@types/babel__core" "^7.1.0" ++ babel-plugin-istanbul "^5.1.0" ++ babel-preset-jest "^24.9.0" ++ chalk "^2.4.2" ++ slash "^2.0.0" ++ ++babel-plugin-istanbul@^5.1.0: ++ version "5.2.0" ++ resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz#df4ade83d897a92df069c4d9a25cf2671293c854" ++ integrity sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw== ++ dependencies: ++ "@babel/helper-plugin-utils" "^7.0.0" ++ find-up "^3.0.0" ++ istanbul-lib-instrument "^3.3.0" ++ test-exclude "^5.2.3" ++ ++babel-plugin-jest-hoist@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz#4f837091eb407e01447c8843cbec546d0002d756" ++ integrity sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw== ++ dependencies: ++ "@types/babel__traverse" "^7.0.6" ++ ++babel-preset-jest@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz#192b521e2217fb1d1f67cf73f70c336650ad3cdc" ++ integrity sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg== ++ dependencies: ++ "@babel/plugin-syntax-object-rest-spread" "^7.0.0" ++ babel-plugin-jest-hoist "^24.9.0" ++ + balanced-match@^1.0.0: + version "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: +- version "1.3.0" +- resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" +- integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== ++ 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== + + base@^0.11.1: + version "0.11.2" +@@ -330,6 +1184,11 @@ base@^0.11.1: + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + ++batch@0.6.1: ++ version "0.6.1" ++ resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" ++ integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= ++ + bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" +@@ -337,21 +1196,125 @@ bcrypt-pbkdf@^1.0.0: + dependencies: + tweetnacl "^0.14.3" + ++big.js@^3.1.3: ++ version "3.2.0" ++ resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" ++ integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== ++ ++big.js@^5.2.2: ++ version "5.2.2" ++ resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" ++ integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== ++ ++bin-build@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/bin-build/-/bin-build-3.0.0.tgz#c5780a25a8a9f966d8244217e6c1f5082a143861" ++ integrity sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA== ++ dependencies: ++ decompress "^4.0.0" ++ download "^6.2.2" ++ execa "^0.7.0" ++ p-map-series "^1.0.0" ++ tempfile "^2.0.0" ++ ++bin-check@^4.1.0: ++ version "4.1.0" ++ resolved "https://registry.yarnpkg.com/bin-check/-/bin-check-4.1.0.tgz#fc495970bdc88bb1d5a35fc17e65c4a149fc4a49" ++ integrity sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA== ++ dependencies: ++ execa "^0.7.0" ++ executable "^4.1.0" ++ ++bin-version-check@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-4.0.0.tgz#7d819c62496991f80d893e6e02a3032361608f71" ++ integrity sha512-sR631OrhC+1f8Cvs8WyVWOA33Y8tgwjETNPyyD/myRBXLkfS/vl74FmH/lFcRl9KY3zwGh7jFhvyk9vV3/3ilQ== ++ dependencies: ++ bin-version "^3.0.0" ++ semver "^5.6.0" ++ semver-truncate "^1.1.2" ++ ++bin-version@^3.0.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-3.1.0.tgz#5b09eb280752b1bd28f0c9db3f96f2f43b6c0839" ++ integrity sha512-Mkfm4iE1VFt4xd4vH+gx+0/71esbfus2LsnCGe8Pi4mndSPyT+NGES/Eg99jx8/lUGWfu3z2yuB/bt5UB+iVbQ== ++ dependencies: ++ execa "^1.0.0" ++ find-versions "^3.0.0" ++ ++bin-wrapper@^4.0.0, bin-wrapper@^4.0.1: ++ version "4.1.0" ++ resolved "https://registry.yarnpkg.com/bin-wrapper/-/bin-wrapper-4.1.0.tgz#99348f2cf85031e3ef7efce7e5300aeaae960605" ++ integrity sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q== ++ dependencies: ++ bin-check "^4.1.0" ++ bin-version-check "^4.0.0" ++ download "^7.1.0" ++ import-lazy "^3.1.0" ++ os-filter-obj "^2.0.0" ++ pify "^4.0.1" ++ + binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +-bluebird@^3.5.0, bluebird@^3.5.x: +- version "3.5.5" +- resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" +- integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== ++bl@^1.0.0: ++ version "1.2.2" ++ resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" ++ integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== ++ dependencies: ++ readable-stream "^2.3.5" ++ safe-buffer "^5.1.1" ++ ++bluebird@^3.5.0, bluebird@^3.5.5, bluebird@^3.5.x: ++ version "3.7.1" ++ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" ++ integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== + + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== + ++body-parser@1.19.0: ++ version "1.19.0" ++ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" ++ integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== ++ dependencies: ++ bytes "3.1.0" ++ content-type "~1.0.4" ++ debug "2.6.9" ++ depd "~1.1.2" ++ http-errors "1.7.2" ++ iconv-lite "0.4.24" ++ on-finished "~2.3.0" ++ qs "6.7.0" ++ raw-body "2.4.0" ++ type-is "~1.6.17" ++ ++bonjour@^3.5.0: ++ version "3.5.0" ++ resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" ++ integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= ++ dependencies: ++ array-flatten "^2.1.0" ++ deep-equal "^1.0.1" ++ dns-equal "^1.0.0" ++ dns-txt "^2.0.2" ++ multicast-dns "^6.0.1" ++ multicast-dns-service-types "^1.1.0" ++ ++boolbase@^1.0.0, boolbase@~1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" ++ integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= ++ ++bootstrap@3.4.1: ++ version "3.4.1" ++ resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-3.4.1.tgz#c3a347d419e289ad11f4033e3c4132b87c081d72" ++ integrity sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA== ++ + brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" +@@ -376,24 +1339,24 @@ braces@^2.3.1, braces@^2.3.2: + split-string "^3.0.2" + to-regex "^3.0.1" + ++braces@^3.0.1: ++ version "3.0.2" ++ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" ++ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== ++ dependencies: ++ fill-range "^7.0.1" ++ + brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +-browser-pack@^6.0.1: +- version "6.1.0" +- resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.1.0.tgz#c34ba10d0b9ce162b5af227c7131c92c2ecd5774" +- integrity sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA== +- dependencies: +- JSONStream "^1.0.3" +- combine-source-map "~0.8.0" +- defined "^1.0.0" +- safe-buffer "^5.1.1" +- through2 "^2.0.0" +- umd "^3.0.0" ++browser-process-hrtime@^0.1.2: ++ version "0.1.3" ++ resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" ++ integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw== + +-browser-resolve@^1.11.0, browser-resolve@^1.7.0: ++browser-resolve@^1.11.3: + version "1.11.3" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" + integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ== +@@ -457,90 +1420,87 @@ browserify-sign@^4.0.0: + inherits "^2.0.1" + parse-asn1 "^5.0.0" + +-browserify-zlib@~0.2.0: ++browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +-browserify@^16.2.3: +- version "16.3.0" +- resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.3.0.tgz#4d414466e0b07492fff493a009ea883a9f2db230" +- integrity sha512-BWaaD7alyGZVEBBwSTYx4iJF5DswIGzK17o8ai9w4iKRbYpk3EOiprRHMRRA8DCZFmFeOdx7A385w2XdFvxWmg== +- dependencies: +- JSONStream "^1.0.3" +- assert "^1.4.0" +- browser-pack "^6.0.1" +- browser-resolve "^1.11.0" +- browserify-zlib "~0.2.0" +- buffer "^5.0.2" +- cached-path-relative "^1.0.0" +- concat-stream "^1.6.0" +- console-browserify "^1.1.0" +- constants-browserify "~1.0.0" +- crypto-browserify "^3.0.0" +- defined "^1.0.0" +- deps-sort "^2.0.0" +- domain-browser "^1.2.0" +- duplexer2 "~0.1.2" +- events "^2.0.0" +- glob "^7.1.0" +- has "^1.0.0" +- htmlescape "^1.1.0" +- https-browserify "^1.0.0" +- inherits "~2.0.1" +- insert-module-globals "^7.0.0" +- labeled-stream-splicer "^2.0.0" +- mkdirp "^0.5.0" +- module-deps "^6.0.0" +- os-browserify "~0.3.0" +- parents "^1.0.1" +- path-browserify "~0.0.0" +- process "~0.11.0" +- punycode "^1.3.2" +- querystring-es3 "~0.2.0" +- read-only-stream "^2.0.0" +- readable-stream "^2.0.2" +- resolve "^1.1.4" +- shasum "^1.0.0" +- shell-quote "^1.6.1" +- stream-browserify "^2.0.0" +- stream-http "^2.0.0" +- string_decoder "^1.1.1" +- subarg "^1.0.0" +- syntax-error "^1.1.1" +- through2 "^2.0.0" +- timers-browserify "^1.0.1" +- tty-browserify "0.0.1" +- url "~0.11.0" +- util "~0.10.1" +- vm-browserify "^1.0.0" +- xtend "^4.0.0" +- +-browserslist@^4.6.3: +- version "4.6.4" +- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.4.tgz#fd0638b3f8867fec2c604ed0ed9300379f8ec7c2" +- integrity sha512-ErJT8qGfRt/VWHSr1HeqZzz50DvxHtr1fVL1m5wf20aGrG8e1ce8fpZ2EjZEfs09DDZYSvtRaDlMpWslBf8Low== ++browserslist@^4.0.0, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.7.3: ++ version "4.7.3" ++ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.3.tgz#02341f162b6bcc1e1028e30624815d4924442dc3" ++ integrity sha512-jWvmhqYpx+9EZm/FxcZSbUZyDEvDTLDi3nSAKbzEkyWvtI0mNSmUosey+5awDW1RUlrgXbQb5A6qY1xQH9U6MQ== + dependencies: +- caniuse-lite "^1.0.30000981" +- electron-to-chromium "^1.3.188" +- node-releases "^1.1.25" ++ caniuse-lite "^1.0.30001010" ++ electron-to-chromium "^1.3.306" ++ node-releases "^1.1.40" + +-buffer-from@^1.0.0: +- version "1.1.1" +- resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" +- integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== ++bs-logger@0.x: ++ version "0.2.6" ++ resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" ++ integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== ++ dependencies: ++ fast-json-stable-stringify "2.x" ++ ++bser@^2.0.0: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" ++ integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== ++ dependencies: ++ node-int64 "^0.4.0" ++ ++buffer-alloc-unsafe@^1.1.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" ++ integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== ++ ++buffer-alloc@^1.2.0: ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" ++ integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== ++ dependencies: ++ buffer-alloc-unsafe "^1.1.0" ++ buffer-fill "^1.0.0" ++ ++buffer-crc32@~0.2.3: ++ version "0.2.13" ++ resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" ++ integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= ++ ++buffer-fill@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" ++ integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= ++ ++buffer-from@1.x, buffer-from@^1.0.0: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" ++ integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== ++ ++buffer-indexof@^1.0.0: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" ++ integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== + + buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +-buffer@^5.0.2: +- version "5.2.1" +- resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" +- integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== ++buffer@^4.3.0: ++ version "4.9.2" ++ resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" ++ integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== ++ dependencies: ++ base64-js "^1.0.2" ++ ieee754 "^1.1.4" ++ isarray "^1.0.0" ++ ++buffer@^5.2.1: ++ version "5.4.3" ++ resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" ++ integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" +@@ -550,6 +1510,37 @@ builtin-status-codes@^3.0.0: + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + ++bytes@3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" ++ integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= ++ ++bytes@3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" ++ integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== ++ ++cacache@^12.0.2, cacache@^12.0.3: ++ version "12.0.3" ++ resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" ++ integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== ++ dependencies: ++ bluebird "^3.5.5" ++ chownr "^1.1.1" ++ figgy-pudding "^3.5.1" ++ glob "^7.1.4" ++ graceful-fs "^4.1.15" ++ infer-owner "^1.0.3" ++ lru-cache "^5.1.1" ++ mississippi "^3.0.0" ++ mkdirp "^0.5.1" ++ move-concurrently "^1.0.1" ++ promise-inflight "^1.0.1" ++ rimraf "^2.6.3" ++ ssri "^6.0.1" ++ unique-filename "^1.1.1" ++ y18n "^4.0.0" ++ + cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" +@@ -565,10 +1556,18 @@ cache-base@^1.0.1: + union-value "^1.0.0" + unset-value "^1.0.0" + +-cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: +- version "1.0.2" +- resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.2.tgz#a13df4196d26776220cc3356eb147a52dba2c6db" +- integrity sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg== ++cacheable-request@^2.1.1: ++ version "2.1.4" ++ resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" ++ integrity sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0= ++ dependencies: ++ clone-response "1.0.2" ++ get-stream "3.0.0" ++ http-cache-semantics "3.8.1" ++ keyv "3.0.0" ++ lowercase-keys "1.0.0" ++ normalize-url "2.0.1" ++ responselike "1.0.2" + + call-me-maybe@^1.0.1: + version "1.0.1" +@@ -599,22 +1598,75 @@ callsites@^3.0.0: + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +-camelcase@^5.0.0: ++camel-case@3.0.x: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" ++ integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= ++ dependencies: ++ no-case "^2.2.0" ++ upper-case "^1.1.1" ++ ++camelcase-keys@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" ++ integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= ++ dependencies: ++ camelcase "^2.0.0" ++ map-obj "^1.0.0" ++ ++camelcase@^2.0.0: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" ++ integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= ++ ++camelcase@^4.1.0: ++ version "4.1.0" ++ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" ++ integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= ++ ++camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +-caniuse-lite@^1.0.30000980, caniuse-lite@^1.0.30000981: +- version "1.0.30000983" +- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000983.tgz#ab3c70061ca2a3467182a10ac75109b199b647f8" +- integrity sha512-/llD1bZ6qwNkt41AsvjsmwNOoA4ZB+8iqmf5LVyeSXuBODT/hAMFNVOh84NdUzoiYiSKqo5vQ3ZzeYHSi/olDQ== ++caniuse-api@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" ++ integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== ++ dependencies: ++ browserslist "^4.0.0" ++ caniuse-lite "^1.0.0" ++ lodash.memoize "^4.1.2" ++ lodash.uniq "^4.5.0" ++ ++caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001010: ++ version "1.0.30001011" ++ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001011.tgz#0d6c4549c78c4a800bb043a83ca0cbe0aee6c6e1" ++ integrity sha512-h+Eqyn/YA6o6ZTqpS86PyRmNWOs1r54EBDcd2NTwwfsXQ8re1B38SnB+p2RKF8OUsyEIjeDU8XGec1RGO/wYCg== ++ ++capture-exit@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" ++ integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== ++ dependencies: ++ rsvp "^4.8.4" + + caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: ++caw@^2.0.0, caw@^2.0.1: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" ++ integrity sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA== ++ dependencies: ++ get-proxy "^2.0.0" ++ isurl "^1.0.0-alpha5" ++ tunnel-agent "^0.6.0" ++ url-to-options "^1.0.1" ++ ++chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== +@@ -623,15 +1675,26 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + ++chalk@^1.0.0: ++ version "1.1.3" ++ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" ++ integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= ++ dependencies: ++ ansi-styles "^2.2.1" ++ escape-string-regexp "^1.0.2" ++ has-ansi "^2.0.0" ++ strip-ansi "^3.0.0" ++ supports-color "^2.0.0" ++ + chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +-chokidar@^2.0.0: +- version "2.1.6" +- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" +- integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g== ++chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.1.8: ++ version "2.1.8" ++ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" ++ integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" +@@ -648,9 +1711,21 @@ chokidar@^2.0.0: + fsevents "^1.2.7" + + chownr@^1.1.1: +- version "1.1.2" +- resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" +- integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== ++ version "1.1.3" ++ resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" ++ integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== ++ ++chrome-trace-event@^1.0.2: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" ++ integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== ++ dependencies: ++ tslib "^1.9.0" ++ ++ci-info@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" ++ integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" +@@ -670,34 +1745,34 @@ class-utils@^0.3.5: + isobject "^3.0.0" + static-extend "^0.1.1" + +-clean-css-cli@^4.3.0: +- version "4.3.0" +- resolved "https://registry.yarnpkg.com/clean-css-cli/-/clean-css-cli-4.3.0.tgz#8502aa86d1879e5b111af51b3c2abb799e0684ce" +- integrity sha512-8GHZfr+mG3zB/Lgqrr27qHBFsPSn0fyEI3f2rIZpxPxUbn2J6A8xyyeBRVTW8duDuXigN0s80vsXiXJOEFIO5Q== +- dependencies: +- clean-css "^4.2.1" +- commander "2.x" +- glob "7.x" +- +-clean-css@^4.2.1: ++clean-css@4.2.x: + version "4.2.1" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" + integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g== + dependencies: + source-map "~0.6.0" + +-cli-cursor@^2.1.0: +- version "2.1.0" +- resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" +- integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= ++cli-cursor@^3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" ++ integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: +- restore-cursor "^2.0.0" ++ restore-cursor "^3.1.0" + + cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + ++clipboard@2.0.4: ++ version "2.0.4" ++ resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.4.tgz#836dafd66cf0fea5d71ce5d5b0bf6e958009112d" ++ integrity sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ== ++ dependencies: ++ good-listener "^1.2.2" ++ select "^1.1.2" ++ tiny-emitter "^2.0.0" ++ + cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" +@@ -707,7 +1782,37 @@ cliui@^4.0.0: + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +-codacy-coverage@^3.4.0: ++cliui@^5.0.0: ++ version "5.0.0" ++ resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" ++ integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== ++ dependencies: ++ string-width "^3.1.0" ++ strip-ansi "^5.2.0" ++ wrap-ansi "^5.1.0" ++ ++clone-response@1.0.2: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" ++ integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= ++ dependencies: ++ mimic-response "^1.0.0" ++ ++co@^4.6.0: ++ version "4.6.0" ++ resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" ++ integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= ++ ++coa@^2.0.2: ++ version "2.0.2" ++ resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" ++ integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== ++ dependencies: ++ "@types/q" "^1.5.1" ++ chalk "^2.4.1" ++ q "^1.1.2" ++ ++codacy-coverage@3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/codacy-coverage/-/codacy-coverage-3.4.0.tgz#196af70844c4e4179718f7a7f9d96b921b4b3a67" + integrity sha512-A0ats3/gZtOw76muu++HZ6QrInztWjjLefkLJmmBpjPfyn6nNwNLoApmGmj3F3dfgl2+o6u5GwPnUBkKdfKXTQ== +@@ -735,7 +1840,7 @@ collection-visit@^1.0.0: + map-visit "^1.0.0" + object-visit "^1.0.0" + +-color-convert@^1.9.0: ++color-convert@^1.9.0, color-convert@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== +@@ -747,15 +1852,26 @@ color-name@1.1.3: + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +-combine-source-map@^0.8.0, combine-source-map@~0.8.0: +- version "0.8.0" +- resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" +- integrity sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos= ++color-name@^1.0.0: ++ version "1.1.4" ++ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" ++ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== ++ ++color-string@^1.5.2: ++ version "1.5.3" ++ resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" ++ integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== ++ dependencies: ++ color-name "^1.0.0" ++ simple-swizzle "^0.2.2" ++ ++color@^3.0.0: ++ version "3.1.2" ++ resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" ++ integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== + dependencies: +- convert-source-map "~1.1.0" +- inline-source-map "~0.6.0" +- lodash.memoize "~3.0.3" +- source-map "~0.5.3" ++ color-convert "^1.9.1" ++ color-string "^1.5.2" + + combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" +@@ -769,22 +1885,64 @@ commander@2.15.1: + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== + +-commander@2.x, commander@^2.x, commander@~2.20.0: +- version "2.20.0" +- resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" +- integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== ++commander@2.17.x: ++ version "2.17.1" ++ resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" ++ integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== ++ ++commander@^2.20.0, commander@^2.x, commander@~2.20.3: ++ version "2.20.3" ++ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" ++ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== ++ ++commander@~2.19.0: ++ version "2.19.0" ++ resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" ++ integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== ++ ++commander@~2.8.1: ++ version "2.8.1" ++ resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" ++ integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= ++ dependencies: ++ graceful-readlink ">= 1.0.0" ++ ++commondir@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" ++ integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + + component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + ++compressible@~2.0.16: ++ version "2.0.17" ++ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1" ++ integrity sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw== ++ dependencies: ++ mime-db ">= 1.40.0 < 2" ++ ++compression@^1.7.4: ++ version "1.7.4" ++ resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" ++ integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== ++ dependencies: ++ accepts "~1.3.5" ++ bytes "3.0.0" ++ compressible "~2.0.16" ++ debug "2.6.9" ++ on-headers "~1.0.2" ++ safe-buffer "5.1.2" ++ vary "~1.1.2" ++ + concat-map@0.0.1: + version "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.0, concat-stream@^1.6.1, concat-stream@~1.6.0: ++concat-stream@^1.5.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== +@@ -794,33 +1952,108 @@ concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@~1.6.0: + readable-stream "^2.2.2" + typedarray "^0.0.6" + +-console-browserify@^1.1.0: +- version "1.1.0" +- resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" +- integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= ++config-chain@^1.1.11: ++ version "1.1.12" ++ resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" ++ integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== + dependencies: +- date-now "^0.1.4" ++ ini "^1.3.4" ++ proto-list "~1.2.1" ++ ++connect-history-api-fallback@^1.6.0: ++ version "1.6.0" ++ resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" ++ integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== ++ ++console-browserify@^1.1.0: ++ version "1.2.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 sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +-constants-browserify@~1.0.0: ++console-stream@^0.1.1: ++ version "0.1.1" ++ resolved "https://registry.yarnpkg.com/console-stream/-/console-stream-0.1.1.tgz#a095fe07b20465955f2fafd28b5d72bccd949d44" ++ integrity sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ= ++ ++constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +-convert-source-map@~1.1.0: +- version "1.1.3" +- resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" +- integrity sha1-SCnId+n+SbMWHzvzZziI4gRpmGA= ++contains-path@^0.1.0: ++ version "0.1.0" ++ resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" ++ integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= ++ ++content-disposition@0.5.3, content-disposition@^0.5.2: ++ version "0.5.3" ++ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" ++ integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== ++ dependencies: ++ safe-buffer "5.1.2" ++ ++content-type@~1.0.4: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" ++ integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== ++ ++convert-source-map@^1.4.0, convert-source-map@^1.7.0: ++ version "1.7.0" ++ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" ++ integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== ++ dependencies: ++ safe-buffer "~5.1.1" ++ ++cookie-signature@1.0.6: ++ version "1.0.6" ++ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" ++ integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= ++ ++cookie@0.4.0: ++ version "0.4.0" ++ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" ++ integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== ++ ++copy-concurrently@^1.0.0: ++ version "1.0.5" ++ resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" ++ integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== ++ dependencies: ++ aproba "^1.1.1" ++ fs-write-stream-atomic "^1.0.8" ++ iferr "^0.1.5" ++ mkdirp "^0.5.1" ++ rimraf "^2.5.4" ++ run-queue "^1.0.0" + + copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + ++copy-webpack-plugin@5.0.5: ++ version "5.0.5" ++ resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.0.5.tgz#731df6a837a2ef0f8f8e2345bdfe9b7c62a2da68" ++ integrity sha512-7N68eIoQTyudAuxkfPT7HzGoQ+TsmArN/I3HFwG+lVE3FNzqvZKIiaxtYh4o3BIznioxUvx9j26+Rtsc9htQUQ== ++ dependencies: ++ cacache "^12.0.3" ++ find-cache-dir "^2.1.0" ++ glob-parent "^3.1.0" ++ globby "^7.1.1" ++ is-glob "^4.0.1" ++ loader-utils "^1.2.3" ++ minimatch "^3.0.4" ++ normalize-path "^3.0.0" ++ p-limit "^2.2.1" ++ schema-utils "^1.0.0" ++ serialize-javascript "^2.1.0" ++ webpack-log "^2.0.0" ++ + core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" +@@ -867,7 +2100,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +-cross-spawn@^6.0.0, cross-spawn@^6.0.5: ++cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== +@@ -878,7 +2111,16 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: + shebang-command "^1.2.0" + which "^1.2.9" + +-crypto-browserify@^3.0.0: ++cross-spawn@^5.0.1: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" ++ integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= ++ dependencies: ++ lru-cache "^4.0.1" ++ shebang-command "^1.2.0" ++ which "^1.2.9" ++ ++crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== +@@ -895,10 +2137,229 @@ crypto-browserify@^3.0.0: + randombytes "^2.0.0" + randomfill "^1.0.3" + +-dash-ast@^1.0.0: +- version "1.0.0" +- resolved "https://registry.yarnpkg.com/dash-ast/-/dash-ast-1.0.0.tgz#12029ba5fb2f8aa6f0a861795b23c1b4b6c27d37" +- integrity sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA== ++css-blank-pseudo@^0.1.4: ++ version "0.1.4" ++ resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" ++ integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== ++ dependencies: ++ postcss "^7.0.5" ++ ++css-color-names@0.0.4, css-color-names@^0.0.4: ++ version "0.0.4" ++ resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" ++ integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= ++ ++css-declaration-sorter@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" ++ integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== ++ dependencies: ++ postcss "^7.0.1" ++ timsort "^0.3.0" ++ ++css-has-pseudo@^0.10.0: ++ version "0.10.0" ++ resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" ++ integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== ++ dependencies: ++ postcss "^7.0.6" ++ postcss-selector-parser "^5.0.0-rc.4" ++ ++css-loader@3.2.0: ++ version "3.2.0" ++ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.2.0.tgz#bb570d89c194f763627fcf1f80059c6832d009b2" ++ integrity sha512-QTF3Ud5H7DaZotgdcJjGMvyDj5F3Pn1j/sC6VBEOVp94cbwqyIBdcs/quzj4MC1BKQSrTpQznegH/5giYbhnCQ== ++ dependencies: ++ camelcase "^5.3.1" ++ cssesc "^3.0.0" ++ icss-utils "^4.1.1" ++ loader-utils "^1.2.3" ++ normalize-path "^3.0.0" ++ postcss "^7.0.17" ++ postcss-modules-extract-imports "^2.0.0" ++ postcss-modules-local-by-default "^3.0.2" ++ postcss-modules-scope "^2.1.0" ++ postcss-modules-values "^3.0.0" ++ postcss-value-parser "^4.0.0" ++ schema-utils "^2.0.0" ++ ++css-prefers-color-scheme@^3.1.1: ++ version "3.1.1" ++ resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" ++ integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== ++ dependencies: ++ postcss "^7.0.5" ++ ++css-select-base-adapter@^0.1.1: ++ version "0.1.1" ++ resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" ++ integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== ++ ++css-select@^1.1.0: ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" ++ integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= ++ dependencies: ++ boolbase "~1.0.0" ++ css-what "2.1" ++ domutils "1.5.1" ++ nth-check "~1.0.1" ++ ++css-select@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" ++ integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== ++ dependencies: ++ boolbase "^1.0.0" ++ css-what "^3.2.1" ++ domutils "^1.7.0" ++ nth-check "^1.0.2" ++ ++css-tree@1.0.0-alpha.37: ++ version "1.0.0-alpha.37" ++ resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" ++ integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== ++ dependencies: ++ mdn-data "2.0.4" ++ source-map "^0.6.1" ++ ++css-unit-converter@^1.1.1: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" ++ integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= ++ ++css-what@2.1: ++ version "2.1.3" ++ resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" ++ integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== ++ ++css-what@^3.2.1: ++ version "3.2.1" ++ resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" ++ integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== ++ ++cssdb@^4.4.0: ++ version "4.4.0" ++ resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" ++ integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== ++ ++cssesc@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" ++ integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== ++ ++cssesc@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" ++ integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== ++ ++cssnano-preset-default@^4.0.7: ++ version "4.0.7" ++ resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" ++ integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== ++ dependencies: ++ css-declaration-sorter "^4.0.1" ++ cssnano-util-raw-cache "^4.0.1" ++ postcss "^7.0.0" ++ postcss-calc "^7.0.1" ++ postcss-colormin "^4.0.3" ++ postcss-convert-values "^4.0.1" ++ postcss-discard-comments "^4.0.2" ++ postcss-discard-duplicates "^4.0.2" ++ postcss-discard-empty "^4.0.1" ++ postcss-discard-overridden "^4.0.1" ++ postcss-merge-longhand "^4.0.11" ++ postcss-merge-rules "^4.0.3" ++ postcss-minify-font-values "^4.0.2" ++ postcss-minify-gradients "^4.0.2" ++ postcss-minify-params "^4.0.2" ++ postcss-minify-selectors "^4.0.2" ++ postcss-normalize-charset "^4.0.1" ++ postcss-normalize-display-values "^4.0.2" ++ postcss-normalize-positions "^4.0.2" ++ postcss-normalize-repeat-style "^4.0.2" ++ postcss-normalize-string "^4.0.2" ++ postcss-normalize-timing-functions "^4.0.2" ++ postcss-normalize-unicode "^4.0.1" ++ postcss-normalize-url "^4.0.1" ++ postcss-normalize-whitespace "^4.0.2" ++ postcss-ordered-values "^4.1.2" ++ postcss-reduce-initial "^4.0.3" ++ postcss-reduce-transforms "^4.0.2" ++ postcss-svgo "^4.0.2" ++ postcss-unique-selectors "^4.0.1" ++ ++cssnano-util-get-arguments@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" ++ integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= ++ ++cssnano-util-get-match@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" ++ integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= ++ ++cssnano-util-raw-cache@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" ++ integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== ++ dependencies: ++ postcss "^7.0.0" ++ ++cssnano-util-same-parent@^4.0.0: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" ++ integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== ++ ++cssnano@4.1.10: ++ version "4.1.10" ++ resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" ++ integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== ++ dependencies: ++ cosmiconfig "^5.0.0" ++ cssnano-preset-default "^4.0.7" ++ is-resolvable "^1.0.0" ++ postcss "^7.0.0" ++ ++csso@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d" ++ integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg== ++ dependencies: ++ css-tree "1.0.0-alpha.37" ++ ++cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": ++ version "0.3.8" ++ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" ++ integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== ++ ++cssstyle@^1.0.0: ++ version "1.4.0" ++ resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" ++ integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA== ++ dependencies: ++ cssom "0.3.x" ++ ++currently-unhandled@^0.4.1: ++ version "0.4.1" ++ resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" ++ integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= ++ dependencies: ++ array-find-index "^1.0.1" ++ ++cwebp-bin@^5.0.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/cwebp-bin/-/cwebp-bin-5.1.0.tgz#d5bea87c127358558e7bf7a90a6d440d42dcb074" ++ integrity sha512-BsPKStaNr98zfxwejWWLIGELbPERULJoD2v5ijvpeutSAGsegX7gmABgnkRK7MUucCPROXXfaPqkLAwI509JzA== ++ dependencies: ++ bin-build "^3.0.0" ++ bin-wrapper "^4.0.1" ++ logalot "^2.1.0" ++ ++cyclist@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" ++ integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= + + dashdash@^1.12.0: + version "1.14.1" +@@ -907,40 +2368,44 @@ dashdash@^1.12.0: + dependencies: + assert-plus "^1.0.0" + +-date-now@^0.1.4: +- version "0.1.4" +- resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" +- integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= +- +-debug@3.1.0: +- version "3.1.0" +- resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" +- integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== ++data-urls@^1.0.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" ++ integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ== + dependencies: +- ms "2.0.0" ++ abab "^2.0.0" ++ whatwg-mimetype "^2.2.0" ++ whatwg-url "^7.0.0" + +-debug@^2.2.0, debug@^2.3.3: ++debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +-debug@^3.2.6: ++debug@3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" ++ integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== ++ dependencies: ++ ms "2.0.0" ++ ++debug@^3.0.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +-debug@^4.0.1: ++debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +-decamelize@^1.2.0: ++decamelize@^1.1.2, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +@@ -950,6 +2415,78 @@ decode-uri-component@^0.2.0: + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + ++decompress-response@^3.2.0, decompress-response@^3.3.0: ++ version "3.3.0" ++ resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" ++ integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= ++ dependencies: ++ mimic-response "^1.0.0" ++ ++decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: ++ version "4.1.1" ++ resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" ++ integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== ++ dependencies: ++ file-type "^5.2.0" ++ is-stream "^1.1.0" ++ tar-stream "^1.5.2" ++ ++decompress-tarbz2@^4.0.0: ++ version "4.1.1" ++ resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" ++ integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== ++ dependencies: ++ decompress-tar "^4.1.0" ++ file-type "^6.1.0" ++ is-stream "^1.1.0" ++ seek-bzip "^1.0.5" ++ unbzip2-stream "^1.0.9" ++ ++decompress-targz@^4.0.0: ++ version "4.1.1" ++ resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" ++ integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== ++ dependencies: ++ decompress-tar "^4.1.1" ++ file-type "^5.2.0" ++ is-stream "^1.1.0" ++ ++decompress-unzip@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" ++ integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= ++ dependencies: ++ file-type "^3.8.0" ++ get-stream "^2.2.0" ++ pify "^2.3.0" ++ yauzl "^2.4.2" ++ ++decompress@^4.0.0, decompress@^4.2.0: ++ version "4.2.0" ++ resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" ++ integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= ++ dependencies: ++ decompress-tar "^4.0.0" ++ decompress-tarbz2 "^4.0.0" ++ decompress-targz "^4.0.0" ++ decompress-unzip "^4.0.1" ++ graceful-fs "^4.1.10" ++ make-dir "^1.0.0" ++ pify "^2.3.0" ++ strip-dirs "^2.0.0" ++ ++deep-equal@^1.0.1: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" ++ integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== ++ dependencies: ++ is-arguments "^1.0.4" ++ is-date-object "^1.0.1" ++ is-regex "^1.0.4" ++ object-is "^1.0.1" ++ object-keys "^1.1.1" ++ regexp.prototype.flags "^1.2.0" ++ + deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" +@@ -960,6 +2497,21 @@ deep-is@~0.1.3: + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + ++default-gateway@^4.2.0: ++ version "4.2.0" ++ resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" ++ integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== ++ dependencies: ++ execa "^1.0.0" ++ ip-regex "^2.1.0" ++ ++define-properties@^1.1.2, define-properties@^1.1.3: ++ version "1.1.3" ++ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" ++ integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== ++ dependencies: ++ object-keys "^1.0.12" ++ + define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" +@@ -982,64 +2534,88 @@ define-property@^2.0.2: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +-defined@^1.0.0: +- version "1.0.0" +- resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" +- integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= ++del@^4.1.1: ++ version "4.1.1" ++ resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" ++ integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== ++ dependencies: ++ "@types/glob" "^7.1.1" ++ globby "^6.1.0" ++ is-path-cwd "^2.0.0" ++ is-path-in-cwd "^2.0.0" ++ p-map "^2.0.0" ++ pify "^4.0.1" ++ rimraf "^2.6.3" + + delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +-delegates@^1.0.0: ++delegate@^3.1.2: ++ version "3.2.0" ++ resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" ++ integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== ++ ++delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + ++depd@~1.1.2: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" ++ integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= ++ + dependency-graph@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.8.0.tgz#2da2d35ed852ecc24a5d6c17788ba57c3708755b" + integrity sha512-DCvzSq2UiMsuLnj/9AL484ummEgLtZIcRS7YvtO38QnpX3vqh9nJ8P+zhu8Ja+SmLrBHO2iDbva20jq38qvBkQ== + +-deps-sort@^2.0.0: +- version "2.0.0" +- resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.0.tgz#091724902e84658260eb910748cccd1af6e21fb5" +- integrity sha1-CRckkC6EZYJg65EHSMzNGvbiH7U= +- dependencies: +- JSONStream "^1.0.3" +- shasum "^1.0.0" +- subarg "^1.0.0" +- through2 "^2.0.0" +- + des.js@^1.0.0: +- version "1.0.0" +- resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" +- integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" ++ integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + ++destroy@~1.0.4: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" ++ integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= ++ ++detect-file@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" ++ integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= ++ + detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +-detective@^5.0.2: +- version "5.2.0" +- resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" +- integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg== +- dependencies: +- acorn-node "^1.6.1" +- defined "^1.0.0" +- minimist "^1.1.1" ++detect-newline@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" ++ integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= ++ ++detect-node@^2.0.4: ++ version "2.0.4" ++ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" ++ integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== ++ ++diff-sequences@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" ++ integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== + + diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +-diff@^4.0.1: ++diff@4.0.1, diff@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" + integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== +@@ -1053,13 +2629,48 @@ diffie-hellman@^5.0.0: + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +-dir-glob@^2.2.2: ++dir-glob@^2.0.0, dir-glob@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" + integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== + dependencies: + path-type "^3.0.0" + ++dir-glob@^3.0.1: ++ version "3.0.1" ++ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" ++ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== ++ dependencies: ++ path-type "^4.0.0" ++ ++dns-equal@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" ++ integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= ++ ++dns-packet@^1.3.1: ++ version "1.3.1" ++ resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" ++ integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg== ++ dependencies: ++ ip "^1.1.0" ++ safe-buffer "^5.0.1" ++ ++dns-txt@^2.0.2: ++ version "2.0.2" ++ resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" ++ integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= ++ dependencies: ++ buffer-indexof "^1.0.0" ++ ++doctrine@1.5.0: ++ version "1.5.0" ++ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" ++ integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= ++ dependencies: ++ esutils "^2.0.2" ++ isarray "^1.0.0" ++ + doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" +@@ -1067,17 +2678,122 @@ doctrine@^3.0.0: + dependencies: + esutils "^2.0.2" + +-domain-browser@^1.2.0: ++dom-converter@^0.2: ++ version "0.2.0" ++ resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" ++ integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== ++ dependencies: ++ utila "~0.4" ++ ++dom-serializer@0: ++ version "0.2.2" ++ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" ++ integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== ++ dependencies: ++ domelementtype "^2.0.1" ++ entities "^2.0.0" ++ ++domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +-duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: ++domelementtype@1, domelementtype@^1.3.1: ++ version "1.3.1" ++ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" ++ integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== ++ ++domelementtype@^2.0.1: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" ++ integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== ++ ++domexception@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" ++ integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== ++ dependencies: ++ webidl-conversions "^4.0.2" ++ ++domhandler@^2.3.0: ++ version "2.4.2" ++ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" ++ integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== ++ dependencies: ++ domelementtype "1" ++ ++domutils@1.5.1: ++ version "1.5.1" ++ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" ++ integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= ++ dependencies: ++ dom-serializer "0" ++ domelementtype "1" ++ ++domutils@^1.5.1, domutils@^1.7.0: ++ version "1.7.0" ++ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" ++ integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== ++ dependencies: ++ dom-serializer "0" ++ domelementtype "1" ++ ++dot-prop@^4.1.1: ++ version "4.2.0" ++ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" ++ integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== ++ dependencies: ++ is-obj "^1.0.0" ++ ++download@^6.2.2: ++ version "6.2.5" ++ resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714" ++ integrity sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA== ++ dependencies: ++ caw "^2.0.0" ++ content-disposition "^0.5.2" ++ decompress "^4.0.0" ++ ext-name "^5.0.0" ++ file-type "5.2.0" ++ filenamify "^2.0.0" ++ get-stream "^3.0.0" ++ got "^7.0.0" ++ make-dir "^1.0.0" ++ p-event "^1.0.0" ++ pify "^3.0.0" ++ ++download@^7.1.0: ++ version "7.1.0" ++ resolved "https://registry.yarnpkg.com/download/-/download-7.1.0.tgz#9059aa9d70b503ee76a132897be6dec8e5587233" ++ integrity sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ== ++ dependencies: ++ archive-type "^4.0.0" ++ caw "^2.0.1" ++ content-disposition "^0.5.2" ++ decompress "^4.2.0" ++ ext-name "^5.0.0" ++ file-type "^8.1.0" ++ filenamify "^2.0.0" ++ get-stream "^3.0.0" ++ got "^8.3.1" ++ make-dir "^1.2.0" ++ p-event "^2.1.0" ++ pify "^3.0.0" ++ ++duplexer3@^0.1.4: + version "0.1.4" +- resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" +- integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= ++ resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" ++ integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= ++ ++duplexify@^3.4.2, duplexify@^3.6.0: ++ version "3.7.1" ++ resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" ++ integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: +- readable-stream "^2.0.2" ++ end-of-stream "^1.0.0" ++ inherits "^2.0.1" ++ readable-stream "^2.0.0" ++ stream-shift "^1.0.0" + + ecc-jsbn@~0.1.1: + version "0.1.2" +@@ -1087,15 +2803,20 @@ ecc-jsbn@~0.1.1: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +-electron-to-chromium@^1.3.188: +- version "1.3.190" +- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.190.tgz#5bf599519983bfffd9d4387817039a3ed7ca085f" +- integrity sha512-cs9WnTnGBGnYYVFMCtLmr9jXNTOkdp95RLz5VhwzDn7dErg1Lnt9o4d01gEH69XlmRKWUr91Yu1hA+Hi8qW0PA== ++ee-first@1.1.1: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" ++ integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= ++ ++electron-to-chromium@^1.3.306: ++ version "1.3.313" ++ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.313.tgz#6c63d8698ec4193b7e51e28531c47c88f1104579" ++ integrity sha512-rWbB6P3kPpWez/BZqrVatQ+lxJaDTv9pWgUUGYAA0/O5+YZLm6RiGy2Roml6rQj4EJ4r/eTdO0ppOZUUP2oFpQ== + + elliptic@^6.0.0: +- version "6.5.0" +- resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.0.tgz#2b8ed4c891b7de3200e14412a5b8248c7af505ca" +- integrity sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg== ++ version "6.5.2" ++ resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" ++ integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" +@@ -1110,51 +2831,205 @@ emoji-regex@^7.0.1: + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +-end-of-stream@^1.1.0: +- version "1.4.1" +- resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" +- integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== ++emoji-regex@^8.0.0: ++ version "8.0.0" ++ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" ++ integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== ++ ++emojis-list@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" ++ integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= ++ ++encodeurl@~1.0.2: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" ++ integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= ++ ++end-of-stream@^1.0.0, end-of-stream@^1.1.0: ++ 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" + ++enhanced-resolve@4.1.0: ++ version "4.1.0" ++ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" ++ integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== ++ dependencies: ++ graceful-fs "^4.1.2" ++ memory-fs "^0.4.0" ++ tapable "^1.0.0" ++ ++enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: ++ version "4.1.1" ++ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" ++ integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== ++ dependencies: ++ graceful-fs "^4.1.2" ++ memory-fs "^0.5.0" ++ tapable "^1.0.0" ++ + entities@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +-error-ex@^1.3.1: ++entities@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" ++ integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== ++ ++errno@^0.1.3, errno@~0.1.7: ++ version "0.1.7" ++ resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" ++ integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== ++ dependencies: ++ prr "~1.0.1" ++ ++error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +-escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: ++es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: ++ version "1.16.0" ++ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" ++ integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== ++ dependencies: ++ es-to-primitive "^1.2.0" ++ function-bind "^1.1.1" ++ has "^1.0.3" ++ has-symbols "^1.0.0" ++ is-callable "^1.1.4" ++ is-regex "^1.0.4" ++ object-inspect "^1.6.0" ++ object-keys "^1.1.1" ++ string.prototype.trimleft "^2.1.0" ++ string.prototype.trimright "^2.1.0" ++ ++es-to-primitive@^1.2.0: ++ version "1.2.1" ++ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" ++ integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== ++ dependencies: ++ is-callable "^1.1.4" ++ is-date-object "^1.0.1" ++ is-symbol "^1.0.2" ++ ++escape-html@~1.0.3: ++ version "1.0.3" ++ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" ++ integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= ++ ++escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +-escodegen@1.8.x: +- version "1.8.1" +- resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" +- integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= ++escodegen@^1.9.1: ++ version "1.12.0" ++ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541" ++ integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg== + dependencies: +- esprima "^2.7.1" +- estraverse "^1.9.1" ++ esprima "^3.1.3" ++ estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: +- source-map "~0.2.0" ++ source-map "~0.6.1" ++ ++eslint-config-prettier@6.7.0: ++ version "6.7.0" ++ resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz#9a876952e12df2b284adbd3440994bf1f39dfbb9" ++ integrity sha512-FamQVKM3jjUVwhG4hEMnbtsq7xOIDm+SY5iBPfR8gKsJoAB2IQnNF+bk1+8Fy44Nq7PPJaLvkRxILYdJWoguKQ== ++ dependencies: ++ get-stdin "^6.0.0" ++ ++eslint-config-standard@14.1.0: ++ version "14.1.0" ++ resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.0.tgz#b23da2b76fe5a2eba668374f246454e7058f15d4" ++ integrity sha512-EF6XkrrGVbvv8hL/kYa/m6vnvmUT+K82pJJc4JJVMM6+Qgqh0pnwprSxdduDLB9p/7bIxD+YV5O0wfb8lmcPbA== ++ ++eslint-import-resolver-node@^0.3.2: ++ version "0.3.2" ++ resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" ++ integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== ++ dependencies: ++ debug "^2.6.9" ++ resolve "^1.5.0" ++ ++eslint-module-utils@^2.4.0: ++ version "2.4.1" ++ resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz#7b4675875bf96b0dbf1b21977456e5bb1f5e018c" ++ integrity sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw== ++ dependencies: ++ debug "^2.6.8" ++ pkg-dir "^2.0.0" ++ ++eslint-plugin-es@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-2.0.0.tgz#0f5f5da5f18aa21989feebe8a73eadefb3432976" ++ integrity sha512-f6fceVtg27BR02EYnBhgWLFQfK6bN4Ll0nQFrBHOlCsAyxeZkn0NHns5O0YZOPrV1B3ramd6cgFwaoFLcSkwEQ== ++ dependencies: ++ eslint-utils "^1.4.2" ++ regexpp "^3.0.0" ++ ++eslint-plugin-import@2.18.2: ++ version "2.18.2" ++ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz#02f1180b90b077b33d447a17a2326ceb400aceb6" ++ integrity sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ== ++ dependencies: ++ array-includes "^3.0.3" ++ contains-path "^0.1.0" ++ debug "^2.6.9" ++ doctrine "1.5.0" ++ eslint-import-resolver-node "^0.3.2" ++ eslint-module-utils "^2.4.0" ++ has "^1.0.3" ++ minimatch "^3.0.4" ++ object.values "^1.1.0" ++ read-pkg-up "^2.0.0" ++ resolve "^1.11.0" + +-eslint-plugin-promise@^4.1.1: ++eslint-plugin-jest@23.0.4: ++ version "23.0.4" ++ resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.0.4.tgz#1ab81ffe3b16c5168efa72cbd4db14d335092aa0" ++ integrity sha512-OaP8hhT8chJNodUPvLJ6vl8gnalcsU/Ww1t9oR3HnGdEWjm/DdCCUXLOral+IPGAeWu/EwgVQCK/QtxALpH1Yw== ++ dependencies: ++ "@typescript-eslint/experimental-utils" "^2.5.0" ++ ++eslint-plugin-node@10.0.0: ++ version "10.0.0" ++ resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-10.0.0.tgz#fd1adbc7a300cf7eb6ac55cf4b0b6fc6e577f5a6" ++ integrity sha512-1CSyM/QCjs6PXaT18+zuAXsjXGIGo5Rw630rSKwokSs2jrYURQc4R5JZpoanNCqwNmepg+0eZ9L7YiRUJb8jiQ== ++ dependencies: ++ eslint-plugin-es "^2.0.0" ++ eslint-utils "^1.4.2" ++ ignore "^5.1.1" ++ minimatch "^3.0.4" ++ resolve "^1.10.1" ++ semver "^6.1.0" ++ ++eslint-plugin-prettier@3.1.1: ++ version "3.1.1" ++ resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz#507b8562410d02a03f0ddc949c616f877852f2ba" ++ integrity sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA== ++ dependencies: ++ prettier-linter-helpers "^1.0.0" ++ ++eslint-plugin-promise@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" + integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== + +-eslint-plugin-standard@^4.0.0: +- version "4.0.0" +- resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz#f845b45109c99cd90e77796940a344546c8f6b5c" +- integrity sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA== ++eslint-plugin-standard@4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" ++ integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ== + + eslint-scope@^4.0.3: + version "4.0.3" +@@ -1164,73 +3039,82 @@ eslint-scope@^4.0.3: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +-eslint-utils@^1.3.1: +- version "1.4.2" +- resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" +- integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== ++eslint-scope@^5.0.0: ++ version "5.0.0" ++ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" ++ integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== ++ dependencies: ++ esrecurse "^4.1.0" ++ estraverse "^4.1.1" ++ ++eslint-utils@^1.4.2, eslint-utils@^1.4.3: ++ version "1.4.3" ++ resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" ++ integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: +- eslint-visitor-keys "^1.0.0" ++ eslint-visitor-keys "^1.1.0" + +-eslint-visitor-keys@^1.0.0: ++eslint-visitor-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + +-eslint@^5.16.0: +- version "5.16.0" +- resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" +- integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== ++eslint@6.7.0: ++ version "6.7.0" ++ resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.0.tgz#766162e383b236e61d873697f82c3a3e41392020" ++ integrity sha512-dQpj+PaHKHfXHQ2Imcw5d853PTvkUGbHk/MR68KQUl98EgKDCdh4vLRH1ZxhqeQjQFJeg8fgN0UwmNhN3l8dDQ== + dependencies: + "@babel/code-frame" "^7.0.0" +- ajv "^6.9.1" ++ ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" +- eslint-scope "^4.0.3" +- eslint-utils "^1.3.1" +- eslint-visitor-keys "^1.0.0" +- espree "^5.0.1" ++ eslint-scope "^5.0.0" ++ eslint-utils "^1.4.3" ++ eslint-visitor-keys "^1.1.0" ++ espree "^6.1.2" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" +- glob "^7.1.2" +- globals "^11.7.0" ++ glob-parent "^5.0.0" ++ globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" +- inquirer "^6.2.2" +- js-yaml "^3.13.0" ++ inquirer "^7.0.0" ++ is-glob "^4.0.0" ++ js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" +- lodash "^4.17.11" ++ lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" +- optionator "^0.8.2" +- path-is-inside "^1.0.2" ++ optionator "^0.8.3" + progress "^2.0.0" + regexpp "^2.0.1" +- semver "^5.5.1" +- strip-ansi "^4.0.0" +- strip-json-comments "^2.0.1" ++ semver "^6.1.2" ++ strip-ansi "^5.2.0" ++ strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" ++ v8-compile-cache "^2.0.3" + +-espree@^5.0.1: +- version "5.0.1" +- resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" +- integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== ++espree@^6.1.2: ++ version "6.1.2" ++ resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" ++ integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== + dependencies: +- acorn "^6.0.7" +- acorn-jsx "^5.0.0" +- eslint-visitor-keys "^1.0.0" ++ acorn "^7.1.0" ++ acorn-jsx "^5.1.0" ++ eslint-visitor-keys "^1.1.0" + +-esprima@2.7.x, esprima@^2.7.1: +- version "2.7.3" +- resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" +- integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= ++esprima@^3.1.3: ++ version "3.1.3" ++ resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" ++ integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= + + esprima@^4.0.0: + version "4.0.1" +@@ -1251,25 +3135,37 @@ esrecurse@^4.1.0: + dependencies: + estraverse "^4.1.0" + +-estraverse@^1.9.1: +- version "1.9.3" +- resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" +- integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= +- +-estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: +- version "4.2.0" +- resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" +- integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= ++estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: ++ version "4.3.0" ++ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" ++ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + + esutils@^2.0.2: +- version "2.0.2" +- resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" +- integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= ++ version "2.0.3" ++ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" ++ integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +-events@^2.0.0: +- version "2.1.0" +- resolved "https://registry.yarnpkg.com/events/-/events-2.1.0.tgz#2a9a1e18e6106e0e812aa9ebd4a819b3c29c0ba5" +- integrity sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg== ++etag@~1.8.1: ++ version "1.8.1" ++ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" ++ integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= ++ ++eventemitter3@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" ++ integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== ++ ++events@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" ++ integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== ++ ++eventsource@^1.0.7: ++ version "1.0.7" ++ resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0" ++ integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ== ++ dependencies: ++ original "^1.0.0" + + evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" +@@ -1279,6 +3175,48 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + ++exec-buffer@^3.0.0: ++ version "3.2.0" ++ resolved "https://registry.yarnpkg.com/exec-buffer/-/exec-buffer-3.2.0.tgz#b1686dbd904c7cf982e652c1f5a79b1e5573082b" ++ integrity sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA== ++ dependencies: ++ execa "^0.7.0" ++ p-finally "^1.0.0" ++ pify "^3.0.0" ++ rimraf "^2.5.4" ++ tempfile "^2.0.0" ++ ++exec-sh@^0.3.2: ++ version "0.3.4" ++ resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5" ++ integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A== ++ ++execa@^0.10.0: ++ version "0.10.0" ++ resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" ++ integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw== ++ dependencies: ++ cross-spawn "^6.0.0" ++ get-stream "^3.0.0" ++ is-stream "^1.1.0" ++ npm-run-path "^2.0.0" ++ p-finally "^1.0.0" ++ signal-exit "^3.0.0" ++ strip-eof "^1.0.0" ++ ++execa@^0.7.0: ++ version "0.7.0" ++ resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" ++ integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= ++ dependencies: ++ cross-spawn "^5.0.1" ++ get-stream "^3.0.0" ++ is-stream "^1.1.0" ++ npm-run-path "^2.0.0" ++ p-finally "^1.0.0" ++ signal-exit "^3.0.0" ++ strip-eof "^1.0.0" ++ + execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" +@@ -1292,6 +3230,18 @@ execa@^1.0.0: + signal-exit "^3.0.0" + strip-eof "^1.0.0" + ++executable@^4.1.0: ++ version "4.1.1" ++ resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" ++ integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== ++ dependencies: ++ pify "^2.2.0" ++ ++exit@^0.1.2: ++ version "0.1.2" ++ resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" ++ integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= ++ + expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" +@@ -1305,6 +3255,76 @@ expand-brackets@^2.1.4: + snapdragon "^0.8.1" + to-regex "^3.0.1" + ++expand-tilde@^2.0.0, expand-tilde@^2.0.2: ++ version "2.0.2" ++ resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" ++ integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= ++ dependencies: ++ homedir-polyfill "^1.0.1" ++ ++expect@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca" ++ integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q== ++ dependencies: ++ "@jest/types" "^24.9.0" ++ ansi-styles "^3.2.0" ++ jest-get-type "^24.9.0" ++ jest-matcher-utils "^24.9.0" ++ jest-message-util "^24.9.0" ++ jest-regex-util "^24.9.0" ++ ++express@^4.17.1: ++ version "4.17.1" ++ resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" ++ integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== ++ dependencies: ++ accepts "~1.3.7" ++ array-flatten "1.1.1" ++ body-parser "1.19.0" ++ content-disposition "0.5.3" ++ content-type "~1.0.4" ++ cookie "0.4.0" ++ cookie-signature "1.0.6" ++ debug "2.6.9" ++ depd "~1.1.2" ++ encodeurl "~1.0.2" ++ escape-html "~1.0.3" ++ etag "~1.8.1" ++ finalhandler "~1.1.2" ++ fresh "0.5.2" ++ merge-descriptors "1.0.1" ++ methods "~1.1.2" ++ on-finished "~2.3.0" ++ parseurl "~1.3.3" ++ path-to-regexp "0.1.7" ++ proxy-addr "~2.0.5" ++ qs "6.7.0" ++ range-parser "~1.2.1" ++ safe-buffer "5.1.2" ++ send "0.17.1" ++ serve-static "1.14.1" ++ setprototypeof "1.1.1" ++ statuses "~1.5.0" ++ type-is "~1.6.18" ++ utils-merge "1.0.1" ++ vary "~1.1.2" ++ ++ext-list@^2.0.0: ++ version "2.2.2" ++ resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" ++ integrity sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA== ++ dependencies: ++ mime-db "^1.28.0" ++ ++ext-name@^5.0.0: ++ version "5.0.0" ++ resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6" ++ integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ== ++ dependencies: ++ ext-list "^2.0.0" ++ sort-keys-length "^1.0.0" ++ + extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" +@@ -1363,6 +3383,11 @@ fast-deep-equal@^2.0.1: + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + ++fast-diff@^1.1.2: ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" ++ integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== ++ + fast-glob@^2.2.6: + version "2.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" +@@ -1375,7 +3400,18 @@ fast-glob@^2.2.6: + merge2 "^1.2.3" + micromatch "^3.1.10" + +-fast-html-parser@^1.0.1: ++fast-glob@^3.0.3: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.0.tgz#77375a7e3e6f6fc9b18f061cddd28b8d1eec75ae" ++ integrity sha512-TrUz3THiq2Vy3bjfQUB2wNyPdGBeGmdjbzzBLhfHN4YFurYptCKwGq/TfiRavbGywFRzY6U2CdmQ1zmsY5yYaw== ++ dependencies: ++ "@nodelib/fs.stat" "^2.0.2" ++ "@nodelib/fs.walk" "^1.2.3" ++ glob-parent "^5.1.0" ++ merge2 "^1.3.0" ++ micromatch "^4.0.2" ++ ++fast-html-parser@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fast-html-parser/-/fast-html-parser-1.0.1.tgz#4ecc9683b8bb79afe11a50807b7853e79256cea2" + integrity sha1-TsyWg7i7ea/hGlCAe3hT55JWzqI= +@@ -1383,20 +3419,73 @@ fast-html-parser@^1.0.1: + apollojs "^1.3.0" + entities "^1.1.1" + +-fast-json-stable-stringify@^2.0.0: ++fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +-fast-levenshtein@~2.0.4: ++fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +-figures@^2.0.0: ++fastparse@^1.0.0: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" ++ integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== ++ ++fastq@^1.6.0: ++ version "1.6.0" ++ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" ++ integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== ++ dependencies: ++ reusify "^1.0.0" ++ ++faye-websocket@^0.10.0: ++ version "0.10.0" ++ resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" ++ integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ= ++ dependencies: ++ websocket-driver ">=0.5.1" ++ ++faye-websocket@~0.11.1: ++ version "0.11.3" ++ resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" ++ integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== ++ dependencies: ++ websocket-driver ">=0.5.1" ++ ++fb-watchman@^2.0.0: + version "2.0.0" +- resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" +- integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= ++ resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" ++ integrity sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg= ++ dependencies: ++ bser "^2.0.0" ++ ++fd-slicer@~1.1.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" ++ integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= ++ dependencies: ++ pend "~1.2.0" ++ ++figgy-pudding@^3.5.1: ++ version "3.5.1" ++ resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" ++ integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== ++ ++figures@^1.3.5: ++ version "1.7.0" ++ resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" ++ integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= ++ dependencies: ++ escape-string-regexp "^1.0.5" ++ object-assign "^4.1.0" ++ ++figures@^3.0.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" ++ integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== + dependencies: + escape-string-regexp "^1.0.5" + +@@ -1407,6 +3496,63 @@ file-entry-cache@^5.0.1: + dependencies: + flat-cache "^2.0.1" + ++file-loader@4.3.0: ++ version "4.3.0" ++ resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.3.0.tgz#780f040f729b3d18019f20605f723e844b8a58af" ++ integrity sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA== ++ dependencies: ++ loader-utils "^1.2.3" ++ schema-utils "^2.5.0" ++ ++file-type@5.2.0, file-type@^5.2.0: ++ version "5.2.0" ++ resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" ++ integrity sha1-LdvqfHP/42No365J3DOMBYwritY= ++ ++file-type@^10.4.0: ++ version "10.11.0" ++ resolved "https://registry.yarnpkg.com/file-type/-/file-type-10.11.0.tgz#2961d09e4675b9fb9a3ee6b69e9cd23f43fd1890" ++ integrity sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw== ++ ++file-type@^12.0.0: ++ version "12.4.0" ++ resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.4.0.tgz#a9a399459e1940d9f34b3973039958f1f36a565e" ++ integrity sha512-WTvyKq8yjtNmUtVAD8LGcTkvtCdJglM6ks2HTqEClm6+65XTqM6MoZYA1Vtra50DLRWLiM38fEs1y56f5VhnUA== ++ ++file-type@^3.8.0: ++ version "3.9.0" ++ resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" ++ integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= ++ ++file-type@^4.2.0, file-type@^4.3.0: ++ version "4.4.0" ++ resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" ++ integrity sha1-G2AOX8ofvcboDApwxxyNul95BsU= ++ ++file-type@^6.1.0: ++ version "6.2.0" ++ resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" ++ integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== ++ ++file-type@^8.1.0: ++ version "8.1.0" ++ resolved "https://registry.yarnpkg.com/file-type/-/file-type-8.1.0.tgz#244f3b7ef641bbe0cca196c7276e4b332399f68c" ++ integrity sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ== ++ ++filename-reserved-regex@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" ++ integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= ++ ++filenamify@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-2.1.0.tgz#88faf495fb1b47abfd612300002a16228c677ee9" ++ integrity sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA== ++ dependencies: ++ filename-reserved-regex "^2.0.0" ++ strip-outer "^1.0.0" ++ trim-repeated "^1.0.0" ++ + fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" +@@ -1417,6 +3563,50 @@ fill-range@^4.0.0: + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + ++fill-range@^7.0.1: ++ version "7.0.1" ++ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" ++ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== ++ dependencies: ++ to-regex-range "^5.0.1" ++ ++finalhandler@~1.1.2: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" ++ integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== ++ dependencies: ++ debug "2.6.9" ++ encodeurl "~1.0.2" ++ escape-html "~1.0.3" ++ on-finished "~2.3.0" ++ parseurl "~1.3.3" ++ statuses "~1.5.0" ++ unpipe "~1.0.0" ++ ++find-cache-dir@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" ++ integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== ++ dependencies: ++ commondir "^1.0.1" ++ make-dir "^2.0.0" ++ pkg-dir "^3.0.0" ++ ++find-up@^1.0.0: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" ++ integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= ++ dependencies: ++ path-exists "^2.0.0" ++ pinkie-promise "^2.0.0" ++ ++find-up@^2.0.0, find-up@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" ++ integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= ++ dependencies: ++ locate-path "^2.0.0" ++ + find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" +@@ -1424,6 +3614,23 @@ find-up@^3.0.0: + dependencies: + locate-path "^3.0.0" + ++find-versions@^3.0.0: ++ version "3.2.0" ++ resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" ++ integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww== ++ dependencies: ++ semver-regex "^2.0.0" ++ ++findup-sync@3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" ++ integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== ++ dependencies: ++ detect-file "^1.0.0" ++ is-glob "^4.0.0" ++ micromatch "^3.0.4" ++ resolve-dir "^1.0.1" ++ + flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" +@@ -1438,6 +3645,26 @@ flatted@^2.0.0: + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== + ++flatten@^1.0.2: ++ version "1.0.3" ++ resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" ++ integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== ++ ++flush-write-stream@^1.0.0: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" ++ integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== ++ dependencies: ++ inherits "^2.0.3" ++ readable-stream "^2.3.6" ++ ++follow-redirects@^1.0.0: ++ version "1.9.0" ++ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f" ++ integrity sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A== ++ dependencies: ++ debug "^3.0.0" ++ + for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" +@@ -1457,6 +3684,11 @@ form-data@~2.3.2: + combined-stream "^1.0.6" + mime-types "^2.1.12" + ++forwarded@~0.1.2: ++ version "0.1.2" ++ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" ++ integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= ++ + fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" +@@ -1464,8 +3696,26 @@ fragment-cache@^0.2.1: + dependencies: + map-cache "^0.2.2" + +-fs-extra@^7.0.0: +- version "7.0.1" ++fresh@0.5.2: ++ version "0.5.2" ++ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" ++ integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= ++ ++from2@^2.1.0, from2@^2.1.1: ++ version "2.3.0" ++ resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" ++ integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= ++ dependencies: ++ inherits "^2.0.1" ++ readable-stream "^2.0.0" ++ ++fs-constants@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" ++ integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== ++ ++fs-extra@^7.0.0: ++ version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: +@@ -1474,11 +3724,21 @@ fs-extra@^7.0.0: + universalify "^0.1.0" + + fs-minipass@^1.2.5: +- version "1.2.6" +- resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" +- integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== ++ version "1.2.7" ++ resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" ++ integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== ++ dependencies: ++ minipass "^2.6.0" ++ ++fs-write-stream-atomic@^1.0.8: ++ version "1.0.10" ++ resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" ++ integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= + dependencies: +- minipass "^2.2.1" ++ graceful-fs "^4.1.2" ++ iferr "^0.1.5" ++ imurmurhash "^0.1.4" ++ readable-stream "1 || 2" + + fs.realpath@^1.0.0: + version "1.0.0" +@@ -1517,21 +3777,46 @@ gauge@~2.7.3: + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +-get-assigned-identifiers@^1.2.0: +- version "1.2.0" +- resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" +- integrity sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ== +- + get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + ++get-caller-file@^2.0.1: ++ version "2.0.5" ++ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" ++ integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== ++ ++get-proxy@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" ++ integrity sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw== ++ dependencies: ++ npm-conf "^1.1.0" ++ ++get-stdin@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" ++ integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= ++ + get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + ++get-stream@3.0.0, get-stream@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" ++ integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= ++ ++get-stream@^2.2.0: ++ version "2.3.1" ++ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" ++ integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= ++ dependencies: ++ object-assign "^4.0.1" ++ pinkie-promise "^2.0.0" ++ + get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" +@@ -1551,6 +3836,16 @@ getpass@^0.1.1: + dependencies: + assert-plus "^1.0.0" + ++gifsicle@^4.0.0: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-4.0.1.tgz#30e1e61e3ee4884ef702641b2e98a15c2127b2e2" ++ integrity sha512-A/kiCLfDdV+ERV/UB+2O41mifd+RxH8jlRG8DMxZO84Bma/Fw0htqZ+hY2iaalLRNyUu7tYZQslqUBJxBggxbg== ++ dependencies: ++ bin-build "^3.0.0" ++ bin-wrapper "^4.0.0" ++ execa "^1.0.0" ++ logalot "^2.0.0" ++ + glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" +@@ -1559,6 +3854,13 @@ glob-parent@^3.1.0: + is-glob "^3.1.0" + path-dirname "^1.0.0" + ++glob-parent@^5.0.0, glob-parent@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" ++ integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== ++ dependencies: ++ is-glob "^4.0.1" ++ + glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" +@@ -1576,10 +3878,10 @@ glob@7.1.2: + once "^1.3.0" + path-is-absolute "^1.0.0" + +-glob@7.x, glob@^7.1.0, glob@^7.1.2, glob@^7.1.3: +- version "7.1.4" +- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" +- integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== ++glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: ++ version "7.1.6" ++ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" ++ integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" +@@ -1588,22 +3890,91 @@ glob@7.x, glob@^7.1.0, glob@^7.1.2, glob@^7.1.3: + once "^1.3.0" + path-is-absolute "^1.0.0" + +-glob@^5.0.15: +- version "5.0.15" +- resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" +- integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= ++global-modules@2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" ++ integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: +- inflight "^1.0.4" +- inherits "2" +- minimatch "2 || 3" +- once "^1.3.0" +- path-is-absolute "^1.0.0" ++ global-prefix "^3.0.0" ++ ++global-modules@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" ++ integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== ++ dependencies: ++ global-prefix "^1.0.1" ++ is-windows "^1.0.1" ++ resolve-dir "^1.0.0" ++ ++global-prefix@^1.0.1: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" ++ integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= ++ dependencies: ++ expand-tilde "^2.0.2" ++ homedir-polyfill "^1.0.1" ++ ini "^1.3.4" ++ is-windows "^1.0.1" ++ which "^1.2.14" ++ ++global-prefix@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" ++ integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== ++ dependencies: ++ ini "^1.3.5" ++ kind-of "^6.0.2" ++ which "^1.3.1" + +-globals@^11.7.0: ++globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + ++globals@^12.1.0: ++ version "12.3.0" ++ resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" ++ integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw== ++ dependencies: ++ type-fest "^0.8.1" ++ ++globby@^10.0.0: ++ version "10.0.1" ++ resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" ++ integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== ++ dependencies: ++ "@types/glob" "^7.1.1" ++ array-union "^2.1.0" ++ dir-glob "^3.0.1" ++ fast-glob "^3.0.3" ++ glob "^7.1.3" ++ ignore "^5.1.1" ++ merge2 "^1.2.3" ++ slash "^3.0.0" ++ ++globby@^6.1.0: ++ version "6.1.0" ++ resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" ++ integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= ++ dependencies: ++ array-union "^1.0.1" ++ glob "^7.0.3" ++ object-assign "^4.0.1" ++ pify "^2.0.0" ++ pinkie-promise "^2.0.0" ++ ++globby@^7.1.1: ++ version "7.1.1" ++ resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" ++ integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA= ++ dependencies: ++ array-union "^1.0.1" ++ dir-glob "^2.0.0" ++ glob "^7.1.2" ++ ignore "^3.3.5" ++ pify "^3.0.0" ++ slash "^1.0.0" ++ + globby@^9.0.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" +@@ -1618,20 +3989,95 @@ globby@^9.0.0: + pify "^4.0.1" + slash "^2.0.0" + +-graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: +- version "4.2.0" +- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" +- integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== ++good-listener@^1.2.2: ++ version "1.2.2" ++ resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" ++ integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= ++ dependencies: ++ delegate "^3.1.2" ++ ++got@^7.0.0: ++ version "7.1.0" ++ resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" ++ integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== ++ dependencies: ++ decompress-response "^3.2.0" ++ duplexer3 "^0.1.4" ++ get-stream "^3.0.0" ++ is-plain-obj "^1.1.0" ++ is-retry-allowed "^1.0.0" ++ is-stream "^1.0.0" ++ isurl "^1.0.0-alpha5" ++ lowercase-keys "^1.0.0" ++ p-cancelable "^0.3.0" ++ p-timeout "^1.1.1" ++ safe-buffer "^5.0.1" ++ timed-out "^4.0.0" ++ url-parse-lax "^1.0.0" ++ url-to-options "^1.0.1" ++ ++got@^8.3.1: ++ version "8.3.2" ++ resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" ++ integrity sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw== ++ dependencies: ++ "@sindresorhus/is" "^0.7.0" ++ cacheable-request "^2.1.1" ++ decompress-response "^3.3.0" ++ duplexer3 "^0.1.4" ++ get-stream "^3.0.0" ++ into-stream "^3.1.0" ++ is-retry-allowed "^1.1.0" ++ isurl "^1.0.0-alpha5" ++ lowercase-keys "^1.0.0" ++ mimic-response "^1.0.0" ++ p-cancelable "^0.4.0" ++ p-timeout "^2.0.1" ++ pify "^3.0.0" ++ safe-buffer "^5.1.1" ++ timed-out "^4.0.1" ++ url-parse-lax "^3.0.0" ++ url-to-options "^1.0.1" ++ ++graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.2: ++ version "4.2.3" ++ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" ++ integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== ++ ++"graceful-readlink@>= 1.0.0": ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" ++ integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= + + growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +-handlebars@^4.0.1: +- version "4.1.2" +- resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" +- integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== ++growly@^1.3.0: ++ version "1.3.0" ++ resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" ++ integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= ++ ++handle-thing@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" ++ integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ== ++ ++handlebars-loader@1.7.1: ++ version "1.7.1" ++ resolved "https://registry.yarnpkg.com/handlebars-loader/-/handlebars-loader-1.7.1.tgz#07088f09d8a559344908f7c88c68c0ffdacc555d" ++ integrity sha512-Q+Z/hDPQzU8ZTlVnAe/0T1LHABlyhL7opNcSKcQDhmUXK2ByGTqib1Z2Tfv4Ic50WqDcLFWQcOb3mhjcBRbscQ== ++ dependencies: ++ async "~0.2.10" ++ fastparse "^1.0.0" ++ loader-utils "1.0.x" ++ object-assign "^4.1.0" ++ ++handlebars@4.5.3, handlebars@^4.1.2: ++ version "4.5.3" ++ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" ++ integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA== + dependencies: + neo-async "^2.6.0" + optimist "^0.6.1" +@@ -1652,16 +4098,35 @@ har-validator@~5.1.0: + ajv "^6.5.5" + har-schema "^2.0.0" + +-has-flag@^1.0.0: +- version "1.0.0" +- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" +- integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= ++has-ansi@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" ++ integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= ++ dependencies: ++ ansi-regex "^2.0.0" + + has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + ++has-symbol-support-x@^1.4.1: ++ version "1.4.2" ++ resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" ++ integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== ++ ++has-symbols@^1.0.0, has-symbols@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" ++ integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== ++ ++has-to-string-tag-x@^1.2.0: ++ version "1.4.1" ++ resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" ++ integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== ++ dependencies: ++ has-symbol-support-x "^1.4.1" ++ + has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" +@@ -1698,7 +4163,7 @@ has-values@^1.0.0: + is-number "^3.0.0" + kind-of "^4.0.0" + +-has@^1.0.0: ++has@^1.0.0, has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== +@@ -1726,6 +4191,21 @@ he@1.1.1: + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + ++he@1.2.x: ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" ++ integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== ++ ++hex-color-regex@^1.1.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" ++ integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== ++ ++highlight.js@9.16.2: ++ version "9.16.2" ++ resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.16.2.tgz#68368d039ffe1c6211bcc07e483daf95de3e403e" ++ integrity sha512-feMUrVLZvjy0oC7FVJQcSQRqbBq9kwqnYE4+Kj9ZjbHh3g+BisiPgF49NyQbVLNdrL/qqZr3Ca9yOKwgn2i/tw== ++ + hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" +@@ -1745,7 +4225,7 @@ hoek@6.x.x: + resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c" + integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ== + +-hogan.js@^3.0.2: ++hogan.js@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd" + integrity sha1-TNnhq9QpQUbnZ55B14mHMrAse/0= +@@ -1753,10 +4233,158 @@ hogan.js@^3.0.2: + mkdirp "0.3.0" + nopt "1.0.10" + +-htmlescape@^1.1.0: +- version "1.1.1" +- resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" +- integrity sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E= ++homedir-polyfill@^1.0.1: ++ version "1.0.3" ++ resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" ++ integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== ++ dependencies: ++ parse-passwd "^1.0.0" ++ ++hosted-git-info@^2.1.4: ++ version "2.8.5" ++ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" ++ integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== ++ ++hpack.js@^2.1.6: ++ version "2.1.6" ++ resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" ++ integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= ++ dependencies: ++ inherits "^2.0.1" ++ obuf "^1.0.0" ++ readable-stream "^2.0.1" ++ wbuf "^1.1.0" ++ ++hsl-regex@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" ++ integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= ++ ++hsla-regex@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" ++ integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= ++ ++html-comment-regex@^1.1.0: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" ++ integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== ++ ++html-encoding-sniffer@^1.0.2: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" ++ integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== ++ dependencies: ++ whatwg-encoding "^1.0.1" ++ ++html-entities@^1.2.1: ++ version "1.2.1" ++ resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" ++ integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= ++ ++html-minifier@^3.2.3: ++ version "3.5.21" ++ resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" ++ integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA== ++ dependencies: ++ camel-case "3.0.x" ++ clean-css "4.2.x" ++ commander "2.17.x" ++ he "1.2.x" ++ param-case "2.1.x" ++ relateurl "0.2.x" ++ uglify-js "3.4.x" ++ ++html-webpack-plugin@3.2.0: ++ version "3.2.0" ++ resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b" ++ integrity sha1-sBq71yOsqqeze2r0SS69oD2d03s= ++ dependencies: ++ html-minifier "^3.2.3" ++ loader-utils "^0.2.16" ++ lodash "^4.17.3" ++ pretty-error "^2.0.2" ++ tapable "^1.0.0" ++ toposort "^1.0.0" ++ util.promisify "1.0.0" ++ ++htmlparser2@^3.3.0: ++ version "3.10.1" ++ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" ++ integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== ++ dependencies: ++ domelementtype "^1.3.1" ++ domhandler "^2.3.0" ++ domutils "^1.5.1" ++ entities "^1.1.1" ++ inherits "^2.0.1" ++ readable-stream "^3.1.1" ++ ++http-cache-semantics@3.8.1: ++ version "3.8.1" ++ resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" ++ integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== ++ ++http-deceiver@^1.2.7: ++ version "1.2.7" ++ resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" ++ integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= ++ ++http-errors@1.7.2: ++ version "1.7.2" ++ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" ++ integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== ++ dependencies: ++ depd "~1.1.2" ++ inherits "2.0.3" ++ setprototypeof "1.1.1" ++ statuses ">= 1.5.0 < 2" ++ toidentifier "1.0.0" ++ ++http-errors@~1.6.2: ++ version "1.6.3" ++ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" ++ integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= ++ dependencies: ++ depd "~1.1.2" ++ inherits "2.0.3" ++ setprototypeof "1.1.0" ++ statuses ">= 1.4.0 < 2" ++ ++http-errors@~1.7.2: ++ version "1.7.3" ++ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" ++ integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== ++ dependencies: ++ depd "~1.1.2" ++ inherits "2.0.4" ++ setprototypeof "1.1.1" ++ statuses ">= 1.5.0 < 2" ++ toidentifier "1.0.0" ++ ++"http-parser-js@>=0.4.0 <0.4.11": ++ version "0.4.10" ++ resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" ++ integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= ++ ++http-proxy-middleware@0.19.1: ++ version "0.19.1" ++ resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" ++ integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== ++ dependencies: ++ http-proxy "^1.17.0" ++ is-glob "^4.0.0" ++ lodash "^4.17.11" ++ micromatch "^3.1.10" ++ ++http-proxy@^1.17.0: ++ version "1.18.0" ++ resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a" ++ integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ== ++ dependencies: ++ eventemitter3 "^4.0.0" ++ follow-redirects "^1.0.0" ++ requires-port "^1.0.0" + + http-signature@~1.2.0: + version "1.2.0" +@@ -1772,30 +4400,136 @@ 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= + +-iconv-lite@^0.4.24, iconv-lite@^0.4.4: ++iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + ++icss-utils@^4.0.0, icss-utils@^4.1.1: ++ version "4.1.1" ++ resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" ++ integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== ++ dependencies: ++ postcss "^7.0.14" ++ + ieee754@^1.1.4: + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + ++iferr@^0.1.5: ++ version "0.1.5" ++ resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" ++ integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= ++ + ignore-walk@^3.0.1: +- version "3.0.1" +- resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" +- integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== ++ version "3.0.3" ++ resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" ++ integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== + dependencies: + minimatch "^3.0.4" + ++ignore@^3.3.5: ++ version "3.3.10" ++ resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" ++ integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== ++ + ignore@^4.0.3, ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + ++ignore@^5.1.1: ++ version "5.1.4" ++ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" ++ integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== ++ ++image-webpack-loader@6.0.0: ++ version "6.0.0" ++ resolved "https://registry.yarnpkg.com/image-webpack-loader/-/image-webpack-loader-6.0.0.tgz#c60ed8a1a2dc626d93cbc50f087668a3f2cb2d02" ++ integrity sha512-H5qZ+DH88A4mW9CPJpa7VH8B2dxLbzqiMH+BQYtMw8v2jaFwZPQOS/NfkSaJMz76dsi/uw+0LY4uHR1iK6hq8g== ++ dependencies: ++ imagemin "^7.0.0" ++ loader-utils "^1.2.3" ++ object-assign "^4.1.1" ++ optionalDependencies: ++ imagemin-gifsicle "^6.0.1" ++ imagemin-mozjpeg "^8.0.0" ++ imagemin-optipng "^7.0.0" ++ imagemin-pngquant "^8.0.0" ++ imagemin-svgo "^7.0.0" ++ imagemin-webp "^5.1.0" ++ ++imagemin-gifsicle@^6.0.1: ++ version "6.0.1" ++ resolved "https://registry.yarnpkg.com/imagemin-gifsicle/-/imagemin-gifsicle-6.0.1.tgz#6abad4e95566d52e5a104aba1c24b4f3b48581b3" ++ integrity sha512-kuu47c6iKDQ6R9J10xCwL0lgs0+sMz3LRHqRcJ2CRBWdcNmo3T5hUaM8hSZfksptZXJLGKk8heSAvwtSdB1Fng== ++ dependencies: ++ exec-buffer "^3.0.0" ++ gifsicle "^4.0.0" ++ is-gif "^3.0.0" ++ ++imagemin-mozjpeg@^8.0.0: ++ version "8.0.0" ++ resolved "https://registry.yarnpkg.com/imagemin-mozjpeg/-/imagemin-mozjpeg-8.0.0.tgz#d2ca4e8c982c7c6eda55069af89dee4c1cebcdfd" ++ integrity sha512-+EciPiIjCb8JWjQNr1q8sYWYf7GDCNDxPYnkD11TNIjjWNzaV+oTg4DpOPQjl5ZX/KRCPMEgS79zLYAQzLitIA== ++ dependencies: ++ execa "^1.0.0" ++ is-jpg "^2.0.0" ++ mozjpeg "^6.0.0" ++ ++imagemin-optipng@^7.0.0: ++ version "7.1.0" ++ resolved "https://registry.yarnpkg.com/imagemin-optipng/-/imagemin-optipng-7.1.0.tgz#2225c82c35e5c29b7fa98d4f9ecee1161a68e888" ++ integrity sha512-JNORTZ6j6untH7e5gF4aWdhDCxe3ODsSLKs/f7Grewy3ebZpl1ZsU+VUTPY4rzeHgaFA8GSWOoA8V2M3OixWZQ== ++ dependencies: ++ exec-buffer "^3.0.0" ++ is-png "^2.0.0" ++ optipng-bin "^6.0.0" ++ ++imagemin-pngquant@^8.0.0: ++ version "8.0.0" ++ resolved "https://registry.yarnpkg.com/imagemin-pngquant/-/imagemin-pngquant-8.0.0.tgz#bf7a41d850c6998f2475c54058ab1db9c516385d" ++ integrity sha512-PVq0diOxO+Zyq/zlMCz2Pfu6mVLHgiT1GpW702OwVlnej+NhS6ZQegYi3OFEDW8d7GxouyR5e8R+t53SMciOeg== ++ dependencies: ++ execa "^1.0.0" ++ is-png "^2.0.0" ++ is-stream "^2.0.0" ++ ow "^0.13.2" ++ pngquant-bin "^5.0.0" ++ ++imagemin-svgo@^7.0.0: ++ version "7.0.0" ++ resolved "https://registry.yarnpkg.com/imagemin-svgo/-/imagemin-svgo-7.0.0.tgz#a22d0a5917a0d0f37e436932c30f5e000fa91b1c" ++ integrity sha512-+iGJFaPIMx8TjFW6zN+EkOhlqcemdL7F3N3Y0wODvV2kCUBuUtZK7DRZc1+Zfu4U2W/lTMUyx2G8YMOrZntIWg== ++ dependencies: ++ is-svg "^3.0.0" ++ svgo "^1.0.5" ++ ++imagemin-webp@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/imagemin-webp/-/imagemin-webp-5.1.0.tgz#ddb1307ad97aff97293c5a600e384e40c07f68a7" ++ integrity sha512-BsPTpobgbDPFBBsI3UflnU/cpIVa15qInEDBcYBw16qI/6XiB4vDF/dGp9l4aM3pfFDDYqR0mANMcKpBD7wbCw== ++ dependencies: ++ cwebp-bin "^5.0.0" ++ exec-buffer "^3.0.0" ++ is-cwebp-readable "^2.0.1" ++ ++imagemin@^7.0.0: ++ version "7.0.1" ++ resolved "https://registry.yarnpkg.com/imagemin/-/imagemin-7.0.1.tgz#f6441ca647197632e23db7d971fffbd530c87dbf" ++ integrity sha512-33AmZ+xjZhg2JMCe+vDf6a9mzWukE7l+wAtesjE7KyteqqKjzxv7aVQeWnul1Ve26mWvEQqyPwl0OctNBfSR9w== ++ dependencies: ++ file-type "^12.0.0" ++ globby "^10.0.0" ++ graceful-fs "^4.2.2" ++ junk "^3.1.0" ++ make-dir "^3.0.0" ++ p-pipe "^3.0.0" ++ replace-ext "^1.0.0" ++ + import-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" +@@ -1812,9 +4546,9 @@ import-fresh@^2.0.0: + resolve-from "^3.0.0" + + import-fresh@^3.0.0: +- version "3.1.0" +- resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" +- integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== ++ version "3.2.1" ++ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" ++ integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" +@@ -1826,11 +4560,41 @@ import-from@^2.1.0: + dependencies: + resolve-from "^3.0.0" + ++import-lazy@^3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" ++ integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ== ++ ++import-local@2.0.0, import-local@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" ++ integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== ++ dependencies: ++ pkg-dir "^3.0.0" ++ resolve-cwd "^2.0.0" ++ + imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + ++indent-string@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" ++ integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= ++ dependencies: ++ repeating "^2.0.0" ++ ++indexes-of@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" ++ integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= ++ ++infer-owner@^1.0.3: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" ++ integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== ++ + inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" +@@ -1839,7 +4603,7 @@ inflight@^1.0.4: + once "^1.3.0" + wrappy "1" + +-inherits@2, 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.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== +@@ -1854,58 +4618,93 @@ inherits@2.0.3: + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +-ini@~1.3.0: ++ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +-inline-source-map@~0.6.0: +- version "0.6.2" +- resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" +- integrity sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU= +- dependencies: +- source-map "~0.5.3" +- +-inquirer@^6.2.2: +- version "6.5.0" +- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42" +- integrity sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA== ++inquirer@^7.0.0: ++ version "7.0.0" ++ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.0.tgz#9e2b032dde77da1db5db804758b8fea3a970519a" ++ integrity sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ== + dependencies: +- ansi-escapes "^3.2.0" ++ ansi-escapes "^4.2.1" + chalk "^2.4.2" +- cli-cursor "^2.1.0" ++ cli-cursor "^3.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" +- figures "^2.0.0" +- lodash "^4.17.12" +- mute-stream "0.0.7" ++ figures "^3.0.0" ++ lodash "^4.17.15" ++ mute-stream "0.0.8" + run-async "^2.2.0" + rxjs "^6.4.0" +- string-width "^2.1.0" ++ string-width "^4.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + +-insert-module-globals@^7.0.0: +- version "7.2.0" +- resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.0.tgz#ec87e5b42728479e327bd5c5c71611ddfb4752ba" +- integrity sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw== +- dependencies: +- JSONStream "^1.0.3" +- acorn-node "^1.5.2" +- combine-source-map "^0.8.0" +- concat-stream "^1.6.1" +- is-buffer "^1.1.0" +- path-is-absolute "^1.0.1" +- process "~0.11.0" +- through2 "^2.0.0" +- undeclared-identifiers "^1.1.2" +- xtend "^4.0.0" ++internal-ip@^4.3.0: ++ version "4.3.0" ++ resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" ++ integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== ++ dependencies: ++ default-gateway "^4.2.0" ++ ipaddr.js "^1.9.0" ++ ++interpret@1.2.0: ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" ++ integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== ++ ++into-stream@^3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" ++ integrity sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY= ++ dependencies: ++ from2 "^2.1.1" ++ p-is-promise "^1.1.0" ++ ++invariant@^2.2.4: ++ version "2.2.4" ++ resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" ++ integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== ++ dependencies: ++ loose-envify "^1.0.0" + + invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + ++ip-regex@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" ++ integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= ++ ++ip@^1.1.0, ip@^1.1.5: ++ version "1.1.5" ++ resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" ++ integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= ++ ++ipaddr.js@1.9.0: ++ version "1.9.0" ++ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" ++ integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== ++ ++ipaddr.js@^1.9.0: ++ version "1.9.1" ++ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" ++ integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== ++ ++is-absolute-url@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" ++ integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= ++ ++is-absolute-url@^3.0.3: ++ version "3.0.3" ++ resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" ++ integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== ++ + is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" +@@ -1920,11 +4719,21 @@ is-accessor-descriptor@^1.0.0: + dependencies: + kind-of "^6.0.0" + ++is-arguments@^1.0.4: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" ++ integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== ++ + is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + ++is-arrayish@^0.3.1: ++ version "0.3.2" ++ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" ++ integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== ++ + is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" +@@ -1932,11 +4741,42 @@ is-binary-path@^1.0.0: + dependencies: + binary-extensions "^1.0.0" + +-is-buffer@^1.1.0, is-buffer@^1.1.5: ++is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + ++is-callable@^1.1.4: ++ version "1.1.4" ++ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" ++ integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== ++ ++is-ci@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" ++ integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== ++ dependencies: ++ ci-info "^2.0.0" ++ ++is-color-stop@^1.0.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" ++ integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= ++ dependencies: ++ css-color-names "^0.0.4" ++ hex-color-regex "^1.1.0" ++ hsl-regex "^1.0.0" ++ hsla-regex "^1.0.0" ++ rgb-regex "^1.0.1" ++ rgba-regex "^1.0.0" ++ ++is-cwebp-readable@^2.0.1: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/is-cwebp-readable/-/is-cwebp-readable-2.0.1.tgz#afb93b0c0abd0a25101016ae33aea8aedf926d26" ++ integrity sha1-r7k7DAq9CiUQEBauM66ort+SbSY= ++ dependencies: ++ file-type "^4.3.0" ++ + is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" +@@ -1951,6 +4791,11 @@ is-data-descriptor@^1.0.0: + dependencies: + kind-of "^6.0.0" + ++is-date-object@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" ++ integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= ++ + is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" +@@ -1991,6 +4836,13 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + ++is-finite@^1.0.0: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" ++ integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= ++ dependencies: ++ number-is-nan "^1.0.0" ++ + is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" +@@ -2003,6 +4855,23 @@ is-fullwidth-code-point@^2.0.0: + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + ++is-fullwidth-code-point@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" ++ integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== ++ ++is-generator-fn@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" ++ integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== ++ ++is-gif@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/is-gif/-/is-gif-3.0.0.tgz#c4be60b26a301d695bb833b20d9b5d66c6cf83b1" ++ integrity sha512-IqJ/jlbw5WJSNfwQ/lHEDXF8rxhRgF6ythk2oiEvhpG29F704eX9NO6TvPfMiq9DrbwgcEDnETYNcZDPewQoVw== ++ dependencies: ++ file-type "^10.4.0" ++ + is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" +@@ -2010,13 +4879,23 @@ is-glob@^3.1.0: + dependencies: + is-extglob "^2.1.0" + +-is-glob@^4.0.0: ++is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + ++is-jpg@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/is-jpg/-/is-jpg-2.0.0.tgz#2e1997fa6e9166eaac0242daae443403e4ef1d97" ++ integrity sha1-LhmX+m6RZuqsAkLarkQ0A+TvHZc= ++ ++is-natural-number@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" ++ integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= ++ + is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" +@@ -2024,6 +4903,45 @@ is-number@^3.0.0: + dependencies: + kind-of "^3.0.2" + ++is-number@^7.0.0: ++ version "7.0.0" ++ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" ++ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== ++ ++is-obj@^1.0.0: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" ++ integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= ++ ++is-object@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" ++ integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= ++ ++is-path-cwd@^2.0.0: ++ version "2.2.0" ++ resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" ++ integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== ++ ++is-path-in-cwd@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" ++ integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== ++ dependencies: ++ is-path-inside "^2.1.0" ++ ++is-path-inside@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" ++ integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== ++ dependencies: ++ path-is-inside "^1.0.2" ++ ++is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" ++ integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= ++ + is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" +@@ -2031,27 +4949,78 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: + dependencies: + isobject "^3.0.1" + ++is-png@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/is-png/-/is-png-2.0.0.tgz#ee8cbc9e9b050425cedeeb4a6fb74a649b0a4a8d" ++ integrity sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g== ++ + is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + +-is-stream@^1.1.0: ++is-regex@^1.0.4: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" ++ integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= ++ dependencies: ++ has "^1.0.1" ++ ++is-resolvable@^1.0.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" ++ integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== ++ ++is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" ++ integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== ++ ++is-stream@^1.0.0, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + ++is-stream@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" ++ integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== ++ ++is-svg@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" ++ integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== ++ dependencies: ++ html-comment-regex "^1.1.0" ++ ++is-symbol@^1.0.2: ++ version "1.0.3" ++ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" ++ integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== ++ dependencies: ++ has-symbols "^1.0.1" ++ + is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +-is-windows@^1.0.2: ++is-utf8@^0.2.0: ++ version "0.2.1" ++ resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" ++ integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= ++ ++is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +-isarray@1.0.0, isarray@~1.0.0: ++is-wsl@^1.1.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" ++ integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= ++ ++isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +@@ -2085,25 +5054,58 @@ isstream@~0.1.2: + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +-istanbul@^0.4.5: +- version "0.4.5" +- resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" +- integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= +- dependencies: +- abbrev "1.0.x" +- async "1.x" +- escodegen "1.8.x" +- esprima "2.7.x" +- glob "^5.0.15" +- handlebars "^4.0.1" +- js-yaml "3.x" +- mkdirp "0.5.x" +- nopt "3.x" +- once "1.x" +- resolve "1.1.x" +- supports-color "^3.1.0" +- which "^1.1.1" +- wordwrap "^1.0.0" ++istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.5: ++ version "2.0.5" ++ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" ++ integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== ++ ++istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.3.0: ++ version "3.3.0" ++ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" ++ integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== ++ dependencies: ++ "@babel/generator" "^7.4.0" ++ "@babel/parser" "^7.4.3" ++ "@babel/template" "^7.4.0" ++ "@babel/traverse" "^7.4.3" ++ "@babel/types" "^7.4.0" ++ istanbul-lib-coverage "^2.0.5" ++ semver "^6.0.0" ++ ++istanbul-lib-report@^2.0.4: ++ version "2.0.8" ++ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33" ++ integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ== ++ dependencies: ++ istanbul-lib-coverage "^2.0.5" ++ make-dir "^2.1.0" ++ supports-color "^6.1.0" ++ ++istanbul-lib-source-maps@^3.0.1: ++ version "3.0.6" ++ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" ++ integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== ++ dependencies: ++ debug "^4.1.1" ++ istanbul-lib-coverage "^2.0.5" ++ make-dir "^2.1.0" ++ rimraf "^2.6.3" ++ source-map "^0.6.1" ++ ++istanbul-reports@^2.2.6: ++ version "2.2.6" ++ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" ++ integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== ++ dependencies: ++ handlebars "^4.1.2" ++ ++isurl@^1.0.0-alpha5: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" ++ integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== ++ dependencies: ++ has-to-string-tag-x "^1.2.0" ++ is-object "^1.0.1" + + jacoco-parse@^2.x: + version "2.0.1" +@@ -2113,6 +5115,360 @@ jacoco-parse@^2.x: + mocha "^5.2.0" + xml2js "^0.4.9" + ++jest-changed-files@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.9.0.tgz#08d8c15eb79a7fa3fc98269bc14b451ee82f8039" ++ integrity sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg== ++ dependencies: ++ "@jest/types" "^24.9.0" ++ execa "^1.0.0" ++ throat "^4.0.0" ++ ++jest-cli@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.9.0.tgz#ad2de62d07472d419c6abc301fc432b98b10d2af" ++ integrity sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg== ++ dependencies: ++ "@jest/core" "^24.9.0" ++ "@jest/test-result" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ chalk "^2.0.1" ++ exit "^0.1.2" ++ import-local "^2.0.0" ++ is-ci "^2.0.0" ++ jest-config "^24.9.0" ++ jest-util "^24.9.0" ++ jest-validate "^24.9.0" ++ prompts "^2.0.1" ++ realpath-native "^1.1.0" ++ yargs "^13.3.0" ++ ++jest-config@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.9.0.tgz#fb1bbc60c73a46af03590719efa4825e6e4dd1b5" ++ integrity sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ== ++ dependencies: ++ "@babel/core" "^7.1.0" ++ "@jest/test-sequencer" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ babel-jest "^24.9.0" ++ chalk "^2.0.1" ++ glob "^7.1.1" ++ jest-environment-jsdom "^24.9.0" ++ jest-environment-node "^24.9.0" ++ jest-get-type "^24.9.0" ++ jest-jasmine2 "^24.9.0" ++ jest-regex-util "^24.3.0" ++ jest-resolve "^24.9.0" ++ jest-util "^24.9.0" ++ jest-validate "^24.9.0" ++ micromatch "^3.1.10" ++ pretty-format "^24.9.0" ++ realpath-native "^1.1.0" ++ ++jest-diff@^24.3.0, jest-diff@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da" ++ integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ== ++ dependencies: ++ chalk "^2.0.1" ++ diff-sequences "^24.9.0" ++ jest-get-type "^24.9.0" ++ pretty-format "^24.9.0" ++ ++jest-docblock@^24.3.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2" ++ integrity sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA== ++ dependencies: ++ detect-newline "^2.1.0" ++ ++jest-each@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.9.0.tgz#eb2da602e2a610898dbc5f1f6df3ba86b55f8b05" ++ integrity sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog== ++ dependencies: ++ "@jest/types" "^24.9.0" ++ chalk "^2.0.1" ++ jest-get-type "^24.9.0" ++ jest-util "^24.9.0" ++ pretty-format "^24.9.0" ++ ++jest-environment-jsdom@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz#4b0806c7fc94f95edb369a69cc2778eec2b7375b" ++ integrity sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA== ++ dependencies: ++ "@jest/environment" "^24.9.0" ++ "@jest/fake-timers" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ jest-mock "^24.9.0" ++ jest-util "^24.9.0" ++ jsdom "^11.5.1" ++ ++jest-environment-node@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.9.0.tgz#333d2d2796f9687f2aeebf0742b519f33c1cbfd3" ++ integrity sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA== ++ dependencies: ++ "@jest/environment" "^24.9.0" ++ "@jest/fake-timers" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ jest-mock "^24.9.0" ++ jest-util "^24.9.0" ++ ++jest-get-type@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" ++ integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q== ++ ++jest-haste-map@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.9.0.tgz#b38a5d64274934e21fa417ae9a9fbeb77ceaac7d" ++ integrity sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ== ++ dependencies: ++ "@jest/types" "^24.9.0" ++ anymatch "^2.0.0" ++ fb-watchman "^2.0.0" ++ graceful-fs "^4.1.15" ++ invariant "^2.2.4" ++ jest-serializer "^24.9.0" ++ jest-util "^24.9.0" ++ jest-worker "^24.9.0" ++ micromatch "^3.1.10" ++ sane "^4.0.3" ++ walker "^1.0.7" ++ optionalDependencies: ++ fsevents "^1.2.7" ++ ++jest-jasmine2@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz#1f7b1bd3242c1774e62acabb3646d96afc3be6a0" ++ integrity sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw== ++ dependencies: ++ "@babel/traverse" "^7.1.0" ++ "@jest/environment" "^24.9.0" ++ "@jest/test-result" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ chalk "^2.0.1" ++ co "^4.6.0" ++ expect "^24.9.0" ++ is-generator-fn "^2.0.0" ++ jest-each "^24.9.0" ++ jest-matcher-utils "^24.9.0" ++ jest-message-util "^24.9.0" ++ jest-runtime "^24.9.0" ++ jest-snapshot "^24.9.0" ++ jest-util "^24.9.0" ++ pretty-format "^24.9.0" ++ throat "^4.0.0" ++ ++jest-leak-detector@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz#b665dea7c77100c5c4f7dfcb153b65cf07dcf96a" ++ integrity sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA== ++ dependencies: ++ jest-get-type "^24.9.0" ++ pretty-format "^24.9.0" ++ ++jest-matcher-utils@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073" ++ integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA== ++ dependencies: ++ chalk "^2.0.1" ++ jest-diff "^24.9.0" ++ jest-get-type "^24.9.0" ++ pretty-format "^24.9.0" ++ ++jest-message-util@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3" ++ integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw== ++ dependencies: ++ "@babel/code-frame" "^7.0.0" ++ "@jest/test-result" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ "@types/stack-utils" "^1.0.1" ++ chalk "^2.0.1" ++ micromatch "^3.1.10" ++ slash "^2.0.0" ++ stack-utils "^1.0.1" ++ ++jest-mock@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.9.0.tgz#c22835541ee379b908673ad51087a2185c13f1c6" ++ integrity sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w== ++ dependencies: ++ "@jest/types" "^24.9.0" ++ ++jest-pnp-resolver@^1.2.1: ++ version "1.2.1" ++ resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" ++ integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== ++ ++jest-regex-util@^24.3.0, jest-regex-util@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636" ++ integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA== ++ ++jest-resolve-dependencies@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz#ad055198959c4cfba8a4f066c673a3f0786507ab" ++ integrity sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g== ++ dependencies: ++ "@jest/types" "^24.9.0" ++ jest-regex-util "^24.3.0" ++ jest-snapshot "^24.9.0" ++ ++jest-resolve@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.9.0.tgz#dff04c7687af34c4dd7e524892d9cf77e5d17321" ++ integrity sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ== ++ dependencies: ++ "@jest/types" "^24.9.0" ++ browser-resolve "^1.11.3" ++ chalk "^2.0.1" ++ jest-pnp-resolver "^1.2.1" ++ realpath-native "^1.1.0" ++ ++jest-runner@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.9.0.tgz#574fafdbd54455c2b34b4bdf4365a23857fcdf42" ++ integrity sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg== ++ dependencies: ++ "@jest/console" "^24.7.1" ++ "@jest/environment" "^24.9.0" ++ "@jest/test-result" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ chalk "^2.4.2" ++ exit "^0.1.2" ++ graceful-fs "^4.1.15" ++ jest-config "^24.9.0" ++ jest-docblock "^24.3.0" ++ jest-haste-map "^24.9.0" ++ jest-jasmine2 "^24.9.0" ++ jest-leak-detector "^24.9.0" ++ jest-message-util "^24.9.0" ++ jest-resolve "^24.9.0" ++ jest-runtime "^24.9.0" ++ jest-util "^24.9.0" ++ jest-worker "^24.6.0" ++ source-map-support "^0.5.6" ++ throat "^4.0.0" ++ ++jest-runtime@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.9.0.tgz#9f14583af6a4f7314a6a9d9f0226e1a781c8e4ac" ++ integrity sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw== ++ dependencies: ++ "@jest/console" "^24.7.1" ++ "@jest/environment" "^24.9.0" ++ "@jest/source-map" "^24.3.0" ++ "@jest/transform" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ "@types/yargs" "^13.0.0" ++ chalk "^2.0.1" ++ exit "^0.1.2" ++ glob "^7.1.3" ++ graceful-fs "^4.1.15" ++ jest-config "^24.9.0" ++ jest-haste-map "^24.9.0" ++ jest-message-util "^24.9.0" ++ jest-mock "^24.9.0" ++ jest-regex-util "^24.3.0" ++ jest-resolve "^24.9.0" ++ jest-snapshot "^24.9.0" ++ jest-util "^24.9.0" ++ jest-validate "^24.9.0" ++ realpath-native "^1.1.0" ++ slash "^2.0.0" ++ strip-bom "^3.0.0" ++ yargs "^13.3.0" ++ ++jest-serializer@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.9.0.tgz#e6d7d7ef96d31e8b9079a714754c5d5c58288e73" ++ integrity sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ== ++ ++jest-snapshot@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.9.0.tgz#ec8e9ca4f2ec0c5c87ae8f925cf97497b0e951ba" ++ integrity sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew== ++ dependencies: ++ "@babel/types" "^7.0.0" ++ "@jest/types" "^24.9.0" ++ chalk "^2.0.1" ++ expect "^24.9.0" ++ jest-diff "^24.9.0" ++ jest-get-type "^24.9.0" ++ jest-matcher-utils "^24.9.0" ++ jest-message-util "^24.9.0" ++ jest-resolve "^24.9.0" ++ mkdirp "^0.5.1" ++ natural-compare "^1.4.0" ++ pretty-format "^24.9.0" ++ semver "^6.2.0" ++ ++jest-util@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162" ++ integrity sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg== ++ dependencies: ++ "@jest/console" "^24.9.0" ++ "@jest/fake-timers" "^24.9.0" ++ "@jest/source-map" "^24.9.0" ++ "@jest/test-result" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ callsites "^3.0.0" ++ chalk "^2.0.1" ++ graceful-fs "^4.1.15" ++ is-ci "^2.0.0" ++ mkdirp "^0.5.1" ++ slash "^2.0.0" ++ source-map "^0.6.0" ++ ++jest-validate@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.9.0.tgz#0775c55360d173cd854e40180756d4ff52def8ab" ++ integrity sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ== ++ dependencies: ++ "@jest/types" "^24.9.0" ++ camelcase "^5.3.1" ++ chalk "^2.0.1" ++ jest-get-type "^24.9.0" ++ leven "^3.1.0" ++ pretty-format "^24.9.0" ++ ++jest-watcher@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.9.0.tgz#4b56e5d1ceff005f5b88e528dc9afc8dd4ed2b3b" ++ integrity sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw== ++ dependencies: ++ "@jest/test-result" "^24.9.0" ++ "@jest/types" "^24.9.0" ++ "@types/yargs" "^13.0.0" ++ ansi-escapes "^3.0.0" ++ chalk "^2.0.1" ++ jest-util "^24.9.0" ++ string-length "^2.0.0" ++ ++jest-worker@^24.6.0, jest-worker@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" ++ integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== ++ dependencies: ++ merge-stream "^2.0.0" ++ supports-color "^6.1.0" ++ ++jest@24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171" ++ integrity sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw== ++ dependencies: ++ import-local "^2.0.0" ++ jest-cli "^24.9.0" ++ + joi@^13.x: + version "13.7.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-13.7.0.tgz#cfd85ebfe67e8a1900432400b4d03bbd93fb879f" +@@ -2122,12 +5478,12 @@ joi@^13.x: + isemail "3.x.x" + topo "3.x.x" + +-js-tokens@^4.0.0: ++"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +-js-yaml@3.x, js-yaml@^3.13.0, js-yaml@^3.13.1: ++js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== +@@ -2140,7 +5496,49 @@ jsbn@~0.1.0: + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +-json-parse-better-errors@^1.0.1: ++jsdom@^11.5.1: ++ version "11.12.0" ++ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" ++ integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw== ++ dependencies: ++ abab "^2.0.0" ++ acorn "^5.5.3" ++ acorn-globals "^4.1.0" ++ array-equal "^1.0.0" ++ cssom ">= 0.3.2 < 0.4.0" ++ cssstyle "^1.0.0" ++ data-urls "^1.0.0" ++ domexception "^1.0.1" ++ escodegen "^1.9.1" ++ html-encoding-sniffer "^1.0.2" ++ left-pad "^1.3.0" ++ nwsapi "^2.0.7" ++ parse5 "4.0.0" ++ pn "^1.1.0" ++ request "^2.87.0" ++ request-promise-native "^1.0.5" ++ sax "^1.2.4" ++ symbol-tree "^3.2.2" ++ tough-cookie "^2.3.4" ++ w3c-hr-time "^1.0.1" ++ webidl-conversions "^4.0.2" ++ whatwg-encoding "^1.0.3" ++ whatwg-mimetype "^2.1.0" ++ whatwg-url "^6.4.1" ++ ws "^5.2.0" ++ xml-name-validator "^3.0.0" ++ ++jsesc@^2.5.1: ++ version "2.5.2" ++ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" ++ integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== ++ ++json-buffer@3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" ++ integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= ++ ++json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +@@ -2160,18 +5558,35 @@ json-stable-stringify-without-jsonify@^1.0.1: + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +-json-stable-stringify@~0.0.0: +- version "0.0.1" +- resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" +- integrity sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U= +- dependencies: +- jsonify "~0.0.0" +- + json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + ++json3@^3.3.2: ++ version "3.3.3" ++ resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" ++ integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== ++ ++json5@2.x, json5@^2.1.0: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" ++ integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== ++ dependencies: ++ minimist "^1.2.0" ++ ++json5@^0.5.0: ++ version "0.5.1" ++ resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" ++ integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= ++ ++json5@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" ++ integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== ++ dependencies: ++ minimist "^1.2.0" ++ + jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" +@@ -2179,16 +5594,6 @@ jsonfile@^4.0.0: + optionalDependencies: + graceful-fs "^4.1.6" + +-jsonify@~0.0.0: +- version "0.0.0" +- resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" +- integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= +- +-jsonparse@^1.2.0: +- version "1.3.1" +- resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" +- integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= +- + jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" +@@ -2199,6 +5604,23 @@ jsprim@^1.2.2: + json-schema "0.2.3" + verror "1.10.0" + ++junk@^3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" ++ integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== ++ ++keyv@3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" ++ integrity sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA== ++ dependencies: ++ json-buffer "3.0.0" ++ ++killable@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" ++ integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== ++ + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" +@@ -2223,13 +5645,10 @@ kind-of@^6.0.0, kind-of@^6.0.2: + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +-labeled-stream-splicer@^2.0.0: +- version "2.0.2" +- resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz#42a41a16abcd46fd046306cf4f2c3576fffb1c21" +- integrity sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw== +- dependencies: +- inherits "^2.0.1" +- stream-splicer "^2.0.0" ++kleur@^3.0.3: ++ version "3.0.3" ++ resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" ++ integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + + lcid@^2.0.0: + version "2.0.0" +@@ -2243,6 +5662,16 @@ lcov-parse@^1.x: + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" + integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= + ++left-pad@^1.3.0: ++ version "1.3.0" ++ resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" ++ integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== ++ ++leven@^3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" ++ integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== ++ + levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" +@@ -2251,6 +5680,78 @@ levn@^0.3.0, levn@~0.3.0: + prelude-ls "~1.1.2" + type-check "~0.3.2" + ++load-json-file@^1.0.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" ++ integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= ++ dependencies: ++ graceful-fs "^4.1.2" ++ parse-json "^2.2.0" ++ pify "^2.0.0" ++ pinkie-promise "^2.0.0" ++ strip-bom "^2.0.0" ++ ++load-json-file@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" ++ integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= ++ dependencies: ++ graceful-fs "^4.1.2" ++ parse-json "^2.2.0" ++ pify "^2.0.0" ++ strip-bom "^3.0.0" ++ ++load-json-file@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" ++ integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= ++ dependencies: ++ graceful-fs "^4.1.2" ++ parse-json "^4.0.0" ++ pify "^3.0.0" ++ strip-bom "^3.0.0" ++ ++loader-runner@^2.4.0: ++ version "2.4.0" ++ resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" ++ integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== ++ ++loader-utils@1.0.x: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.0.4.tgz#13f56197f1523a305891248b4c7244540848426c" ++ integrity sha1-E/Vhl/FSOjBYkSSLTHJEVAhIQmw= ++ dependencies: ++ big.js "^3.1.3" ++ emojis-list "^2.0.0" ++ json5 "^0.5.0" ++ ++loader-utils@1.2.3, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: ++ version "1.2.3" ++ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" ++ integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== ++ dependencies: ++ big.js "^5.2.2" ++ emojis-list "^2.0.0" ++ json5 "^1.0.1" ++ ++loader-utils@^0.2.16: ++ version "0.2.17" ++ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" ++ integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= ++ dependencies: ++ big.js "^3.1.3" ++ emojis-list "^2.0.0" ++ json5 "^0.5.0" ++ object-assign "^4.0.1" ++ ++locate-path@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" ++ integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= ++ dependencies: ++ p-locate "^2.0.0" ++ path-exists "^3.0.0" ++ + locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" +@@ -2259,15 +5760,50 @@ locate-path@^3.0.0: + p-locate "^3.0.0" + path-exists "^3.0.0" + +-lodash.memoize@~3.0.3: +- version "3.0.4" +- resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" +- integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= ++lodash._reinterpolate@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" ++ integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= ++ ++lodash.memoize@4.x, lodash.memoize@^4.1.2: ++ version "4.1.2" ++ resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" ++ integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + +-lodash@4.17.14, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.4: +- version "4.17.14" +- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" +- integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== ++lodash.sortby@^4.7.0: ++ version "4.7.0" ++ resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" ++ integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= ++ ++lodash.template@^4.5.0: ++ version "4.5.0" ++ resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" ++ integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== ++ dependencies: ++ lodash._reinterpolate "^3.0.0" ++ lodash.templatesettings "^4.0.0" ++ ++lodash.templatesettings@^4.0.0: ++ version "4.2.0" ++ resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" ++ integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== ++ dependencies: ++ lodash._reinterpolate "^3.0.0" ++ ++lodash.unescape@4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" ++ integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= ++ ++lodash.uniq@^4.5.0: ++ version "4.5.0" ++ resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" ++ integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= ++ ++lodash@4.17.15, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.4: ++ version "4.17.15" ++ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" ++ integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + + log-driver@^1.x: + version "1.2.7" +@@ -2281,6 +5817,118 @@ log-symbols@^2.2.0: + dependencies: + chalk "^2.0.1" + ++logalot@^2.0.0, logalot@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/logalot/-/logalot-2.1.0.tgz#5f8e8c90d304edf12530951a5554abb8c5e3f552" ++ integrity sha1-X46MkNME7fElMJUaVVSruMXj9VI= ++ dependencies: ++ figures "^1.3.5" ++ squeak "^1.0.0" ++ ++loglevel@^1.6.4: ++ version "1.6.6" ++ resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.6.tgz#0ee6300cc058db6b3551fa1c4bf73b83bb771312" ++ integrity sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ== ++ ++longest@^1.0.0: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" ++ integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= ++ ++loose-envify@^1.0.0: ++ version "1.4.0" ++ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" ++ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== ++ dependencies: ++ js-tokens "^3.0.0 || ^4.0.0" ++ ++loud-rejection@^1.0.0: ++ version "1.6.0" ++ resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" ++ integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= ++ dependencies: ++ currently-unhandled "^0.4.1" ++ signal-exit "^3.0.0" ++ ++lower-case@^1.1.1: ++ version "1.1.4" ++ resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" ++ integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= ++ ++lowercase-keys@1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" ++ integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY= ++ ++lowercase-keys@^1.0.0: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" ++ integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== ++ ++lpad-align@^1.0.1: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/lpad-align/-/lpad-align-1.1.2.tgz#21f600ac1c3095c3c6e497ee67271ee08481fe9e" ++ integrity sha1-IfYArBwwlcPG5JfuZyce4ISB/p4= ++ dependencies: ++ get-stdin "^4.0.1" ++ indent-string "^2.1.0" ++ longest "^1.0.0" ++ meow "^3.3.0" ++ ++lru-cache@^4.0.1: ++ version "4.1.5" ++ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" ++ integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== ++ dependencies: ++ pseudomap "^1.0.2" ++ yallist "^2.1.2" ++ ++lru-cache@^5.1.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" ++ integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== ++ dependencies: ++ yallist "^3.0.2" ++ ++make-dir@^1.0.0, make-dir@^1.2.0: ++ version "1.3.0" ++ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" ++ integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== ++ dependencies: ++ pify "^3.0.0" ++ ++make-dir@^2.0.0, make-dir@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" ++ integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== ++ dependencies: ++ pify "^4.0.1" ++ semver "^5.6.0" ++ ++make-dir@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.0.tgz#1b5f39f6b9270ed33f9f054c5c0f84304989f801" ++ integrity sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw== ++ dependencies: ++ semver "^6.0.0" ++ ++make-error@1.x, make-error@^1.1.1: ++ version "1.3.5" ++ resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" ++ integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== ++ ++makeerror@1.0.x: ++ version "1.0.11" ++ resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" ++ integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= ++ dependencies: ++ tmpl "1.0.x" ++ ++mamacro@^0.0.3: ++ version "0.0.3" ++ resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" ++ integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== ++ + map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" +@@ -2293,6 +5941,11 @@ map-cache@^0.2.2: + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + ++map-obj@^1.0.0, map-obj@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" ++ integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= ++ + map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" +@@ -2309,6 +5962,16 @@ md5.js@^1.3.4: + inherits "^2.0.1" + safe-buffer "^5.1.2" + ++mdn-data@2.0.4: ++ version "2.0.4" ++ resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" ++ integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== ++ ++media-typer@0.3.0: ++ version "0.3.0" ++ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" ++ integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= ++ + mem@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" +@@ -2318,17 +5981,59 @@ mem@^4.0.0: + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" + +-merge2@^1.2.3: +- version "1.2.3" +- resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" +- integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== ++memory-fs@^0.4.0, memory-fs@^0.4.1: ++ version "0.4.1" ++ resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" ++ integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= ++ dependencies: ++ errno "^0.1.3" ++ readable-stream "^2.0.1" ++ ++memory-fs@^0.5.0: ++ version "0.5.0" ++ resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" ++ integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== ++ dependencies: ++ errno "^0.1.3" ++ readable-stream "^2.0.1" ++ ++meow@^3.3.0: ++ version "3.7.0" ++ resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" ++ integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= ++ dependencies: ++ camelcase-keys "^2.0.0" ++ decamelize "^1.1.2" ++ loud-rejection "^1.0.0" ++ map-obj "^1.0.1" ++ minimist "^1.1.3" ++ normalize-package-data "^2.3.4" ++ object-assign "^4.0.1" ++ read-pkg-up "^1.0.1" ++ redent "^1.0.0" ++ trim-newlines "^1.0.0" ++ ++merge-descriptors@1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" ++ integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +-merge@^1.2.1: +- version "1.2.1" +- resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" +- integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== ++merge-stream@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" ++ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== ++ ++merge2@^1.2.3, merge2@^1.3.0: ++ version "1.3.0" ++ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" ++ integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== ++ ++methods@~1.1.2: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" ++ integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +-micromatch@^3.1.10, micromatch@^3.1.4: ++micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== +@@ -2347,6 +6052,14 @@ micromatch@^3.1.10, micromatch@^3.1.4: + snapdragon "^0.8.1" + to-regex "^3.0.2" + ++micromatch@^4.0.0, micromatch@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" ++ integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== ++ dependencies: ++ braces "^3.0.1" ++ picomatch "^2.0.5" ++ + miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" +@@ -2355,28 +6068,48 @@ miller-rabin@^4.0.0: + bn.js "^4.0.0" + brorand "^1.0.1" + +-mime-db@1.40.0: +- version "1.40.0" +- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" +- integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== ++mime-db@1.42.0, "mime-db@>= 1.40.0 < 2", mime-db@^1.28.0: ++ version "1.42.0" ++ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" ++ integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== + +-mime-types@^2.1.12, mime-types@~2.1.19: +- version "2.1.24" +- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" +- integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== ++mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: ++ version "2.1.25" ++ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437" ++ integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== + dependencies: +- mime-db "1.40.0" ++ mime-db "1.42.0" + +-mimic-fn@^1.0.0: +- version "1.2.0" +- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" +- integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== ++mime@1.6.0: ++ version "1.6.0" ++ resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" ++ integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== ++ ++mime@^2.4.4: ++ version "2.4.4" ++ resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" ++ integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== + +-mimic-fn@^2.0.0: ++mimic-fn@^2.0.0, mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + ++mimic-response@^1.0.0: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" ++ integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== ++ ++mini-css-extract-plugin@0.8.0: ++ version "0.8.0" ++ resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz#81d41ec4fe58c713a96ad7c723cdb2d0bd4d70e1" ++ integrity sha512-MNpRGbNA52q6U92i0qbVpQNsgk7LExy41MdAlG84FeytfDOtRIf/mCHdEgG8rpTKOaNKiqUnZdlptF469hxqOw== ++ dependencies: ++ loader-utils "^1.1.0" ++ normalize-url "1.9.1" ++ schema-utils "^1.0.0" ++ webpack-sources "^1.1.0" ++ + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" +@@ -2387,7 +6120,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +-"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4: ++minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== +@@ -2399,7 +6132,7 @@ minimist@0.0.8: + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +-minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0: ++minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +@@ -2409,20 +6142,36 @@ minimist@~0.0.1: + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= + +-minipass@^2.2.1, minipass@^2.3.5: +- version "2.3.5" +- resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" +- integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== ++minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: ++ version "2.9.0" ++ resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" ++ integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + + minizlib@^1.2.1: +- version "1.2.1" +- resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" +- integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== ++ version "1.3.3" ++ resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" ++ integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: +- minipass "^2.2.1" ++ minipass "^2.9.0" ++ ++mississippi@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" ++ integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== ++ dependencies: ++ concat-stream "^1.5.0" ++ duplexify "^3.4.2" ++ end-of-stream "^1.1.0" ++ flush-write-stream "^1.0.0" ++ from2 "^2.1.0" ++ parallel-transform "^1.1.0" ++ pump "^3.0.0" ++ pumpify "^1.3.3" ++ stream-each "^1.1.0" ++ through2 "^2.0.0" + + mixin-deep@^1.2.0: + version "1.3.2" +@@ -2437,14 +6186,14 @@ mkdirp@0.3.0: + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" + integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4= + +-mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1: ++mkdirp@0.5.1, mkdirp@0.x, 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" + +-mocha@5.2.0, mocha@^5.2.0: ++mocha@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== +@@ -2461,41 +6210,59 @@ mocha@5.2.0, mocha@^5.2.0: + mkdirp "0.5.1" + supports-color "5.4.0" + +-module-deps@^6.0.0: +- version "6.2.1" +- resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-6.2.1.tgz#cfe558784060e926824f474b4e647287837cda50" +- integrity sha512-UnEn6Ah36Tu4jFiBbJVUtt0h+iXqxpLqDvPS8nllbw5RZFmNJ1+Mz5BjYnM9ieH80zyxHkARGLnMIHlPK5bu6A== +- dependencies: +- JSONStream "^1.0.3" +- browser-resolve "^1.7.0" +- cached-path-relative "^1.0.2" +- concat-stream "~1.6.0" +- defined "^1.0.0" +- detective "^5.0.2" +- duplexer2 "^0.1.2" +- inherits "^2.0.1" +- parents "^1.0.0" +- readable-stream "^2.0.2" +- resolve "^1.4.0" +- stream-combiner2 "^1.1.1" +- subarg "^1.0.0" +- through2 "^2.0.0" +- xtend "^4.0.0" ++move-concurrently@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" ++ integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= ++ dependencies: ++ aproba "^1.1.1" ++ copy-concurrently "^1.0.0" ++ fs-write-stream-atomic "^1.0.8" ++ mkdirp "^0.5.1" ++ rimraf "^2.5.4" ++ run-queue "^1.0.3" ++ ++mozjpeg@^6.0.0: ++ version "6.0.1" ++ resolved "https://registry.yarnpkg.com/mozjpeg/-/mozjpeg-6.0.1.tgz#56969dddb5741ef2bcb1af066cae21e61a91a27b" ++ integrity sha512-9Z59pJMi8ni+IUvSH5xQwK5tNLw7p3dwDNCZ3o1xE+of3G5Hc/yOz6Ue/YuLiBXU3ZB5oaHPURyPdqfBX/QYJA== ++ dependencies: ++ bin-build "^3.0.0" ++ bin-wrapper "^4.0.0" ++ logalot "^2.1.0" + + ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + ++ms@2.1.1: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" ++ integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== ++ + ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +-mute-stream@0.0.7: +- version "0.0.7" +- resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" +- integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= ++multicast-dns-service-types@^1.1.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" ++ integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= ++ ++multicast-dns@^6.0.1: ++ version "6.2.3" ++ resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" ++ integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== ++ dependencies: ++ dns-packet "^1.3.1" ++ thunky "^1.0.2" ++ ++mute-stream@0.0.8: ++ version "0.0.8" ++ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" ++ integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + + nan@^2.12.1: + version "2.14.0" +@@ -2533,7 +6300,12 @@ needle@^2.2.1: + iconv-lite "^0.4.4" + sax "^1.2.4" + +-neo-async@^2.6.0: ++negotiator@0.6.2: ++ version "0.6.2" ++ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" ++ integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== ++ ++neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" + integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== +@@ -2543,6 +6315,68 @@ nice-try@^1.0.4: + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + ++no-case@^2.2.0: ++ version "2.3.2" ++ resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" ++ integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== ++ dependencies: ++ lower-case "^1.1.1" ++ ++node-forge@0.9.0: ++ version "0.9.0" ++ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" ++ integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== ++ ++node-int64@^0.4.0: ++ version "0.4.0" ++ resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" ++ integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= ++ ++node-libs-browser@^2.2.1: ++ version "2.2.1" ++ resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" ++ integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== ++ dependencies: ++ assert "^1.1.1" ++ browserify-zlib "^0.2.0" ++ buffer "^4.3.0" ++ console-browserify "^1.1.0" ++ constants-browserify "^1.0.0" ++ crypto-browserify "^3.11.0" ++ domain-browser "^1.1.1" ++ events "^3.0.0" ++ https-browserify "^1.0.0" ++ os-browserify "^0.3.0" ++ path-browserify "0.0.1" ++ process "^0.11.10" ++ punycode "^1.2.4" ++ querystring-es3 "^0.2.0" ++ readable-stream "^2.3.3" ++ stream-browserify "^2.0.1" ++ stream-http "^2.7.2" ++ string_decoder "^1.0.0" ++ timers-browserify "^2.0.4" ++ tty-browserify "0.0.0" ++ url "^0.11.0" ++ util "^0.11.0" ++ vm-browserify "^1.0.1" ++ ++node-modules-regexp@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" ++ integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= ++ ++node-notifier@^5.4.2: ++ version "5.4.3" ++ resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50" ++ integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q== ++ dependencies: ++ growly "^1.3.0" ++ is-wsl "^1.1.0" ++ semver "^5.5.0" ++ shellwords "^0.1.1" ++ which "^1.3.0" ++ + node-pre-gyp@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" +@@ -2559,12 +6393,12 @@ node-pre-gyp@^0.12.0: + semver "^5.3.0" + tar "^4" + +-node-releases@^1.1.25: +- version "1.1.25" +- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.25.tgz#0c2d7dbc7fed30fbe02a9ee3007b8c90bf0133d3" +- integrity sha512-fI5BXuk83lKEoZDdH3gRhtsNgh05/wZacuXkgbiYkceE7+QIMXOg98n9ZV7mz27B+kFHnqHcUpscZZlGRSmTpQ== ++node-releases@^1.1.40: ++ version "1.1.41" ++ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.41.tgz#57674a82a37f812d18e3b26118aefaf53a00afed" ++ integrity sha512-+IctMa7wIs8Cfsa8iYzeaLTFwv5Y4r5jZud+4AnfymzeEXKBCavFX0KBgzVaPVqf0ywa6PrO8/b+bPqdwjGBSg== + dependencies: +- semver "^5.3.0" ++ semver "^6.3.0" + + nopt@1.0.10: + version "1.0.10" +@@ -2573,14 +6407,7 @@ nopt@1.0.10: + dependencies: + abbrev "1" + +-nopt@3.x: +- version "3.0.6" +- resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" +- integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= +- dependencies: +- abbrev "1" +- +-nopt@^4.0.1: ++nopt@4.0.1, nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= +@@ -2588,6 +6415,16 @@ nopt@^4.0.1: + abbrev "1" + osenv "^0.1.4" + ++normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: ++ version "2.5.0" ++ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" ++ integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== ++ dependencies: ++ hosted-git-info "^2.1.4" ++ resolve "^1.10.0" ++ semver "2 || 3 || 4 || 5" ++ validate-npm-package-license "^3.0.1" ++ + normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" +@@ -2605,15 +6442,47 @@ normalize-range@^0.1.2: + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= + ++normalize-url@1.9.1: ++ version "1.9.1" ++ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" ++ integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= ++ dependencies: ++ object-assign "^4.0.1" ++ prepend-http "^1.0.0" ++ query-string "^4.1.0" ++ sort-keys "^1.0.0" ++ ++normalize-url@2.0.1: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" ++ integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== ++ dependencies: ++ prepend-http "^2.0.0" ++ query-string "^5.0.1" ++ sort-keys "^2.0.0" ++ ++normalize-url@^3.0.0: ++ version "3.3.0" ++ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" ++ integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== ++ + npm-bundled@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" + integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + ++npm-conf@^1.1.0: ++ version "1.1.3" ++ resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" ++ integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== ++ dependencies: ++ config-chain "^1.1.11" ++ pify "^3.0.0" ++ + npm-packlist@^1.1.6: +- version "1.4.4" +- resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" +- integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== ++ version "1.4.6" ++ resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.6.tgz#53ba3ed11f8523079f1457376dd379ee4ea42ff4" ++ integrity sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" +@@ -2635,6 +6504,13 @@ npmlog@^4.0.2: + gauge "~2.7.3" + set-blocking "~2.0.0" + ++nth-check@^1.0.2, nth-check@~1.0.1: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" ++ integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== ++ dependencies: ++ boolbase "~1.0.0" ++ + num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" +@@ -2645,12 +6521,17 @@ number-is-nan@^1.0.0: + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + ++nwsapi@^2.0.7: ++ version "2.2.0" ++ resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" ++ integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== ++ + oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +-object-assign@^4.1.0, object-assign@^4.1.1: ++object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= +@@ -2664,6 +6545,21 @@ object-copy@^0.1.0: + define-property "^0.2.5" + kind-of "^3.0.3" + ++object-inspect@^1.6.0: ++ version "1.7.0" ++ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" ++ integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== ++ ++object-is@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" ++ integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= ++ ++object-keys@^1.0.12, object-keys@^1.1.1: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" ++ integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== ++ + object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" +@@ -2671,6 +6567,14 @@ object-visit@^1.0.0: + dependencies: + isobject "^3.0.0" + ++object.getownpropertydescriptors@^2.0.3: ++ version "2.0.3" ++ resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" ++ integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= ++ dependencies: ++ define-properties "^1.1.2" ++ es-abstract "^1.5.1" ++ + object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" +@@ -2678,19 +6582,53 @@ object.pick@^1.3.0: + dependencies: + isobject "^3.0.1" + +-once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: ++object.values@^1.1.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" ++ integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== ++ dependencies: ++ define-properties "^1.1.3" ++ es-abstract "^1.12.0" ++ function-bind "^1.1.1" ++ has "^1.0.3" ++ ++obuf@^1.0.0, obuf@^1.1.2: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" ++ integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== ++ ++on-finished@~2.3.0: ++ version "2.3.0" ++ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" ++ integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= ++ dependencies: ++ ee-first "1.1.1" ++ ++on-headers@~1.0.2: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" ++ integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== ++ ++once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +-onetime@^2.0.0: +- version "2.0.1" +- resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" +- integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= ++onetime@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" ++ integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== ++ dependencies: ++ mimic-fn "^2.1.0" ++ ++opn@^5.5.0: ++ version "5.5.0" ++ resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" ++ integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== + dependencies: +- mimic-fn "^1.0.0" ++ is-wsl "^1.1.0" + + optimist@^0.6.1: + version "0.6.1" +@@ -2700,29 +6638,52 @@ optimist@^0.6.1: + minimist "~0.0.1" + wordwrap "~0.0.2" + +-optionator@^0.8.1, optionator@^0.8.2: +- version "0.8.2" +- resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" +- integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= ++optionator@^0.8.1, optionator@^0.8.3: ++ version "0.8.3" ++ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" ++ integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" +- fast-levenshtein "~2.0.4" ++ fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" +- wordwrap "~1.0.0" ++ word-wrap "~1.2.3" ++ ++optipng-bin@^6.0.0: ++ version "6.0.0" ++ resolved "https://registry.yarnpkg.com/optipng-bin/-/optipng-bin-6.0.0.tgz#376120fa79d5e71eee2f524176efdd3a5eabd316" ++ integrity sha512-95bB4y8IaTsa/8x6QH4bLUuyvyOoGBCLDA7wOgDL8UFqJpSUh1Hob8JRJhit+wC1ZLN3tQ7mFt7KuBj0x8F2Wg== ++ dependencies: ++ bin-build "^3.0.0" ++ bin-wrapper "^4.0.0" ++ logalot "^2.0.0" ++ ++original@^1.0.0: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" ++ integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== ++ dependencies: ++ url-parse "^1.4.3" + +-os-browserify@~0.3.0: ++os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + ++os-filter-obj@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/os-filter-obj/-/os-filter-obj-2.0.0.tgz#1c0b62d5f3a2442749a2d139e6dddee6e81d8d16" ++ integrity sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg== ++ dependencies: ++ arch "^2.1.0" ++ + os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +-os-locale@^3.0.0: ++os-locale@^3.0.0, os-locale@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== +@@ -2744,28 +6705,85 @@ osenv@^0.1.4: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + ++ow@^0.13.2: ++ version "0.13.2" ++ resolved "https://registry.yarnpkg.com/ow/-/ow-0.13.2.tgz#375e76d3d3f928a8dfcf0cd0b9c921cb62e469a0" ++ integrity sha512-9wvr+q+ZTDRvXDjL6eDOdFe5WUl/wa5sntf9kAolxqSpkBqaIObwLgFCGXSJASFw+YciXnOVtDWpxXa9cqV94A== ++ dependencies: ++ type-fest "^0.5.1" ++ ++p-cancelable@^0.3.0: ++ version "0.3.0" ++ resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" ++ integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== ++ ++p-cancelable@^0.4.0: ++ version "0.4.1" ++ resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" ++ integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ== ++ + p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + ++p-each-series@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71" ++ integrity sha1-kw89Et0fUOdDRFeiLNbwSsatf3E= ++ dependencies: ++ p-reduce "^1.0.0" ++ ++p-event@^1.0.0: ++ version "1.3.0" ++ resolved "https://registry.yarnpkg.com/p-event/-/p-event-1.3.0.tgz#8e6b4f4f65c72bc5b6fe28b75eda874f96a4a085" ++ integrity sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU= ++ dependencies: ++ p-timeout "^1.1.1" ++ ++p-event@^2.1.0: ++ version "2.3.1" ++ resolved "https://registry.yarnpkg.com/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6" ++ integrity sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA== ++ dependencies: ++ p-timeout "^2.0.1" ++ + p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + ++p-is-promise@^1.1.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" ++ integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4= ++ + p-is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== + +-p-limit@^2.0.0: +- version "2.2.0" +- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" +- integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== ++p-limit@^1.1.0: ++ version "1.3.0" ++ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" ++ integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== ++ dependencies: ++ p-try "^1.0.0" ++ ++p-limit@^2.0.0, p-limit@^2.2.1: ++ version "2.2.1" ++ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" ++ integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + dependencies: + p-try "^2.0.0" + ++p-locate@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" ++ integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= ++ dependencies: ++ p-limit "^1.1.0" ++ + p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" +@@ -2773,6 +6791,54 @@ p-locate@^3.0.0: + dependencies: + p-limit "^2.0.0" + ++p-map-series@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" ++ integrity sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco= ++ dependencies: ++ p-reduce "^1.0.0" ++ ++p-map@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" ++ integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== ++ ++p-pipe@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.0.0.tgz#ab1fb87c0b8dd79b3bb03a8a23680fc9d054e132" ++ integrity sha512-gwwdRFmaxsT3IU+Tl3vYKVRdjfhg8Bbdjw7B+E0y6F7Yz6l+eaQLn0BRmGMXIhcPDONPtOkMoNwx1etZh4zPJA== ++ ++p-reduce@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" ++ integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= ++ ++p-retry@^3.0.1: ++ version "3.0.1" ++ resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" ++ integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== ++ dependencies: ++ retry "^0.12.0" ++ ++p-timeout@^1.1.1: ++ version "1.2.1" ++ resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" ++ integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= ++ dependencies: ++ p-finally "^1.0.0" ++ ++p-timeout@^2.0.1: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" ++ integrity sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA== ++ dependencies: ++ p-finally "^1.0.0" ++ ++p-try@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" ++ integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= ++ + p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" +@@ -2783,6 +6849,22 @@ pako@~1.0.5: + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" + integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== + ++parallel-transform@^1.1.0: ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" ++ integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== ++ dependencies: ++ cyclist "^1.0.1" ++ inherits "^2.0.3" ++ readable-stream "^2.1.5" ++ ++param-case@2.1.x: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" ++ integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= ++ dependencies: ++ no-case "^2.2.0" ++ + parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" +@@ -2790,17 +6872,10 @@ parent-module@^1.0.0: + dependencies: + callsites "^3.0.0" + +-parents@^1.0.0, parents@^1.0.1: +- version "1.0.1" +- resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" +- integrity sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E= +- dependencies: +- path-platform "~0.11.15" +- + parse-asn1@^5.0.0: +- version "5.1.4" +- resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" +- integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== ++ version "5.1.5" ++ resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" ++ integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" +@@ -2809,6 +6884,13 @@ parse-asn1@^5.0.0: + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + ++parse-json@^2.2.0: ++ version "2.2.0" ++ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" ++ integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= ++ dependencies: ++ error-ex "^1.2.0" ++ + parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" +@@ -2817,12 +6899,27 @@ parse-json@^4.0.0: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + ++parse-passwd@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" ++ integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= ++ ++parse5@4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" ++ integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== ++ ++parseurl@~1.3.2, parseurl@~1.3.3: ++ version "1.3.3" ++ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" ++ integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== ++ + pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +-path-browserify@~0.0.0: ++path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== +@@ -2832,12 +6929,19 @@ path-dirname@^1.0.0: + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + ++path-exists@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" ++ integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= ++ dependencies: ++ pinkie-promise "^2.0.0" ++ + path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +-path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: ++path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +@@ -2857,10 +6961,26 @@ path-parse@^1.0.6: + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +-path-platform@~0.11.15: +- version "0.11.15" +- resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" +- integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I= ++path-to-regexp@0.1.7: ++ version "0.1.7" ++ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" ++ integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= ++ ++path-type@^1.0.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" ++ integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= ++ dependencies: ++ graceful-fs "^4.1.2" ++ pify "^2.0.0" ++ pinkie-promise "^2.0.0" ++ ++path-type@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" ++ integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= ++ dependencies: ++ pify "^2.0.0" + + path-type@^3.0.0: + version "3.0.0" +@@ -2869,6 +6989,11 @@ path-type@^3.0.0: + dependencies: + pify "^3.0.0" + ++path-type@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" ++ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== ++ + pbkdf2@^3.0.3: + version "3.0.17" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" +@@ -2880,12 +7005,22 @@ pbkdf2@^3.0.3: + safe-buffer "^5.0.1" + sha.js "^2.4.8" + ++pend@~1.2.0: ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" ++ integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= ++ + performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +-pify@^2.3.0: ++picomatch@^2.0.5: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" ++ integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA== ++ ++pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= +@@ -2900,12 +7035,94 @@ pify@^4.0.1: + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + ++pinkie-promise@^2.0.0: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" ++ integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= ++ dependencies: ++ pinkie "^2.0.0" ++ ++pinkie@^2.0.0: ++ version "2.0.4" ++ resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" ++ integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= ++ ++pirates@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" ++ integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== ++ dependencies: ++ node-modules-regexp "^1.0.0" ++ ++pkg-dir@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" ++ integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= ++ dependencies: ++ find-up "^2.1.0" ++ ++pkg-dir@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" ++ integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== ++ dependencies: ++ find-up "^3.0.0" ++ ++pn@^1.1.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" ++ integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== ++ ++pngquant-bin@^5.0.0: ++ version "5.0.2" ++ resolved "https://registry.yarnpkg.com/pngquant-bin/-/pngquant-bin-5.0.2.tgz#6f34f3e89c9722a72bbc509062b40f1b17cda460" ++ integrity sha512-OLdT+4JZx5BqE1CFJkrvomYV0aSsv6x2Bba+aWaVc0PMfWlE+ZByNKYAdKeIqsM4uvW1HOSEHnf8KcOnykPNxA== ++ dependencies: ++ bin-build "^3.0.0" ++ bin-wrapper "^4.0.1" ++ execa "^0.10.0" ++ logalot "^2.0.0" ++ ++portfinder@^1.0.25: ++ version "1.0.25" ++ resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" ++ integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg== ++ dependencies: ++ async "^2.6.2" ++ debug "^3.1.1" ++ mkdirp "^0.5.1" ++ + posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +-postcss-cli@^6.1.2: ++postcss-attribute-case-insensitive@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.1.tgz#b2a721a0d279c2f9103a36331c88981526428cc7" ++ integrity sha512-L2YKB3vF4PetdTIthQVeT+7YiSzMoNMLLYxPXXppOOP7NoazEAy45sh2LvJ8leCQjfBcfkYQs8TtCcQjeZTp8A== ++ dependencies: ++ postcss "^7.0.2" ++ postcss-selector-parser "^5.0.0" ++ ++postcss-browser-comments@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-browser-comments/-/postcss-browser-comments-3.0.0.tgz#1248d2d935fb72053c8e1f61a84a57292d9f65e9" ++ integrity sha512-qfVjLfq7HFd2e0HW4s1dvU8X080OZdG46fFbIBFjW7US7YPDcWfRvdElvwMJr2LI6hMmD+7LnH2HcmXTs+uOig== ++ dependencies: ++ postcss "^7" ++ ++postcss-calc@^7.0.1: ++ version "7.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" ++ integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== ++ dependencies: ++ css-unit-converter "^1.1.1" ++ postcss "^7.0.5" ++ postcss-selector-parser "^5.0.0-rc.4" ++ postcss-value-parser "^3.3.1" ++ ++postcss-cli@6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/postcss-cli/-/postcss-cli-6.1.3.tgz#a9eec3e9cde4aaa90170546baf706f8af6f8ecec" + integrity sha512-eieqJU+OR1OFc/lQqMsDmROTJpoMZFvoAQ+82utBQ8/8qGMTfH9bBSPsTdsagYA8uvNzxHw2I2cNSSJkLAGhvw== +@@ -2923,6 +7140,205 @@ postcss-cli@^6.1.2: + read-cache "^1.0.0" + yargs "^12.0.1" + ++postcss-color-functional-notation@^2.0.1: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" ++ integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== ++ dependencies: ++ postcss "^7.0.2" ++ postcss-values-parser "^2.0.0" ++ ++postcss-color-gray@^5.0.0: ++ version "5.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" ++ integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== ++ dependencies: ++ "@csstools/convert-colors" "^1.4.0" ++ postcss "^7.0.5" ++ postcss-values-parser "^2.0.0" ++ ++postcss-color-hex-alpha@^5.0.3: ++ version "5.0.3" ++ resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" ++ integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw== ++ dependencies: ++ postcss "^7.0.14" ++ postcss-values-parser "^2.0.1" ++ ++postcss-color-mod-function@^3.0.3: ++ version "3.0.3" ++ resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" ++ integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== ++ dependencies: ++ "@csstools/convert-colors" "^1.4.0" ++ postcss "^7.0.2" ++ postcss-values-parser "^2.0.0" ++ ++postcss-color-rebeccapurple@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" ++ integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== ++ dependencies: ++ postcss "^7.0.2" ++ postcss-values-parser "^2.0.0" ++ ++postcss-colormin@^4.0.3: ++ version "4.0.3" ++ resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" ++ integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== ++ dependencies: ++ browserslist "^4.0.0" ++ color "^3.0.0" ++ has "^1.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-convert-values@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" ++ integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== ++ dependencies: ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-custom-media@^7.0.8: ++ version "7.0.8" ++ resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" ++ integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg== ++ dependencies: ++ postcss "^7.0.14" ++ ++postcss-custom-properties@^8.0.11: ++ version "8.0.11" ++ resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" ++ integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA== ++ dependencies: ++ postcss "^7.0.17" ++ postcss-values-parser "^2.0.1" ++ ++postcss-custom-selectors@^5.1.2: ++ version "5.1.2" ++ resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" ++ integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== ++ dependencies: ++ postcss "^7.0.2" ++ postcss-selector-parser "^5.0.0-rc.3" ++ ++postcss-dir-pseudo-class@^5.0.0: ++ version "5.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" ++ integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== ++ dependencies: ++ postcss "^7.0.2" ++ postcss-selector-parser "^5.0.0-rc.3" ++ ++postcss-discard-comments@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" ++ integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== ++ dependencies: ++ postcss "^7.0.0" ++ ++postcss-discard-duplicates@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" ++ integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== ++ dependencies: ++ postcss "^7.0.0" ++ ++postcss-discard-empty@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" ++ integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== ++ dependencies: ++ postcss "^7.0.0" ++ ++postcss-discard-overridden@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" ++ integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== ++ dependencies: ++ postcss "^7.0.0" ++ ++postcss-double-position-gradients@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" ++ integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== ++ dependencies: ++ postcss "^7.0.5" ++ postcss-values-parser "^2.0.0" ++ ++postcss-env-function@^2.0.2: ++ version "2.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" ++ integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== ++ dependencies: ++ postcss "^7.0.2" ++ postcss-values-parser "^2.0.0" ++ ++postcss-focus-visible@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" ++ integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== ++ dependencies: ++ postcss "^7.0.2" ++ ++postcss-focus-within@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" ++ integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== ++ dependencies: ++ postcss "^7.0.2" ++ ++postcss-font-variant@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz#71dd3c6c10a0d846c5eda07803439617bbbabacc" ++ integrity sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg== ++ dependencies: ++ postcss "^7.0.2" ++ ++postcss-gap-properties@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" ++ integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== ++ dependencies: ++ postcss "^7.0.2" ++ ++postcss-image-set-function@^3.0.1: ++ version "3.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" ++ integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== ++ dependencies: ++ postcss "^7.0.2" ++ postcss-values-parser "^2.0.0" ++ ++postcss-import@12.0.1: ++ version "12.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-12.0.1.tgz#cf8c7ab0b5ccab5649024536e565f841928b7153" ++ integrity sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw== ++ dependencies: ++ postcss "^7.0.1" ++ postcss-value-parser "^3.2.3" ++ read-cache "^1.0.0" ++ resolve "^1.1.7" ++ ++postcss-initial@^3.0.0: ++ version "3.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d" ++ integrity sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA== ++ dependencies: ++ lodash.template "^4.5.0" ++ postcss "^7.0.2" ++ ++postcss-lab-function@^2.0.1: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" ++ integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== ++ dependencies: ++ "@csstools/convert-colors" "^1.4.0" ++ postcss "^7.0.2" ++ postcss-values-parser "^2.0.0" ++ + postcss-load-config@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003" +@@ -2931,6 +7347,333 @@ postcss-load-config@^2.0.0: + cosmiconfig "^5.0.0" + import-cwd "^2.0.0" + ++postcss-loader@3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" ++ integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA== ++ dependencies: ++ loader-utils "^1.1.0" ++ postcss "^7.0.0" ++ postcss-load-config "^2.0.0" ++ schema-utils "^1.0.0" ++ ++postcss-logical@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" ++ integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== ++ dependencies: ++ postcss "^7.0.2" ++ ++postcss-media-minmax@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" ++ integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== ++ dependencies: ++ postcss "^7.0.2" ++ ++postcss-merge-longhand@^4.0.11: ++ version "4.0.11" ++ resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" ++ integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== ++ dependencies: ++ css-color-names "0.0.4" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ stylehacks "^4.0.0" ++ ++postcss-merge-rules@^4.0.3: ++ version "4.0.3" ++ resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" ++ integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== ++ dependencies: ++ browserslist "^4.0.0" ++ caniuse-api "^3.0.0" ++ cssnano-util-same-parent "^4.0.0" ++ postcss "^7.0.0" ++ postcss-selector-parser "^3.0.0" ++ vendors "^1.0.0" ++ ++postcss-minify-font-values@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" ++ integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== ++ dependencies: ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-minify-gradients@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" ++ integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== ++ dependencies: ++ cssnano-util-get-arguments "^4.0.0" ++ is-color-stop "^1.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-minify-params@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" ++ integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== ++ dependencies: ++ alphanum-sort "^1.0.0" ++ browserslist "^4.0.0" ++ cssnano-util-get-arguments "^4.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ uniqs "^2.0.0" ++ ++postcss-minify-selectors@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" ++ integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== ++ dependencies: ++ alphanum-sort "^1.0.0" ++ has "^1.0.0" ++ postcss "^7.0.0" ++ postcss-selector-parser "^3.0.0" ++ ++postcss-modules-extract-imports@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" ++ integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== ++ dependencies: ++ postcss "^7.0.5" ++ ++postcss-modules-local-by-default@^3.0.2: ++ version "3.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" ++ integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ== ++ dependencies: ++ icss-utils "^4.1.1" ++ postcss "^7.0.16" ++ postcss-selector-parser "^6.0.2" ++ postcss-value-parser "^4.0.0" ++ ++postcss-modules-scope@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz#ad3f5bf7856114f6fcab901b0502e2a2bc39d4eb" ++ integrity sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A== ++ dependencies: ++ postcss "^7.0.6" ++ postcss-selector-parser "^6.0.0" ++ ++postcss-modules-values@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" ++ integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== ++ dependencies: ++ icss-utils "^4.0.0" ++ postcss "^7.0.6" ++ ++postcss-nesting@^7.0.0: ++ version "7.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" ++ integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg== ++ dependencies: ++ postcss "^7.0.2" ++ ++postcss-normalize-charset@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" ++ integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== ++ dependencies: ++ postcss "^7.0.0" ++ ++postcss-normalize-display-values@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" ++ integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== ++ dependencies: ++ cssnano-util-get-match "^4.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-normalize-positions@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" ++ integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== ++ dependencies: ++ cssnano-util-get-arguments "^4.0.0" ++ has "^1.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-normalize-repeat-style@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" ++ integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== ++ dependencies: ++ cssnano-util-get-arguments "^4.0.0" ++ cssnano-util-get-match "^4.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-normalize-string@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" ++ integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== ++ dependencies: ++ has "^1.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-normalize-timing-functions@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" ++ integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== ++ dependencies: ++ cssnano-util-get-match "^4.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-normalize-unicode@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" ++ integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== ++ dependencies: ++ browserslist "^4.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-normalize-url@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" ++ integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== ++ dependencies: ++ is-absolute-url "^2.0.0" ++ normalize-url "^3.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-normalize-whitespace@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" ++ integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== ++ dependencies: ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-normalize@8.0.1: ++ version "8.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-normalize/-/postcss-normalize-8.0.1.tgz#90e80a7763d7fdf2da6f2f0f82be832ce4f66776" ++ integrity sha512-rt9JMS/m9FHIRroDDBGSMsyW1c0fkvOJPy62ggxSHUldJO7B195TqFMqIf+lY5ezpDcYOV4j86aUp3/XbxzCCQ== ++ dependencies: ++ "@csstools/normalize.css" "^10.1.0" ++ browserslist "^4.6.2" ++ postcss "^7.0.17" ++ postcss-browser-comments "^3.0.0" ++ sanitize.css "^10.0.0" ++ ++postcss-ordered-values@^4.1.2: ++ version "4.1.2" ++ resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" ++ integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== ++ dependencies: ++ cssnano-util-get-arguments "^4.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-overflow-shorthand@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" ++ integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== ++ dependencies: ++ postcss "^7.0.2" ++ ++postcss-page-break@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" ++ integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== ++ dependencies: ++ postcss "^7.0.2" ++ ++postcss-place@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" ++ integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== ++ dependencies: ++ postcss "^7.0.2" ++ postcss-values-parser "^2.0.0" ++ ++postcss-preset-env@6.7.0: ++ version "6.7.0" ++ resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" ++ integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg== ++ dependencies: ++ autoprefixer "^9.6.1" ++ browserslist "^4.6.4" ++ caniuse-lite "^1.0.30000981" ++ css-blank-pseudo "^0.1.4" ++ css-has-pseudo "^0.10.0" ++ css-prefers-color-scheme "^3.1.1" ++ cssdb "^4.4.0" ++ postcss "^7.0.17" ++ postcss-attribute-case-insensitive "^4.0.1" ++ postcss-color-functional-notation "^2.0.1" ++ postcss-color-gray "^5.0.0" ++ postcss-color-hex-alpha "^5.0.3" ++ postcss-color-mod-function "^3.0.3" ++ postcss-color-rebeccapurple "^4.0.1" ++ postcss-custom-media "^7.0.8" ++ postcss-custom-properties "^8.0.11" ++ postcss-custom-selectors "^5.1.2" ++ postcss-dir-pseudo-class "^5.0.0" ++ postcss-double-position-gradients "^1.0.0" ++ postcss-env-function "^2.0.2" ++ postcss-focus-visible "^4.0.0" ++ postcss-focus-within "^3.0.0" ++ postcss-font-variant "^4.0.0" ++ postcss-gap-properties "^2.0.0" ++ postcss-image-set-function "^3.0.1" ++ postcss-initial "^3.0.0" ++ postcss-lab-function "^2.0.1" ++ postcss-logical "^3.0.0" ++ postcss-media-minmax "^4.0.0" ++ postcss-nesting "^7.0.0" ++ postcss-overflow-shorthand "^2.0.0" ++ postcss-page-break "^2.0.0" ++ postcss-place "^4.0.1" ++ postcss-pseudo-class-any-link "^6.0.0" ++ postcss-replace-overflow-wrap "^3.0.0" ++ postcss-selector-matches "^4.0.0" ++ postcss-selector-not "^4.0.0" ++ ++postcss-pseudo-class-any-link@^6.0.0: ++ version "6.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" ++ integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== ++ dependencies: ++ postcss "^7.0.2" ++ postcss-selector-parser "^5.0.0-rc.3" ++ ++postcss-reduce-initial@^4.0.3: ++ version "4.0.3" ++ resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" ++ integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== ++ dependencies: ++ browserslist "^4.0.0" ++ caniuse-api "^3.0.0" ++ has "^1.0.0" ++ postcss "^7.0.0" ++ ++postcss-reduce-transforms@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" ++ integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== ++ dependencies: ++ cssnano-util-get-match "^4.0.0" ++ has "^1.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ ++postcss-replace-overflow-wrap@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" ++ integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== ++ dependencies: ++ postcss "^7.0.2" ++ + postcss-reporter@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-6.0.1.tgz#7c055120060a97c8837b4e48215661aafb74245f" +@@ -2941,15 +7684,91 @@ postcss-reporter@^6.0.0: + log-symbols "^2.2.0" + postcss "^7.0.7" + +-postcss-value-parser@^4.0.0: ++postcss-selector-matches@^4.0.0: + version "4.0.0" +- resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz#99a983d365f7b2ad8d0f9b8c3094926eab4b936d" +- integrity sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ== ++ resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" ++ integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== ++ dependencies: ++ balanced-match "^1.0.0" ++ postcss "^7.0.2" + +-postcss@^7.0.0, postcss@^7.0.17, postcss@^7.0.7: +- version "7.0.17" +- resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f" +- integrity sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ== ++postcss-selector-not@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz#c68ff7ba96527499e832724a2674d65603b645c0" ++ integrity sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ== ++ dependencies: ++ balanced-match "^1.0.0" ++ postcss "^7.0.2" ++ ++postcss-selector-parser@^3.0.0: ++ version "3.1.1" ++ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" ++ integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= ++ dependencies: ++ dot-prop "^4.1.1" ++ indexes-of "^1.0.1" ++ uniq "^1.0.1" ++ ++postcss-selector-parser@^5.0.0, postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: ++ version "5.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" ++ integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== ++ dependencies: ++ cssesc "^2.0.0" ++ indexes-of "^1.0.1" ++ uniq "^1.0.1" ++ ++postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: ++ version "6.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" ++ integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== ++ dependencies: ++ cssesc "^3.0.0" ++ indexes-of "^1.0.1" ++ uniq "^1.0.1" ++ ++postcss-svgo@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" ++ integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== ++ dependencies: ++ is-svg "^3.0.0" ++ postcss "^7.0.0" ++ postcss-value-parser "^3.0.0" ++ svgo "^1.0.0" ++ ++postcss-unique-selectors@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" ++ integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== ++ dependencies: ++ alphanum-sort "^1.0.0" ++ postcss "^7.0.0" ++ uniqs "^2.0.0" ++ ++postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.1: ++ version "3.3.1" ++ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" ++ integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== ++ ++postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" ++ integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== ++ ++postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" ++ integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== ++ dependencies: ++ flatten "^1.0.2" ++ indexes-of "^1.0.1" ++ uniq "^1.0.1" ++ ++postcss@7.x.x, postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.23, postcss@^7.0.5, postcss@^7.0.6, postcss@^7.0.7: ++ version "7.0.23" ++ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.23.tgz#9f9759fad661b15964f3cfc3140f66f1e05eadc1" ++ integrity sha512-hOlMf3ouRIFXD+j2VJecwssTwbvsPGJVMzupptg+85WA+i7MwyrydmQAgY3R+m0Bc0exunhbJmijy8u8+vufuQ== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" +@@ -2960,6 +7779,46 @@ prelude-ls@~1.1.2: + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + ++prepend-http@^1.0.0, prepend-http@^1.0.1: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" ++ integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= ++ ++prepend-http@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" ++ integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= ++ ++prettier-linter-helpers@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" ++ integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== ++ dependencies: ++ fast-diff "^1.1.2" ++ ++prettier@1.19.1: ++ version "1.19.1" ++ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" ++ integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== ++ ++pretty-error@^2.0.2: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" ++ integrity sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM= ++ dependencies: ++ renderkid "^2.0.1" ++ utila "~0.4" ++ ++pretty-format@^24.9.0: ++ version "24.9.0" ++ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9" ++ integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA== ++ dependencies: ++ "@jest/types" "^24.9.0" ++ ansi-regex "^4.0.0" ++ ansi-styles "^3.2.0" ++ react-is "^16.8.4" ++ + pretty-hrtime@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" +@@ -2970,20 +7829,56 @@ process-nextick-args@~2.0.0: + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +-process@~0.11.0: +- version "0.11.10" +- resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" +- integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= ++process@^0.11.10: ++ version "0.11.10" ++ resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" ++ integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= ++ ++progress@^2.0.0: ++ version "2.0.3" ++ resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" ++ integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== ++ ++promise-inflight@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" ++ integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= ++ ++prompts@^2.0.1: ++ version "2.3.0" ++ resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.0.tgz#a444e968fa4cc7e86689a74050685ac8006c4cc4" ++ integrity sha512-NfbbPPg/74fT7wk2XYQ7hAIp9zJyZp5Fu19iRbORqqy1BhtrkZ0fPafBU+7bmn8ie69DpT0R6QpJIN2oisYjJg== ++ dependencies: ++ kleur "^3.0.3" ++ sisteransi "^1.0.3" ++ ++proto-list@~1.2.1: ++ version "1.2.4" ++ resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" ++ integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= ++ ++proxy-addr@~2.0.5: ++ version "2.0.5" ++ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" ++ integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== ++ dependencies: ++ forwarded "~0.1.2" ++ ipaddr.js "1.9.0" ++ ++prr@~1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" ++ integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +-progress@^2.0.0: +- version "2.0.3" +- resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" +- integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== ++pseudomap@^1.0.2: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" ++ integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + + psl@^1.1.24, psl@^1.1.28: +- version "1.2.0" +- resolved "https://registry.yarnpkg.com/psl/-/psl-1.2.0.tgz#df12b5b1b3a30f51c329eacbdef98f3a6e136dc6" +- integrity sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA== ++ version "1.4.0" ++ resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" ++ integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== + + public-encrypt@^4.0.0: + version "4.0.3" +@@ -2997,6 +7892,14 @@ public-encrypt@^4.0.0: + randombytes "^2.0.1" + safe-buffer "^5.1.2" + ++pump@^2.0.0: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" ++ integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== ++ dependencies: ++ end-of-stream "^1.1.0" ++ once "^1.3.1" ++ + pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" +@@ -3005,6 +7908,15 @@ pump@^3.0.0: + end-of-stream "^1.1.0" + once "^1.3.1" + ++pumpify@^1.3.3: ++ version "1.5.1" ++ resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" ++ integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== ++ dependencies: ++ duplexify "^3.6.0" ++ inherits "^2.0.3" ++ pump "^2.0.0" ++ + punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" +@@ -3015,17 +7927,44 @@ punycode@2.x.x, 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== + +-punycode@^1.3.2, punycode@^1.4.1: ++punycode@^1.2.4, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + ++q@^1.1.2: ++ version "1.5.1" ++ resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" ++ integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= ++ ++qs@6.7.0: ++ version "6.7.0" ++ resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" ++ integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== ++ + qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +-querystring-es3@~0.2.0: ++query-string@^4.1.0: ++ version "4.3.4" ++ resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" ++ integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= ++ dependencies: ++ object-assign "^4.1.0" ++ strict-uri-encode "^1.0.0" ++ ++query-string@^5.0.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" ++ integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== ++ dependencies: ++ decode-uri-component "^0.2.0" ++ object-assign "^4.1.0" ++ strict-uri-encode "^1.0.0" ++ ++querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= +@@ -3035,6 +7974,11 @@ querystring@0.2.0: + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + ++querystringify@^2.1.1: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" ++ integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== ++ + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" +@@ -3050,6 +7994,21 @@ randomfill@^1.0.3: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + ++range-parser@^1.2.1, range-parser@~1.2.1: ++ version "1.2.1" ++ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" ++ integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== ++ ++raw-body@2.4.0: ++ version "2.4.0" ++ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" ++ integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== ++ dependencies: ++ bytes "3.1.0" ++ http-errors "1.7.2" ++ iconv-lite "0.4.24" ++ unpipe "1.0.0" ++ + rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" +@@ -3060,6 +8019,11 @@ rc@^1.2.7: + minimist "^1.2.0" + strip-json-comments "~2.0.1" + ++react-is@^16.8.4: ++ version "16.12.0" ++ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" ++ integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== ++ + read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" +@@ -3067,14 +8031,58 @@ read-cache@^1.0.0: + dependencies: + pify "^2.3.0" + +-read-only-stream@^2.0.0: ++read-pkg-up@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" ++ integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= ++ dependencies: ++ find-up "^1.0.0" ++ read-pkg "^1.0.0" ++ ++read-pkg-up@^2.0.0: + version "2.0.0" +- resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0" +- integrity sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A= ++ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" ++ integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: +- readable-stream "^2.0.2" ++ find-up "^2.0.0" ++ read-pkg "^2.0.0" ++ ++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" ++ integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA== ++ dependencies: ++ find-up "^3.0.0" ++ read-pkg "^3.0.0" ++ ++read-pkg@^1.0.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" ++ integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= ++ dependencies: ++ load-json-file "^1.0.0" ++ normalize-package-data "^2.3.2" ++ path-type "^1.0.0" ++ ++read-pkg@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" ++ integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= ++ dependencies: ++ load-json-file "^2.0.0" ++ normalize-package-data "^2.3.2" ++ path-type "^2.0.0" ++ ++read-pkg@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" ++ integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= ++ dependencies: ++ load-json-file "^4.0.0" ++ normalize-package-data "^2.3.2" ++ path-type "^3.0.0" + +-readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: ++"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== +@@ -3087,6 +8095,15 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + ++readable-stream@^3.0.6, readable-stream@^3.1.1: ++ version "3.4.0" ++ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" ++ integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== ++ 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" +@@ -3096,6 +8113,21 @@ readdirp@^2.2.1: + micromatch "^3.1.10" + readable-stream "^2.0.2" + ++realpath-native@^1.1.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" ++ integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA== ++ dependencies: ++ util.promisify "^1.0.0" ++ ++redent@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" ++ integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= ++ dependencies: ++ indent-string "^2.1.0" ++ strip-indent "^1.0.1" ++ + regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" +@@ -3104,16 +8136,44 @@ regex-not@^1.0.0, regex-not@^1.0.2: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + ++regexp.prototype.flags@^1.2.0: ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" ++ integrity sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA== ++ dependencies: ++ define-properties "^1.1.2" ++ + regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + ++regexpp@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.0.0.tgz#dd63982ee3300e67b41c1956f850aa680d9d330e" ++ integrity sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g== ++ ++relateurl@0.2.x: ++ version "0.2.7" ++ resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" ++ integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= ++ + remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + ++renderkid@^2.0.1: ++ version "2.0.3" ++ resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.3.tgz#380179c2ff5ae1365c522bf2fcfcff01c5b74149" ++ integrity sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA== ++ dependencies: ++ css-select "^1.1.0" ++ dom-converter "^0.2" ++ htmlparser2 "^3.3.0" ++ strip-ansi "^3.0.0" ++ utila "^0.4.0" ++ + repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" +@@ -3124,24 +8184,45 @@ repeat-string@^1.6.1: + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +-request-promise-core@1.1.2: +- version "1.1.2" +- resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" +- integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag== ++repeating@^2.0.0: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" ++ integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= + dependencies: +- lodash "^4.17.11" ++ is-finite "^1.0.0" ++ ++replace-ext@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" ++ integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= ++ ++request-promise-core@1.1.3: ++ version "1.1.3" ++ resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" ++ integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== ++ dependencies: ++ lodash "^4.17.15" ++ ++request-promise-native@^1.0.5: ++ version "1.0.8" ++ resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" ++ integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== ++ dependencies: ++ request-promise-core "1.1.3" ++ stealthy-require "^1.1.1" ++ tough-cookie "^2.3.3" + + request-promise@^4.x: +- version "4.2.4" +- resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.4.tgz#1c5ed0d71441e38ad58c7ce4ea4ea5b06d54b310" +- integrity sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg== ++ version "4.2.5" ++ resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.5.tgz#186222c59ae512f3497dfe4d75a9c8461bd0053c" ++ integrity sha512-ZgnepCykFdmpq86fKGwqntyTiUrHycALuGggpyCZwMvGaZWgxW6yagT0FHkgo5LzYvOaCNvxYwWYIjevSH1EDg== + dependencies: + bluebird "^3.5.0" +- request-promise-core "1.1.2" ++ request-promise-core "1.1.3" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +-request@^2.88.0: ++request@^2.87.0, request@^2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== +@@ -3177,6 +8258,31 @@ require-main-filename@^1.0.1: + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + ++require-main-filename@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" ++ integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== ++ ++requires-port@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" ++ integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= ++ ++resolve-cwd@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" ++ integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= ++ dependencies: ++ resolve-from "^3.0.0" ++ ++resolve-dir@^1.0.0, resolve-dir@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" ++ integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= ++ dependencies: ++ expand-tilde "^2.0.0" ++ global-modules "^1.0.0" ++ + resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" +@@ -3192,24 +8298,31 @@ resolve-url@^0.2.1: + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +-resolve@1.1.7, resolve@1.1.x: ++resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= + +-resolve@^1.1.4, resolve@^1.4.0: +- version "1.11.1" +- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" +- integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw== ++resolve@1.x, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.3.2, resolve@^1.5.0: ++ version "1.12.2" ++ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.2.tgz#08b12496d9aa8659c75f534a8f05f0d892fff594" ++ integrity sha512-cAVTI2VLHWYsGOirfeYVVQ7ZDejtQ9fp4YhYckWDEkFfqbVjaT11iM8k6xSAfGFMM+gDpZjMnFssPu8we+mqFw== + dependencies: + path-parse "^1.0.6" + +-restore-cursor@^2.0.0: +- version "2.0.0" +- resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" +- integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= ++responselike@1.0.2: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" ++ integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= ++ dependencies: ++ lowercase-keys "^1.0.0" ++ ++restore-cursor@^3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" ++ integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: +- onetime "^2.0.0" ++ onetime "^5.1.0" + signal-exit "^3.0.2" + + ret@~0.1.10: +@@ -3217,13 +8330,40 @@ ret@~0.1.10: + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +-rimraf@2.6.3, rimraf@^2.6.1: ++retry@^0.12.0: ++ version "0.12.0" ++ resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" ++ integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= ++ ++reusify@^1.0.0: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" ++ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== ++ ++rgb-regex@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" ++ integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= ++ ++rgba-regex@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" ++ integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= ++ ++rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + ++rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: ++ version "2.7.1" ++ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" ++ integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== ++ dependencies: ++ glob "^7.1.3" ++ + ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" +@@ -3232,6 +8372,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: + hash-base "^3.0.0" + inherits "^2.0.1" + ++rsvp@^4.8.4: ++ version "4.8.5" ++ resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" ++ integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== ++ + run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" +@@ -3239,23 +8384,35 @@ run-async@^2.2.0: + dependencies: + is-promise "^2.1.0" + ++run-parallel@^1.1.9: ++ version "1.1.9" ++ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" ++ integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== ++ ++run-queue@^1.0.0, run-queue@^1.0.3: ++ version "1.0.3" ++ resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" ++ integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= ++ dependencies: ++ aproba "^1.1.1" ++ + rxjs@^6.4.0: +- version "6.5.2" +- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" +- integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== ++ version "6.5.3" ++ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" ++ integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== + dependencies: + tslib "^1.9.0" + +-safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2: +- version "5.2.0" +- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" +- integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== +- +-safe-buffer@~5.1.0, safe-buffer@~5.1.1: ++safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + ++safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: ++ version "5.2.0" ++ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" ++ integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== ++ + safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" +@@ -3268,15 +8425,145 @@ safe-regex@^1.1.0: + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +-sax@>=0.6.0, sax@^1.2.4: ++sane@^4.0.3: ++ version "4.1.0" ++ resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" ++ integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== ++ dependencies: ++ "@cnakazawa/watch" "^1.0.3" ++ anymatch "^2.0.0" ++ capture-exit "^2.0.0" ++ exec-sh "^0.3.2" ++ execa "^1.0.0" ++ fb-watchman "^2.0.0" ++ micromatch "^3.1.4" ++ minimist "^1.1.1" ++ walker "~1.0.5" ++ ++sanitize.css@^10.0.0: ++ version "10.0.0" ++ resolved "https://registry.yarnpkg.com/sanitize.css/-/sanitize.css-10.0.0.tgz#b5cb2547e96d8629a60947544665243b1dc3657a" ++ integrity sha512-vTxrZz4dX5W86M6oVWVdOVe72ZiPs41Oi7Z6Km4W5Turyz28mrXSJhhEBZoRtzJWIv3833WKVwLSDWWkEfupMg== ++ ++sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +-semver@^5.3.0, semver@^5.5.0, semver@^5.5.1: +- version "5.7.0" +- resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" +- integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== ++schema-utils@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" ++ integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== ++ dependencies: ++ ajv "^6.1.0" ++ ajv-errors "^1.0.0" ++ ajv-keywords "^3.1.0" ++ ++schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.5.0: ++ version "2.5.0" ++ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.5.0.tgz#8f254f618d402cc80257486213c8970edfd7c22f" ++ integrity sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ== ++ dependencies: ++ ajv "^6.10.2" ++ ajv-keywords "^3.4.1" ++ ++seek-bzip@^1.0.5: ++ version "1.0.5" ++ resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" ++ integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= ++ dependencies: ++ commander "~2.8.1" ++ ++select-hose@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" ++ integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= ++ ++select@^1.1.2: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" ++ integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= ++ ++selfsigned@^1.10.7: ++ version "1.10.7" ++ resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b" ++ integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA== ++ dependencies: ++ node-forge "0.9.0" ++ ++semver-regex@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" ++ integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== ++ ++semver-truncate@^1.1.2: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8" ++ integrity sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g= ++ dependencies: ++ semver "^5.3.0" ++ ++"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.6.0: ++ version "5.7.1" ++ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" ++ integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== ++ ++semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: ++ version "6.3.0" ++ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" ++ integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== ++ ++send@0.17.1: ++ version "0.17.1" ++ resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" ++ integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== ++ dependencies: ++ debug "2.6.9" ++ depd "~1.1.2" ++ destroy "~1.0.4" ++ encodeurl "~1.0.2" ++ escape-html "~1.0.3" ++ etag "~1.8.1" ++ fresh "0.5.2" ++ http-errors "~1.7.2" ++ mime "1.6.0" ++ ms "2.1.1" ++ on-finished "~2.3.0" ++ range-parser "~1.2.1" ++ statuses "~1.5.0" ++ ++serialize-javascript@^1.7.0: ++ version "1.9.1" ++ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" ++ integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== ++ ++serialize-javascript@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.0.tgz#9310276819efd0eb128258bb341957f6eb2fc570" ++ integrity sha512-a/mxFfU00QT88umAJQsNWOnUKckhNCqOl028N48e7wFmo2/EHpTo9Wso+iJJCMrQnmFvcjto5RJdAHEvVhcyUQ== ++ ++serve-index@^1.9.1: ++ version "1.9.1" ++ resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" ++ integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= ++ dependencies: ++ accepts "~1.3.4" ++ batch "0.6.1" ++ debug "2.6.9" ++ escape-html "~1.0.3" ++ http-errors "~1.6.2" ++ mime-types "~2.1.17" ++ parseurl "~1.3.2" ++ ++serve-static@1.14.1: ++ version "1.14.1" ++ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" ++ integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== ++ dependencies: ++ encodeurl "~1.0.2" ++ escape-html "~1.0.3" ++ parseurl "~1.3.3" ++ send "0.17.1" + + set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" +@@ -3293,7 +8580,22 @@ set-value@^2.0.0, set-value@^2.0.1: + is-plain-object "^2.0.3" + split-string "^3.0.1" + +-sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: ++setimmediate@^1.0.4: ++ version "1.0.5" ++ resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" ++ integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= ++ ++setprototypeof@1.1.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" ++ integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== ++ ++setprototypeof@1.1.1: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" ++ integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== ++ ++sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== +@@ -3301,14 +8603,6 @@ sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +-shasum@^1.0.0: +- version "1.0.2" +- resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f" +- integrity sha1-5wEjENj0F/TetXEhUOVni4euVl8= +- dependencies: +- json-stable-stringify "~0.0.0" +- sha.js "~2.4.4" +- + shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" +@@ -3321,31 +8615,43 @@ shebang-regex@^1.0.0: + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +-shell-quote@^1.6.1: +- version "1.6.1" +- resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" +- integrity sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c= +- dependencies: +- array-filter "~0.0.0" +- array-map "~0.0.0" +- array-reduce "~0.0.0" +- jsonify "~0.0.0" ++shellwords@^0.1.1: ++ version "0.1.1" ++ resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" ++ integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== + + signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +-simple-concat@^1.0.0: ++simple-swizzle@^0.2.2: ++ version "0.2.2" ++ resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" ++ integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= ++ dependencies: ++ is-arrayish "^0.3.1" ++ ++sisteransi@^1.0.3: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.4.tgz#386713f1ef688c7c0304dc4c0632898941cad2e3" ++ integrity sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig== ++ ++slash@^1.0.0: + version "1.0.0" +- resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" +- integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= ++ resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" ++ integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + + slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + ++slash@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" ++ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== ++ + slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" +@@ -3385,6 +8691,52 @@ snapdragon@^0.8.1: + source-map-resolve "^0.5.0" + use "^3.1.0" + ++sockjs-client@1.4.0: ++ version "1.4.0" ++ resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" ++ integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== ++ dependencies: ++ debug "^3.2.5" ++ eventsource "^1.0.7" ++ faye-websocket "~0.11.1" ++ inherits "^2.0.3" ++ json3 "^3.3.2" ++ url-parse "^1.4.3" ++ ++sockjs@0.3.19: ++ version "0.3.19" ++ resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d" ++ integrity sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw== ++ dependencies: ++ faye-websocket "^0.10.0" ++ uuid "^3.0.1" ++ ++sort-keys-length@^1.0.0: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188" ++ integrity sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg= ++ dependencies: ++ sort-keys "^1.0.0" ++ ++sort-keys@^1.0.0: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" ++ integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= ++ dependencies: ++ is-plain-obj "^1.0.0" ++ ++sort-keys@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" ++ integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= ++ dependencies: ++ is-plain-obj "^1.0.0" ++ ++source-list-map@^2.0.0: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" ++ integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== ++ + source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" +@@ -3396,27 +8748,77 @@ source-map-resolve@^0.5.0: + source-map-url "^0.4.0" + urix "^0.1.0" + ++source-map-support@^0.5.6, source-map-support@~0.5.12: ++ version "0.5.16" ++ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" ++ integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== ++ dependencies: ++ buffer-from "^1.0.0" ++ source-map "^0.6.0" ++ + source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +-source-map@^0.5.6, source-map@~0.5.3: ++source-map@^0.5.0, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +-source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: ++source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +-source-map@~0.2.0: +- version "0.2.0" +- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" +- integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= ++spdx-correct@^3.0.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" ++ integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== ++ dependencies: ++ spdx-expression-parse "^3.0.0" ++ spdx-license-ids "^3.0.0" ++ ++spdx-exceptions@^2.1.0: ++ version "2.2.0" ++ resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" ++ integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== ++ ++spdx-expression-parse@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" ++ integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== ++ dependencies: ++ spdx-exceptions "^2.1.0" ++ spdx-license-ids "^3.0.0" ++ ++spdx-license-ids@^3.0.0: ++ version "3.0.5" ++ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" ++ integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== ++ ++spdy-transport@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" ++ integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== ++ dependencies: ++ debug "^4.1.0" ++ detect-node "^2.0.4" ++ hpack.js "^2.1.6" ++ obuf "^1.1.2" ++ readable-stream "^3.0.6" ++ wbuf "^1.7.3" ++ ++spdy@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2" ++ integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA== + dependencies: +- amdefine ">=0.0.4" ++ debug "^4.1.0" ++ handle-thing "^2.0.0" ++ http-deceiver "^1.2.7" ++ select-hose "^2.0.0" ++ spdy-transport "^3.0.0" + + split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" +@@ -3430,6 +8832,15 @@ sprintf-js@~1.0.2: + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + ++squeak@^1.0.0: ++ version "1.3.0" ++ resolved "https://registry.yarnpkg.com/squeak/-/squeak-1.3.0.tgz#33045037b64388b567674b84322a6521073916c3" ++ integrity sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM= ++ dependencies: ++ chalk "^1.0.0" ++ console-stream "^0.1.1" ++ lpad-align "^1.0.1" ++ + sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" +@@ -3445,6 +8856,23 @@ sshpk@^1.7.0: + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + ++ssri@^6.0.1: ++ version "6.0.1" ++ resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" ++ integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== ++ dependencies: ++ figgy-pudding "^3.5.1" ++ ++stable@^0.1.8: ++ version "0.1.8" ++ resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" ++ integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== ++ ++stack-utils@^1.0.1: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" ++ integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== ++ + static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" +@@ -3453,12 +8881,17 @@ static-extend@^0.1.1: + define-property "^0.2.5" + object-copy "^0.1.0" + ++"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: ++ version "1.5.0" ++ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" ++ integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= ++ + stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +-stream-browserify@^2.0.0: ++stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== +@@ -3466,15 +8899,15 @@ stream-browserify@^2.0.0: + inherits "~2.0.1" + readable-stream "^2.0.2" + +-stream-combiner2@^1.1.1: +- version "1.1.1" +- resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" +- integrity sha1-+02KFCDqNidk4hrUeAOXvry0HL4= ++stream-each@^1.1.0: ++ version "1.2.3" ++ resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" ++ integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: +- duplexer2 "~0.1.0" +- readable-stream "^2.0.2" ++ end-of-stream "^1.1.0" ++ stream-shift "^1.0.0" + +-stream-http@^2.0.0: ++stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== +@@ -3485,13 +8918,23 @@ stream-http@^2.0.0: + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +-stream-splicer@^2.0.0: +- version "2.0.1" +- resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.1.tgz#0b13b7ee2b5ac7e0609a7463d83899589a363fcd" +- integrity sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg== ++stream-shift@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" ++ integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= ++ ++strict-uri-encode@^1.0.0: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" ++ integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= ++ ++string-length@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" ++ integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0= + dependencies: +- inherits "^2.0.1" +- readable-stream "^2.0.2" ++ astral-regex "^1.0.0" ++ strip-ansi "^4.0.0" + + string-width@^1.0.1: + version "1.0.2" +@@ -3502,7 +8945,7 @@ string-width@^1.0.1: + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +-"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: ++"string-width@^1.0.2 || 2", 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== +@@ -3510,21 +8953,46 @@ string-width@^1.0.1: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +-string-width@^3.0.0: +- version "3.1.0" +- resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" +- integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== ++string-width@^3.0.0, string-width@^3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" ++ integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== ++ dependencies: ++ emoji-regex "^7.0.1" ++ is-fullwidth-code-point "^2.0.0" ++ strip-ansi "^5.1.0" ++ ++string-width@^4.1.0: ++ version "4.2.0" ++ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" ++ integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== ++ dependencies: ++ emoji-regex "^8.0.0" ++ is-fullwidth-code-point "^3.0.0" ++ strip-ansi "^6.0.0" ++ ++string.prototype.trimleft@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" ++ integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== ++ dependencies: ++ define-properties "^1.1.3" ++ function-bind "^1.1.1" ++ ++string.prototype.trimright@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" ++ integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: +- emoji-regex "^7.0.1" +- is-fullwidth-code-point "^2.0.0" +- strip-ansi "^5.1.0" ++ define-properties "^1.1.3" ++ function-bind "^1.1.1" + +-string_decoder@^1.1.1: +- version "1.2.0" +- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" +- integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== ++string_decoder@^1.0.0, string_decoder@^1.1.1: ++ version "1.3.0" ++ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" ++ integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: +- safe-buffer "~5.1.0" ++ safe-buffer "~5.2.0" + + string_decoder@~1.1.1: + version "1.1.1" +@@ -3547,29 +9015,84 @@ strip-ansi@^4.0.0: + dependencies: + ansi-regex "^3.0.0" + +-strip-ansi@^5.1.0: ++strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + ++strip-ansi@^6.0.0: ++ version "6.0.0" ++ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" ++ integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== ++ dependencies: ++ ansi-regex "^5.0.0" ++ ++strip-bom@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" ++ integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= ++ dependencies: ++ is-utf8 "^0.2.0" ++ ++strip-bom@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" ++ integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= ++ ++strip-dirs@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" ++ integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== ++ dependencies: ++ is-natural-number "^4.0.1" ++ + strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +-strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: ++strip-indent@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" ++ integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= ++ dependencies: ++ get-stdin "^4.0.1" ++ ++strip-json-comments@^3.0.1: ++ version "3.0.1" ++ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" ++ integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== ++ ++strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +-subarg@^1.0.0: ++strip-outer@^1.0.0: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" ++ integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== ++ dependencies: ++ escape-string-regexp "^1.0.2" ++ ++style-loader@1.0.0: + version "1.0.0" +- resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" +- integrity sha1-9izxdYHplrSPyWVpn1TAauJouNI= ++ resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.0.0.tgz#1d5296f9165e8e2c85d24eee0b7caf9ec8ca1f82" ++ integrity sha512-B0dOCFwv7/eY31a5PCieNwMgMhVGFe9w+rh7s/Bx8kfFkrth9zfTZquoYvdw8URgiqxObQKcpW51Ugz1HjfdZw== ++ dependencies: ++ loader-utils "^1.2.3" ++ schema-utils "^2.0.1" ++ ++stylehacks@^4.0.0: ++ version "4.0.3" ++ resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" ++ integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== + dependencies: +- minimist "^1.1.0" ++ browserslist "^4.0.0" ++ postcss "^7.0.0" ++ postcss-selector-parser "^3.0.0" + + supports-color@5.4.0: + version "5.4.0" +@@ -3578,12 +9101,17 @@ supports-color@5.4.0: + dependencies: + has-flag "^3.0.0" + +-supports-color@^3.1.0: +- version "3.2.3" +- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" +- integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= ++supports-color@6.1.0, supports-color@^6.1.0: ++ version "6.1.0" ++ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" ++ integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: +- has-flag "^1.0.0" ++ has-flag "^3.0.0" ++ ++supports-color@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" ++ integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + + supports-color@^5.3.0: + version "5.5.0" +@@ -3592,48 +9120,128 @@ supports-color@^5.3.0: + dependencies: + has-flag "^3.0.0" + +-supports-color@^6.1.0: +- version "6.1.0" +- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" +- integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== +- dependencies: +- has-flag "^3.0.0" +- +-syntax-error@^1.1.1: +- version "1.4.0" +- resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c" +- integrity sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w== ++svgo@^1.0.0, svgo@^1.0.5: ++ version "1.3.2" ++ resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" ++ integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== + dependencies: +- acorn-node "^1.2.0" ++ chalk "^2.4.1" ++ coa "^2.0.2" ++ css-select "^2.0.0" ++ css-select-base-adapter "^0.1.1" ++ css-tree "1.0.0-alpha.37" ++ csso "^4.0.2" ++ js-yaml "^3.13.1" ++ mkdirp "~0.5.1" ++ object.values "^1.1.0" ++ sax "~1.2.4" ++ stable "^0.1.8" ++ unquote "~1.1.1" ++ util.promisify "~1.0.0" ++ ++symbol-tree@^3.2.2: ++ version "3.2.4" ++ resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" ++ integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + + table@^5.2.3: +- version "5.4.1" +- resolved "https://registry.yarnpkg.com/table/-/table-5.4.1.tgz#0691ae2ebe8259858efb63e550b6d5f9300171e8" +- integrity sha512-E6CK1/pZe2N75rGZQotFOdmzWQ1AILtgYbMAbAjvms0S1l5IDB47zG3nCnFGB/w+7nB3vKofbLXCH7HPBo864w== ++ version "5.4.6" ++ resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" ++ integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: +- ajv "^6.9.1" +- lodash "^4.17.11" ++ ajv "^6.10.2" ++ lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + ++tapable@^1.0.0, tapable@^1.1.3: ++ version "1.1.3" ++ resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" ++ integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== ++ ++tar-stream@^1.5.2: ++ version "1.6.2" ++ resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" ++ integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== ++ dependencies: ++ bl "^1.0.0" ++ buffer-alloc "^1.2.0" ++ end-of-stream "^1.0.0" ++ fs-constants "^1.0.0" ++ readable-stream "^2.3.0" ++ to-buffer "^1.1.1" ++ xtend "^4.0.0" ++ + tar@^4: +- version "4.4.10" +- resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" +- integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== ++ version "4.4.13" ++ resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" ++ integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" +- minipass "^2.3.5" ++ minipass "^2.8.6" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" + ++temp-dir@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" ++ integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= ++ ++tempfile@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-2.0.0.tgz#6b0446856a9b1114d1856ffcbe509cccb0977265" ++ integrity sha1-awRGhWqbERTRhW/8vlCczLCXcmU= ++ dependencies: ++ temp-dir "^1.0.0" ++ uuid "^3.0.1" ++ ++terser-webpack-plugin@^1.4.1: ++ version "1.4.1" ++ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4" ++ integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg== ++ dependencies: ++ cacache "^12.0.2" ++ find-cache-dir "^2.1.0" ++ is-wsl "^1.1.0" ++ schema-utils "^1.0.0" ++ serialize-javascript "^1.7.0" ++ source-map "^0.6.1" ++ terser "^4.1.2" ++ webpack-sources "^1.4.0" ++ worker-farm "^1.7.0" ++ ++terser@^4.1.2: ++ version "4.4.0" ++ resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.0.tgz#22c46b4817cf4c9565434bfe6ad47336af259ac3" ++ integrity sha512-oDG16n2WKm27JO8h4y/w3iqBGAOSCtq7k8dRmrn4Wf9NouL0b2WpMHGChFGZq4nFAQy1FsNJrVQHfurXOSTmOA== ++ dependencies: ++ commander "^2.20.0" ++ source-map "~0.6.1" ++ source-map-support "~0.5.12" ++ ++test-exclude@^5.2.3: ++ version "5.2.3" ++ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" ++ integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== ++ dependencies: ++ glob "^7.1.3" ++ minimatch "^3.0.4" ++ read-pkg-up "^4.0.0" ++ require-main-filename "^2.0.0" ++ + text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + ++throat@^4.0.0: ++ version "4.1.0" ++ resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" ++ integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= ++ + through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" +@@ -3642,17 +9250,37 @@ through2@^2.0.0: + readable-stream "~2.3.6" + xtend "~4.0.1" + +-"through@>=2.2.7 <3", through@^2.3.6: ++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= + +-timers-browserify@^1.0.1: +- version "1.4.2" +- resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" +- integrity sha1-ycWLV1voQHN1y14kYtrO50NZ9B0= ++thunky@^1.0.2: ++ version "1.1.0" ++ resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" ++ integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== ++ ++timed-out@^4.0.0, timed-out@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" ++ integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= ++ ++timers-browserify@^2.0.4: ++ version "2.0.11" ++ resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" ++ integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== + dependencies: +- process "~0.11.0" ++ setimmediate "^1.0.4" ++ ++timsort@^0.3.0: ++ version "0.3.0" ++ resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" ++ integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= ++ ++tiny-emitter@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" ++ integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + + tmp@^0.0.33: + version "0.0.33" +@@ -3661,11 +9289,26 @@ tmp@^0.0.33: + dependencies: + os-tmpdir "~1.0.2" + ++tmpl@1.0.x: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" ++ integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= ++ + to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + ++to-buffer@^1.1.1: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" ++ integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== ++ ++to-fast-properties@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" ++ integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= ++ + to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" +@@ -3681,6 +9324,13 @@ to-regex-range@^2.1.0: + is-number "^3.0.0" + repeat-string "^1.6.1" + ++to-regex-range@^5.0.1: ++ version "5.0.1" ++ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" ++ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== ++ dependencies: ++ is-number "^7.0.0" ++ + to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" +@@ -3691,6 +9341,11 @@ to-regex@^3.0.1, to-regex@^3.0.2: + regex-not "^1.0.2" + safe-regex "^1.1.0" + ++toidentifier@1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" ++ integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== ++ + topo@3.x.x: + version "3.0.3" + resolved "https://registry.yarnpkg.com/topo/-/topo-3.0.3.tgz#d5a67fb2e69307ebeeb08402ec2a2a6f5f7ad95c" +@@ -3698,7 +9353,12 @@ topo@3.x.x: + dependencies: + hoek "6.x.x" + +-tough-cookie@^2.3.3: ++toposort@^1.0.0: ++ version "1.0.7" ++ resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" ++ integrity sha1-LmhELZ9k7HILjMieZEOsbKqVACk= ++ ++tough-cookie@^2.3.3, tough-cookie@^2.3.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== +@@ -3714,15 +9374,79 @@ tough-cookie@~2.4.3: + psl "^1.1.24" + punycode "^1.4.1" + +-tslib@^1.9.0: ++tr46@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" ++ integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= ++ dependencies: ++ punycode "^2.1.0" ++ ++trim-newlines@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" ++ integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= ++ ++trim-repeated@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" ++ integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= ++ dependencies: ++ escape-string-regexp "^1.0.2" ++ ++ts-jest@24.2.0: ++ version "24.2.0" ++ resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.2.0.tgz#7abca28c2b4b0a1fdd715cd667d65d047ea4e768" ++ integrity sha512-Yc+HLyldlIC9iIK8xEN7tV960Or56N49MDP7hubCZUeI7EbIOTsas6rXCMB4kQjLACJ7eDOF4xWEO5qumpKsag== ++ dependencies: ++ bs-logger "0.x" ++ buffer-from "1.x" ++ fast-json-stable-stringify "2.x" ++ json5 "2.x" ++ lodash.memoize "4.x" ++ make-error "1.x" ++ mkdirp "0.x" ++ resolve "1.x" ++ semver "^5.5" ++ yargs-parser "10.x" ++ ++ts-loader@6.2.1: ++ version "6.2.1" ++ resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.1.tgz#67939d5772e8a8c6bdaf6277ca023a4812da02ef" ++ integrity sha512-Dd9FekWuABGgjE1g0TlQJ+4dFUfYGbYcs52/HQObE0ZmUNjQlmLAS7xXsSzy23AMaMwipsx5sNHvoEpT2CZq1g== ++ dependencies: ++ chalk "^2.3.0" ++ enhanced-resolve "^4.0.0" ++ loader-utils "^1.0.2" ++ micromatch "^4.0.0" ++ semver "^6.0.0" ++ ++ts-node@8.5.2: ++ version "8.5.2" ++ resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.5.2.tgz#434f6c893bafe501a30b32ac94ee36809ba2adce" ++ integrity sha512-W1DK/a6BGoV/D4x/SXXm6TSQx6q3blECUzd5TN+j56YEMX3yPVMpHsICLedUw3DvGF3aTQ8hfdR9AKMaHjIi+A== ++ dependencies: ++ arg "^4.1.0" ++ diff "^4.0.1" ++ make-error "^1.1.1" ++ source-map-support "^0.5.6" ++ yn "^3.0.0" ++ ++tslib@^1.8.1, tslib@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +-tty-browserify@0.0.1: +- version "0.0.1" +- resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" +- integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== ++tsutils@^3.17.1: ++ version "3.17.1" ++ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" ++ integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== ++ dependencies: ++ tslib "^1.8.1" ++ ++tty-browserify@0.0.0: ++ version "0.0.0" ++ resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" ++ integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + + tunnel-agent@^0.6.0: + version "0.6.0" +@@ -3743,34 +9467,57 @@ type-check@~0.3.2: + dependencies: + prelude-ls "~1.1.2" + ++type-fest@^0.5.1: ++ version "0.5.2" ++ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" ++ integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== ++ ++type-fest@^0.8.1: ++ version "0.8.1" ++ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" ++ integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== ++ ++type-is@~1.6.17, type-is@~1.6.18: ++ version "1.6.18" ++ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" ++ integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== ++ dependencies: ++ media-typer "0.3.0" ++ mime-types "~2.1.24" ++ + typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +-uglify-js@^3.1.4, uglify-js@^3.6.0: +- version "3.6.0" +- resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5" +- integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg== ++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== ++ ++uglify-js@3.4.x: ++ version "3.4.10" ++ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" ++ integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw== + dependencies: +- commander "~2.20.0" ++ commander "~2.19.0" + source-map "~0.6.1" + +-umd@^3.0.0: +- version "3.0.3" +- resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" +- integrity sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow== ++uglify-js@^3.1.4: ++ version "3.6.9" ++ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.9.tgz#85d353edb6ddfb62a9d798f36e91792249320611" ++ integrity sha512-pcnnhaoG6RtrvHJ1dFncAe8Od6Nuy30oaJ82ts6//sGSXOP5UjBMEthiProjXmMNHOfd93sqlkztifFMcb+4yw== ++ dependencies: ++ commander "~2.20.3" ++ source-map "~0.6.1" + +-undeclared-identifiers@^1.1.2: +- version "1.1.3" +- resolved "https://registry.yarnpkg.com/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz#9254c1d37bdac0ac2b52de4b6722792d2a91e30f" +- integrity sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw== ++unbzip2-stream@^1.0.9: ++ version "1.3.3" ++ resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" ++ integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg== + dependencies: +- acorn-node "^1.3.0" +- dash-ast "^1.0.0" +- get-assigned-identifiers "^1.2.0" +- simple-concat "^1.0.0" +- xtend "^4.0.1" ++ buffer "^5.2.1" ++ through "^2.3.8" + + union-value@^1.0.0: + version "1.0.1" +@@ -3782,11 +9529,45 @@ union-value@^1.0.0: + is-extendable "^0.1.1" + set-value "^2.0.1" + ++uniq@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" ++ integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= ++ ++uniqs@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" ++ integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= ++ ++unique-filename@^1.1.1: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" ++ integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== ++ dependencies: ++ unique-slug "^2.0.0" ++ ++unique-slug@^2.0.0: ++ version "2.0.2" ++ resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" ++ integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== ++ dependencies: ++ imurmurhash "^0.1.4" ++ + universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + ++unpipe@1.0.0, unpipe@~1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" ++ integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= ++ ++unquote@~1.1.1: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" ++ integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= ++ + unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" +@@ -3796,9 +9577,14 @@ unset-value@^1.0.0: + isobject "^3.0.0" + + upath@^1.1.1: +- version "1.1.2" +- resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" +- integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" ++ integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== ++ ++upper-case@^1.1.1: ++ version "1.1.3" ++ resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" ++ integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= + + uri-js@^4.2.2: + version "4.2.2" +@@ -3812,7 +9598,43 @@ urix@^0.1.0: + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +-url@~0.11.0: ++url-loader@2.3.0: ++ version "2.3.0" ++ resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-2.3.0.tgz#e0e2ef658f003efb8ca41b0f3ffbf76bab88658b" ++ integrity sha512-goSdg8VY+7nPZKUEChZSEtW5gjbS66USIGCeSJ1OVOJ7Yfuh/36YxCwMi5HVEJh6mqUYOoy3NJ0vlOMrWsSHog== ++ dependencies: ++ loader-utils "^1.2.3" ++ mime "^2.4.4" ++ schema-utils "^2.5.0" ++ ++url-parse-lax@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" ++ integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= ++ dependencies: ++ prepend-http "^1.0.1" ++ ++url-parse-lax@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" ++ integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= ++ dependencies: ++ prepend-http "^2.0.0" ++ ++url-parse@^1.4.3: ++ version "1.4.7" ++ resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" ++ integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== ++ dependencies: ++ querystringify "^2.1.1" ++ requires-port "^1.0.0" ++ ++url-to-options@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" ++ integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= ++ ++url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= +@@ -3825,11 +9647,19 @@ use@^3.1.0: + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +-util-deprecate@~1.0.1: ++util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + ++util.promisify@1.0.0, util.promisify@^1.0.0, util.promisify@~1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" ++ integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== ++ dependencies: ++ define-properties "^1.1.2" ++ object.getownpropertydescriptors "^2.0.3" ++ + util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" +@@ -3837,17 +9667,55 @@ util@0.10.3: + dependencies: + inherits "2.0.1" + +-util@~0.10.1: +- version "0.10.4" +- resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" +- integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== ++util@^0.11.0: ++ version "0.11.1" ++ resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" ++ integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +-uuid@^3.3.2: +- version "3.3.2" +- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" +- integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== ++utila@^0.4.0, utila@~0.4: ++ version "0.4.0" ++ resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" ++ integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= ++ ++utils-merge@1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" ++ integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= ++ ++uuid@^3.0.1, uuid@^3.3.2: ++ version "3.3.3" ++ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" ++ integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== ++ ++v8-compile-cache@2.0.3: ++ version "2.0.3" ++ resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" ++ integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== ++ ++v8-compile-cache@^2.0.3: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" ++ integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== ++ ++validate-npm-package-license@^3.0.1: ++ version "3.0.4" ++ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" ++ integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== ++ dependencies: ++ spdx-correct "^3.0.0" ++ spdx-expression-parse "^3.0.0" ++ ++vary@~1.1.2: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" ++ integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= ++ ++vendors@^1.0.0: ++ version "1.0.3" ++ resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.3.tgz#a6467781abd366217c050f8202e7e50cc9eef8c0" ++ integrity sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw== + + verror@1.10.0: + version "1.10.0" +@@ -3858,22 +9726,213 @@ verror@1.10.0: + core-util-is "1.0.2" + extsprintf "^1.2.0" + +-vm-browserify@^1.0.0: +- version "1.1.0" +- resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" +- integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw== ++vm-browserify@^1.0.1: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" ++ integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== ++ ++w3c-hr-time@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" ++ integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= ++ dependencies: ++ browser-process-hrtime "^0.1.2" ++ ++walker@^1.0.7, walker@~1.0.5: ++ version "1.0.7" ++ resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" ++ integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= ++ dependencies: ++ makeerror "1.0.x" ++ ++watchpack@^1.6.0: ++ version "1.6.0" ++ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" ++ integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== ++ dependencies: ++ chokidar "^2.0.2" ++ graceful-fs "^4.1.2" ++ neo-async "^2.5.0" ++ ++wbuf@^1.1.0, wbuf@^1.7.3: ++ version "1.7.3" ++ resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" ++ integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== ++ dependencies: ++ minimalistic-assert "^1.0.0" ++ ++webidl-conversions@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" ++ integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== ++ ++webpack-cli@3.3.10: ++ version "3.3.10" ++ resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.10.tgz#17b279267e9b4fb549023fae170da8e6e766da13" ++ integrity sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg== ++ dependencies: ++ chalk "2.4.2" ++ cross-spawn "6.0.5" ++ enhanced-resolve "4.1.0" ++ findup-sync "3.0.0" ++ global-modules "2.0.0" ++ import-local "2.0.0" ++ interpret "1.2.0" ++ loader-utils "1.2.3" ++ supports-color "6.1.0" ++ v8-compile-cache "2.0.3" ++ yargs "13.2.4" ++ ++webpack-dev-middleware@^3.7.2: ++ version "3.7.2" ++ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3" ++ integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw== ++ dependencies: ++ memory-fs "^0.4.1" ++ mime "^2.4.4" ++ mkdirp "^0.5.1" ++ range-parser "^1.2.1" ++ webpack-log "^2.0.0" ++ ++webpack-dev-server@3.9.0: ++ version "3.9.0" ++ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.9.0.tgz#27c3b5d0f6b6677c4304465ac817623c8b27b89c" ++ integrity sha512-E6uQ4kRrTX9URN9s/lIbqTAztwEPdvzVrcmHE8EQ9YnuT9J8Es5Wrd8n9BKg1a0oZ5EgEke/EQFgUsp18dSTBw== ++ dependencies: ++ ansi-html "0.0.7" ++ bonjour "^3.5.0" ++ chokidar "^2.1.8" ++ compression "^1.7.4" ++ connect-history-api-fallback "^1.6.0" ++ debug "^4.1.1" ++ del "^4.1.1" ++ express "^4.17.1" ++ html-entities "^1.2.1" ++ http-proxy-middleware "0.19.1" ++ import-local "^2.0.0" ++ internal-ip "^4.3.0" ++ ip "^1.1.5" ++ is-absolute-url "^3.0.3" ++ killable "^1.0.1" ++ loglevel "^1.6.4" ++ opn "^5.5.0" ++ p-retry "^3.0.1" ++ portfinder "^1.0.25" ++ schema-utils "^1.0.0" ++ selfsigned "^1.10.7" ++ semver "^6.3.0" ++ serve-index "^1.9.1" ++ sockjs "0.3.19" ++ sockjs-client "1.4.0" ++ spdy "^4.0.1" ++ strip-ansi "^3.0.1" ++ supports-color "^6.1.0" ++ url "^0.11.0" ++ webpack-dev-middleware "^3.7.2" ++ webpack-log "^2.0.0" ++ ws "^6.2.1" ++ yargs "12.0.5" ++ ++webpack-log@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" ++ integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== ++ dependencies: ++ ansi-colors "^3.0.0" ++ uuid "^3.3.2" ++ ++webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1: ++ version "1.4.3" ++ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" ++ integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== ++ dependencies: ++ source-list-map "^2.0.0" ++ source-map "~0.6.1" ++ ++webpack@4.41.2: ++ version "4.41.2" ++ resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.2.tgz#c34ec76daa3a8468c9b61a50336d8e3303dce74e" ++ integrity sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A== ++ dependencies: ++ "@webassemblyjs/ast" "1.8.5" ++ "@webassemblyjs/helper-module-context" "1.8.5" ++ "@webassemblyjs/wasm-edit" "1.8.5" ++ "@webassemblyjs/wasm-parser" "1.8.5" ++ acorn "^6.2.1" ++ ajv "^6.10.2" ++ ajv-keywords "^3.4.1" ++ chrome-trace-event "^1.0.2" ++ enhanced-resolve "^4.1.0" ++ eslint-scope "^4.0.3" ++ json-parse-better-errors "^1.0.2" ++ loader-runner "^2.4.0" ++ loader-utils "^1.2.3" ++ memory-fs "^0.4.1" ++ micromatch "^3.1.10" ++ mkdirp "^0.5.1" ++ neo-async "^2.6.1" ++ node-libs-browser "^2.2.1" ++ schema-utils "^1.0.0" ++ tapable "^1.1.3" ++ terser-webpack-plugin "^1.4.1" ++ watchpack "^1.6.0" ++ webpack-sources "^1.4.1" ++ ++websocket-driver@>=0.5.1: ++ version "0.7.3" ++ resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" ++ integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg== ++ dependencies: ++ http-parser-js ">=0.4.0 <0.4.11" ++ safe-buffer ">=5.1.0" ++ websocket-extensions ">=0.1.1" ++ ++websocket-extensions@>=0.1.1: ++ version "0.1.3" ++ resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" ++ integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== + +-whatwg-fetch@^3.0.0: ++whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: ++ version "1.0.5" ++ resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" ++ integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== ++ dependencies: ++ iconv-lite "0.4.24" ++ ++whatwg-fetch@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" + integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== + ++whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0: ++ version "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@^6.4.1: ++ version "6.5.0" ++ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" ++ integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ== ++ dependencies: ++ lodash.sortby "^4.7.0" ++ tr46 "^1.0.1" ++ webidl-conversions "^4.0.2" ++ ++whatwg-url@^7.0.0: ++ version "7.1.0" ++ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" ++ integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== ++ dependencies: ++ lodash.sortby "^4.7.0" ++ tr46 "^1.0.1" ++ webidl-conversions "^4.0.2" ++ + which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +-which@^1.1.1, which@^1.2.9: ++which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== +@@ -3887,16 +9946,23 @@ wide-align@^1.1.0: + dependencies: + string-width "^1.0.2 || 2" + +-wordwrap@^1.0.0, wordwrap@~1.0.0: +- version "1.0.0" +- resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" +- integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= ++word-wrap@~1.2.3: ++ version "1.2.3" ++ resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" ++ integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + + wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= + ++worker-farm@^1.7.0: ++ version "1.7.0" ++ resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" ++ integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== ++ dependencies: ++ errno "~0.1.7" ++ + wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" +@@ -3905,11 +9971,29 @@ wrap-ansi@^2.0.0: + string-width "^1.0.1" + strip-ansi "^3.0.1" + ++wrap-ansi@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" ++ integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== ++ dependencies: ++ ansi-styles "^3.2.0" ++ string-width "^3.0.0" ++ strip-ansi "^5.0.0" ++ + wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + ++write-file-atomic@2.4.1: ++ version "2.4.1" ++ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.1.tgz#d0b05463c188ae804396fd5ab2a370062af87529" ++ integrity sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg== ++ dependencies: ++ graceful-fs "^4.1.11" ++ imurmurhash "^0.1.4" ++ signal-exit "^3.0.2" ++ + write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" +@@ -3917,33 +10001,65 @@ write@1.0.3: + dependencies: + mkdirp "^0.5.1" + ++ws@^5.2.0: ++ version "5.2.2" ++ resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" ++ integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== ++ dependencies: ++ async-limiter "~1.0.0" ++ ++ws@^6.2.1: ++ 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" ++ ++xml-name-validator@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" ++ integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== ++ + xml2js@^0.4.9: +- version "0.4.19" +- resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" +- integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== ++ version "0.4.22" ++ resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.22.tgz#4fa2d846ec803237de86f30aa9b5f70b6600de02" ++ integrity sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw== + dependencies: + sax ">=0.6.0" +- xmlbuilder "~9.0.1" ++ util.promisify "~1.0.0" ++ xmlbuilder "~11.0.0" + +-xmlbuilder@~9.0.1: +- version "9.0.7" +- resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" +- integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= ++xmlbuilder@~11.0.0: ++ version "11.0.1" ++ resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" ++ integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + +-xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: ++xtend@^4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +-"y18n@^3.2.1 || ^4.0.0": ++"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +-yallist@^3.0.0, yallist@^3.0.3: +- version "3.0.3" +- resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" +- integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== ++yallist@^2.1.2: ++ version "2.1.2" ++ resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" ++ integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= ++ ++yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: ++ version "3.1.1" ++ resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" ++ integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== ++ ++yargs-parser@10.x: ++ version "10.1.0" ++ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" ++ integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== ++ dependencies: ++ camelcase "^4.1.0" + + yargs-parser@^11.1.1: + version "11.1.1" +@@ -3953,7 +10069,15 @@ yargs-parser@^11.1.1: + camelcase "^5.0.0" + decamelize "^1.2.0" + +-yargs@^12.0.1: ++yargs-parser@^13.1.0, yargs-parser@^13.1.1: ++ version "13.1.1" ++ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" ++ integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== ++ dependencies: ++ camelcase "^5.0.0" ++ decamelize "^1.2.0" ++ ++yargs@12.0.5, yargs@^12.0.1: + version "12.0.5" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" + integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== +@@ -3970,3 +10094,49 @@ yargs@^12.0.1: + which-module "^2.0.0" + y18n "^3.2.1 || ^4.0.0" + yargs-parser "^11.1.1" ++ ++yargs@13.2.4: ++ version "13.2.4" ++ resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" ++ integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== ++ dependencies: ++ cliui "^5.0.0" ++ find-up "^3.0.0" ++ get-caller-file "^2.0.1" ++ os-locale "^3.1.0" ++ require-directory "^2.1.1" ++ require-main-filename "^2.0.0" ++ set-blocking "^2.0.0" ++ string-width "^3.0.0" ++ which-module "^2.0.0" ++ y18n "^4.0.0" ++ yargs-parser "^13.1.0" ++ ++yargs@^13.3.0: ++ version "13.3.0" ++ resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" ++ integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== ++ dependencies: ++ cliui "^5.0.0" ++ find-up "^3.0.0" ++ get-caller-file "^2.0.1" ++ require-directory "^2.1.1" ++ require-main-filename "^2.0.0" ++ set-blocking "^2.0.0" ++ string-width "^3.0.0" ++ which-module "^2.0.0" ++ y18n "^4.0.0" ++ yargs-parser "^13.1.1" ++ ++yauzl@^2.4.2: ++ version "2.10.0" ++ resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" ++ integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= ++ dependencies: ++ buffer-crc32 "~0.2.3" ++ fd-slicer "~1.1.0" ++ ++yn@^3.0.0: ++ version "3.1.1" ++ resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" ++ integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== diff --git a/web/src/pages/PullRequest/PullRequestDiff/example2.diff b/web/src/pages/PullRequest/PullRequestDiff/example2.diff new file mode 100644 index 000000000..6d2e3f443 --- /dev/null +++ b/web/src/pages/PullRequest/PullRequestDiff/example2.diff @@ -0,0 +1,358 @@ +diff --git a/README.md b/README.md +index 132c8a28..46909f25 100644 +--- a/README.md ++++ b/README.md +@@ -98,6 +98,9 @@ The HTML output accepts a Javascript object with configuration. Possible options + - `synchronisedScroll`: scroll both panes in side-by-side mode: `true` or `false`, default is `false` + - `matchWordsThreshold`: similarity threshold for word matching, default is 0.25 + - `matchingMaxComparisons`: perform at most this much comparisons for line matching a block of changes, default is `2500` ++ - `templates`: object with previously compiled templates to replace parts of the html ++ - `rawTemplates`: object with raw not compiled templates to replace parts of the html ++ > For more information regarding the possible templates look into [src/templates](https://github.com/rtfpessoa/diff2html/tree/master/src/templates) + + ## Diff2HtmlUI Helper + +diff --git a/scripts/hulk.js b/scripts/hulk.js +index 5a793c18..a4b1a4d5 100755 +--- a/scripts/hulk.js ++++ b/scripts/hulk.js +@@ -173,11 +173,11 @@ function namespace(name) { + // write a template foreach file that matches template extension + templates = extractFiles(options.argv.remain) + .map(function(file) { +- var openedFile = fs.readFileSync(file, 'utf-8'); ++ var openedFile = fs.readFileSync(file, 'utf-8').trim(); + var name; + if (!openedFile) return; + name = namespace(path.basename(file).replace(/\..*$/, '')); +- openedFile = removeByteOrderMark(openedFile.trim()); ++ openedFile = removeByteOrderMark(openedFile); + openedFile = wrap(file, name, openedFile); + if (!options.outputdir) return openedFile; + fs.writeFileSync(path.join(options.outputdir, name + '.js') +diff --git a/src/diff2html.js b/src/diff2html.js +index 21b0119e..64e138f5 100644 +--- a/src/diff2html.js ++++ b/src/diff2html.js +@@ -7,7 +7,6 @@ + + (function() { + var diffParser = require('./diff-parser.js').DiffParser; +- var fileLister = require('./file-list-printer.js').FileListPrinter; + var htmlPrinter = require('./html-printer.js').HtmlPrinter; + + function Diff2Html() { +@@ -43,7 +42,7 @@ + + var fileList = ''; + if (configOrEmpty.showFiles === true) { +- fileList = fileLister.generateFileList(diffJson, configOrEmpty); ++ fileList = htmlPrinter.generateFileListSummary(diffJson, configOrEmpty); + } + + var diffOutput = ''; +diff --git a/src/file-list-printer.js b/src/file-list-printer.js +index e408d9b2..1e0a2c61 100644 +--- a/src/file-list-printer.js ++++ b/src/file-list-printer.js +@@ -8,11 +8,16 @@ + (function() { + var printerUtils = require('./printer-utils.js').PrinterUtils; + +- var hoganUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ var hoganUtils; ++ + var baseTemplatesPath = 'file-summary'; + var iconsBaseTemplatesPath = 'icon'; + +- function FileListPrinter() { ++ function FileListPrinter(config) { ++ this.config = config; ++ ++ var HoganJsUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ hoganUtils = new HoganJsUtils(config); + } + + FileListPrinter.prototype.generateFileList = function(diffFiles) { +@@ -38,5 +43,5 @@ + }); + }; + +- module.exports.FileListPrinter = new FileListPrinter(); ++ module.exports.FileListPrinter = FileListPrinter; + })(); +diff --git a/src/hoganjs-utils.js b/src/hoganjs-utils.js +index 9949e5fa..b2e9c275 100644 +--- a/src/hoganjs-utils.js ++++ b/src/hoganjs-utils.js +@@ -8,18 +8,26 @@ + (function() { + var fs = require('fs'); + var path = require('path'); +- + var hogan = require('hogan.js'); + + var hoganTemplates = require('./templates/diff2html-templates.js'); + +- var templatesPath = path.resolve(__dirname, 'templates'); ++ var extraTemplates; ++ ++ function HoganJsUtils(configuration) { ++ this.config = configuration || {}; ++ extraTemplates = this.config.templates || {}; + +- function HoganJsUtils() { ++ var rawTemplates = this.config.rawTemplates || {}; ++ for (var templateName in rawTemplates) { ++ if (rawTemplates.hasOwnProperty(templateName)) { ++ if (!extraTemplates[templateName]) extraTemplates[templateName] = this.compile(rawTemplates[templateName]); ++ } ++ } + } + +- HoganJsUtils.prototype.render = function(namespace, view, params, configuration) { +- var template = this.template(namespace, view, configuration); ++ HoganJsUtils.prototype.render = function(namespace, view, params) { ++ var template = this.template(namespace, view); + if (template) { + return template.render(params); + } +@@ -27,17 +35,16 @@ + return null; + }; + +- HoganJsUtils.prototype.template = function(namespace, view, configuration) { +- var config = configuration || {}; ++ HoganJsUtils.prototype.template = function(namespace, view) { + var templateKey = this._templateKey(namespace, view); + +- return this._getTemplate(templateKey, config); ++ return this._getTemplate(templateKey); + }; + +- HoganJsUtils.prototype._getTemplate = function(templateKey, config) { ++ HoganJsUtils.prototype._getTemplate = function(templateKey) { + var template; + +- if (!config.noCache) { ++ if (!this.config.noCache) { + template = this._readFromCache(templateKey); + } + +@@ -53,6 +60,7 @@ + + try { + if (fs.readFileSync) { ++ var templatesPath = path.resolve(__dirname, 'templates'); + var templatePath = path.join(templatesPath, templateKey); + var templateContent = fs.readFileSync(templatePath + '.mustache', 'utf8'); + template = hogan.compile(templateContent); +@@ -66,12 +74,16 @@ + }; + + HoganJsUtils.prototype._readFromCache = function(templateKey) { +- return hoganTemplates[templateKey]; ++ return extraTemplates[templateKey] || hoganTemplates[templateKey]; + }; + + HoganJsUtils.prototype._templateKey = function(namespace, view) { + return namespace + '-' + view; + }; + +- module.exports.HoganJsUtils = new HoganJsUtils(); ++ HoganJsUtils.prototype.compile = function(templateStr) { ++ return hogan.compile(templateStr); ++ }; ++ ++ module.exports.HoganJsUtils = HoganJsUtils; + })(); +diff --git a/src/html-printer.js b/src/html-printer.js +index 585d5b66..13f83047 100644 +--- a/src/html-printer.js ++++ b/src/html-printer.js +@@ -8,6 +8,7 @@ + (function() { + var LineByLinePrinter = require('./line-by-line-printer.js').LineByLinePrinter; + var SideBySidePrinter = require('./side-by-side-printer.js').SideBySidePrinter; ++ var FileListPrinter = require('./file-list-printer.js').FileListPrinter; + + function HtmlPrinter() { + } +@@ -22,5 +23,10 @@ + return sideBySidePrinter.generateSideBySideJsonHtml(diffFiles); + }; + ++ HtmlPrinter.prototype.generateFileListSummary = function(diffJson, config) { ++ var fileListPrinter = new FileListPrinter(config); ++ return fileListPrinter.generateFileList(diffJson); ++ }; ++ + module.exports.HtmlPrinter = new HtmlPrinter(); + })(); +diff --git a/src/line-by-line-printer.js b/src/line-by-line-printer.js +index b07eb53c..d230bedd 100644 +--- a/src/line-by-line-printer.js ++++ b/src/line-by-line-printer.js +@@ -11,7 +11,8 @@ + var utils = require('./utils.js').Utils; + var Rematch = require('./rematch.js').Rematch; + +- var hoganUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ var hoganUtils; ++ + var genericTemplatesPath = 'generic'; + var baseTemplatesPath = 'line-by-line'; + var iconsBaseTemplatesPath = 'icon'; +@@ -19,6 +20,9 @@ + + function LineByLinePrinter(config) { + this.config = config; ++ ++ var HoganJsUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ hoganUtils = new HoganJsUtils(config); + } + + LineByLinePrinter.prototype.makeFileDiffHtml = function(file, diffs) { +diff --git a/src/side-by-side-printer.js b/src/side-by-side-printer.js +index bbf1dc8d..5e3033b3 100644 +--- a/src/side-by-side-printer.js ++++ b/src/side-by-side-printer.js +@@ -11,7 +11,8 @@ + var utils = require('./utils.js').Utils; + var Rematch = require('./rematch.js').Rematch; + +- var hoganUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ var hoganUtils; ++ + var genericTemplatesPath = 'generic'; + var baseTemplatesPath = 'side-by-side'; + var iconsBaseTemplatesPath = 'icon'; +@@ -26,6 +27,9 @@ + + function SideBySidePrinter(config) { + this.config = config; ++ ++ var HoganJsUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ hoganUtils = new HoganJsUtils(config); + } + + SideBySidePrinter.prototype.makeDiffHtml = function(file, diffs) { +diff --git a/test/file-list-printer-tests.js b/test/file-list-printer-tests.js +index a502a46f..60ea3208 100644 +--- a/test/file-list-printer-tests.js ++++ b/test/file-list-printer-tests.js +@@ -1,6 +1,6 @@ + var assert = require('assert'); + +-var fileListPrinter = require('../src/file-list-printer.js').FileListPrinter; ++var fileListPrinter = new (require('../src/file-list-printer.js').FileListPrinter)(); + + describe('FileListPrinter', function() { + describe('generateFileList', function() { +diff --git a/test/hogan-cache-tests.js b/test/hogan-cache-tests.js +index 190bf6f8..a34839c0 100644 +--- a/test/hogan-cache-tests.js ++++ b/test/hogan-cache-tests.js +@@ -1,6 +1,6 @@ + var assert = require('assert'); + +-var HoganJsUtils = require('../src/hoganjs-utils.js').HoganJsUtils; ++var HoganJsUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(); + var diffParser = require('../src/diff-parser.js').DiffParser; + + describe('HoganJsUtils', function() { +@@ -21,16 +21,50 @@ describe('HoganJsUtils', function() { + }); + assert.equal(emptyDiffHtml, result); + }); ++ + it('should render view without cache', function() { + var result = HoganJsUtils.render('generic', 'empty-diff', { + contentClass: 'd2h-code-line', + diffParser: diffParser + }, {noCache: true}); +- assert.equal(emptyDiffHtml + '\n', result); ++ assert.equal(emptyDiffHtml, result); + }); ++ + it('should return null if template is missing', function() { +- var result = HoganJsUtils.render('generic', 'missing-template', {}, {noCache: true}); ++ var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)({noCache: true}); ++ var result = hoganUtils.render('generic', 'missing-template', {}); + assert.equal(null, result); + }); ++ ++ it('should allow templates to be overridden with compiled templates', function() { ++ var emptyDiffTemplate = HoganJsUtils.compile('

    {{myName}}

    '); ++ ++ var config = {templates: {'generic-empty-diff': emptyDiffTemplate}}; ++ var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(config); ++ var result = hoganUtils.render('generic', 'empty-diff', {myName: 'Rodrigo Fernandes'}); ++ assert.equal('

    Rodrigo Fernandes

    ', result); ++ }); ++ ++ it('should allow templates to be overridden with uncompiled templates', function() { ++ var emptyDiffTemplate = '

    {{myName}}

    '; ++ ++ var config = {rawTemplates: {'generic-empty-diff': emptyDiffTemplate}}; ++ var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(config); ++ var result = hoganUtils.render('generic', 'empty-diff', {myName: 'Rodrigo Fernandes'}); ++ assert.equal('

    Rodrigo Fernandes

    ', result); ++ }); ++ ++ it('should allow templates to be overridden giving priority to compiled templates', function() { ++ var emptyDiffTemplate = HoganJsUtils.compile('

    {{myName}}

    '); ++ var emptyDiffTemplateUncompiled = '

    Not used!

    '; ++ ++ var config = { ++ templates: {'generic-empty-diff': emptyDiffTemplate}, ++ rawTemplates: {'generic-empty-diff': emptyDiffTemplateUncompiled} ++ }; ++ var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(config); ++ var result = hoganUtils.render('generic', 'empty-diff', {myName: 'Rodrigo Fernandes'}); ++ assert.equal('

    Rodrigo Fernandes

    ', result); ++ }); + }); + }); +diff --git a/test/line-by-line-tests.js b/test/line-by-line-tests.js +index 1cd92073..8869b3df 100644 +--- a/test/line-by-line-tests.js ++++ b/test/line-by-line-tests.js +@@ -14,7 +14,7 @@ describe('LineByLinePrinter', function() { + ' File without changes\n' + + ' \n' + + ' \n' + +- '\n'; ++ ''; + + assert.equal(expected, fileHtml); + }); +@@ -422,7 +422,6 @@ describe('LineByLinePrinter', function() { + ' \n' + + ' \n' + + '\n' + +- '\n' + + ' \n' + + ' \n' + + ' \n' + +diff --git a/test/side-by-side-printer-tests.js b/test/side-by-side-printer-tests.js +index 76625f8e..771daaa5 100644 +--- a/test/side-by-side-printer-tests.js ++++ b/test/side-by-side-printer-tests.js +@@ -14,7 +14,7 @@ describe('SideBySidePrinter', function() { + ' File without changes\n' + + ' \n' + + ' \n' + +- '\n'; ++ ''; + + assert.equal(expectedRight, fileHtml.right); + assert.equal(expectedLeft, fileHtml.left); +@@ -324,7 +324,6 @@ describe('SideBySidePrinter', function() { + ' \n' + + ' \n' + + '\n' + +- '\n' + + ' \n' + + ' \n' + + ' \n' + diff --git a/web/src/pages/PullRequest/PullRequestMetaLine.module.scss b/web/src/pages/PullRequest/PullRequestMetaLine.module.scss new file mode 100644 index 000000000..f277d76c1 --- /dev/null +++ b/web/src/pages/PullRequest/PullRequestMetaLine.module.scss @@ -0,0 +1,43 @@ +.main { + .state { + --color: var(--green-700) !important; + --bg: var(--green-50) !important; + + color: var(--color); + background-color: var(--bg); + font-size: 10px !important; + font-weight: 600 !important; + padding: 2px 6px !important; + border-radius: 4px; + + &.merged { + --color: var(--purple-700) !important; + --bg: var(--purple-50) !important; + } + + &.closed { + --color: var(--grey-700) !important; + --bg: var(--grey-100) !important; + } + + &.rejected { + --color: var(--red-700) !important; + --bg: var(--red-50) !important; + } + } + + .metaline { + font-size: 12px !important; + font-weight: 500 !important; + line-height: 20px !important; + color: var(--grey-500) !important; + + &.time { + color: var(--grey-400) !important; + } + + strong { + color: var(--grey-700) !important; + } + } +} diff --git a/web/src/pages/PullRequest/PullRequestMetadataInfo.module.scss.d.ts b/web/src/pages/PullRequest/PullRequestMetaLine.module.scss.d.ts similarity index 71% rename from web/src/pages/PullRequest/PullRequestMetadataInfo.module.scss.d.ts rename to web/src/pages/PullRequest/PullRequestMetaLine.module.scss.d.ts index 8c4a304fe..00c032b73 100644 --- a/web/src/pages/PullRequest/PullRequestMetadataInfo.module.scss.d.ts +++ b/web/src/pages/PullRequest/PullRequestMetaLine.module.scss.d.ts @@ -3,6 +3,9 @@ declare const styles: { readonly main: string readonly state: string + readonly merged: string + readonly closed: string + readonly rejected: string readonly metaline: string readonly time: string } diff --git a/web/src/pages/PullRequest/PullRequestMetaLine.tsx b/web/src/pages/PullRequest/PullRequestMetaLine.tsx new file mode 100644 index 000000000..f47a4e7b8 --- /dev/null +++ b/web/src/pages/PullRequest/PullRequestMetaLine.tsx @@ -0,0 +1,87 @@ +import React from 'react' +import { Container, Text, Layout, Color, StringSubstitute, IconName } from '@harness/uicore' +import cx from 'classnames' +import ReactTimeago from 'react-timeago' +import { CodeIcon, GitInfoProps, PullRequestState } from 'utils/GitUtils' +import { useAppContext } from 'AppContext' +import { useStrings } from 'framework/strings' +import { PipeSeparator } from 'components/PipeSeparator/PipeSeparator' +import { GitRefLink } from 'components/GitRefLink/GitRefLink' +import type { PullRequestResponse } from 'utils/types' +import css from './PullRequestMetaLine.module.scss' + +export const PullRequestMetaLine: React.FC> = ({ + repoMetadata, + targetBranch, + sourceBranch, + createdBy = '', + updated, + merged, + state +}) => { + const { getString } = useStrings() + const { routes } = useAppContext() + const vars = { + user: {createdBy}, + number: 5, // TODO: No data from backend now + target: ( + + ), + source: ( + + ) + } + + return ( + + + + + + + + + + + + + ) +} + +const PullRequestStateLabel: React.FC<{ state: PullRequestState }> = ({ state }) => { + const { getString } = useStrings() + + let color = Color.GREEN_700 + let icon: IconName = CodeIcon.PullRequest + let clazz: typeof css | string = '' + + switch (state) { + case PullRequestState.MERGED: + color = Color.PURPLE_700 + icon = CodeIcon.PullRequest + clazz = css.merged + break + case PullRequestState.CLOSED: + color = Color.GREY_600 + icon = CodeIcon.PullRequest + clazz = css.closed + break + case PullRequestState.REJECTED: + color = Color.RED_600 + icon = CodeIcon.PullRequestRejected + clazz = css.rejected + break + } + + return ( + + + + ) +} diff --git a/web/src/pages/PullRequest/PullRequestMetadataInfo.module.scss b/web/src/pages/PullRequest/PullRequestMetadataInfo.module.scss deleted file mode 100644 index 5f0acf624..000000000 --- a/web/src/pages/PullRequest/PullRequestMetadataInfo.module.scss +++ /dev/null @@ -1,25 +0,0 @@ -.main { - .state { - color: var(--green-700) !important; - background-color: var(--green-50) !important; - font-size: 9px !important; - font-weight: 600 !important; - padding: 2px 6px !important; - border-radius: 4px; - } - - .metaline { - font-size: 12px !important; - font-weight: 500 !important; - line-height: 20px !important; - color: var(--grey-500) !important; - - &.time { - color: var(--grey-400) !important; - } - - strong { - color: var(--grey-700) !important; - } - } -} diff --git a/web/src/pages/PullRequest/PullRequestMetadataInfo.tsx b/web/src/pages/PullRequest/PullRequestMetadataInfo.tsx deleted file mode 100644 index bae6d3e25..000000000 --- a/web/src/pages/PullRequest/PullRequestMetadataInfo.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react' -import { Container, Text, Layout, Color } from '@harness/uicore' -import cx from 'classnames' -import ReactTimeago from 'react-timeago' -import { CodeIcon, GitInfoProps } from 'utils/GitUtils' -// import { useAppContext } from 'AppContext' -import { useStrings } from 'framework/strings' -import { PipeSeparator } from 'components/PipeSeparator/PipeSeparator' -import { StringSubstitute } from 'components/StringSubstitute/StringSubstitute' -import { GitRefLink } from 'components/GitRefLink/GitRefLink' -import type { PullRequestResponse } from 'utils/types' -import css from './PullRequestMetadataInfo.module.scss' - -export const PullRequestMetadataInfo: React.FC> = ({ - createdBy = '', - targetBranch, - sourceBranch, - updated - // repoMetadata -}) => { - const { getString } = useStrings() - // const { routes } = useAppContext() - const vars = { - user: {createdBy}, - number: 1, // TODO: No data from backend now - target: , - source: - } - - return ( - - - - Open - - - - - - - - - - - ) -} diff --git a/web/src/pages/PullRequest/PullRequestTabContentWrapper.tsx b/web/src/pages/PullRequest/PullRequestTabContentWrapper.tsx new file mode 100644 index 000000000..9bb960191 --- /dev/null +++ b/web/src/pages/PullRequest/PullRequestTabContentWrapper.tsx @@ -0,0 +1,30 @@ +import React from 'react' +import { Container, PageError } from '@harness/uicore' +import cx from 'classnames' +import { ContainerSpinner } from 'components/ContainerSpinner/ContainerSpinner' +import { getErrorMessage } from 'utils/Utils' +import css from './PullRequest.module.scss' + +interface PullRequestTabContentWrapperProps { + className?: string + loading?: boolean + error?: Unknown + onRetry: () => void +} + +export const PullRequestTabContentWrapper: React.FC = ({ + className, + loading, + error, + onRetry, + children +}) => ( + + {loading && } + {error && } + {!loading && !error && children} + +) diff --git a/web/src/pages/PullRequests/PullRequests.module.scss b/web/src/pages/PullRequests/PullRequests.module.scss index d1b1df197..e94728d15 100644 --- a/web/src/pages/PullRequests/PullRequests.module.scss +++ b/web/src/pages/PullRequests/PullRequests.module.scss @@ -1,4 +1,16 @@ .main { min-height: var(--page-min-height, 100%); background-color: var(--primary-bg) !important; + + .table { + .row { + height: 80px; + display: flex; + justify-content: center; + + .title { + font-weight: 600; + } + } + } } diff --git a/web/src/pages/PullRequests/PullRequests.module.scss.d.ts b/web/src/pages/PullRequests/PullRequests.module.scss.d.ts index 9e614bf2d..017eade24 100644 --- a/web/src/pages/PullRequests/PullRequests.module.scss.d.ts +++ b/web/src/pages/PullRequests/PullRequests.module.scss.d.ts @@ -2,5 +2,8 @@ // this is an auto-generated file declare const styles: { readonly main: string + readonly table: string + readonly row: string + readonly title: string } export default styles diff --git a/web/src/pages/PullRequests/PullRequests.tsx b/web/src/pages/PullRequests/PullRequests.tsx index f372dae1d..2f801d98c 100644 --- a/web/src/pages/PullRequests/PullRequests.tsx +++ b/web/src/pages/PullRequests/PullRequests.tsx @@ -1,20 +1,88 @@ -import React from 'react' -import { Button, Container, ButtonVariation, PageBody } from '@harness/uicore' +import React, { useMemo, useState } from 'react' +import { + Button, + Container, + ButtonVariation, + PageBody, + Text, + Color, + TableV2, + Layout, + StringSubstitute +} from '@harness/uicore' import { useHistory } from 'react-router-dom' +import { useGet } from 'restful-react' +import type { CellProps, Column } from 'react-table' +import ReactTimeago from 'react-timeago' import { CodeIcon, makeDiffRefs } from 'utils/GitUtils' import { useAppContext } from 'AppContext' import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata' import { useStrings } from 'framework/strings' import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader' -import { getErrorMessage } from 'utils/Utils' +import { getErrorMessage, LIST_FETCHING_PER_PAGE } from 'utils/Utils' import emptyStateImage from 'images/empty-state.svg' +import type { PullRequestResponse } from 'utils/types' +import { usePageIndex } from 'hooks/usePageIndex' +import { PullRequestsContentHeader } from './PullRequestsContentHeader/PullRequestsContentHeader' +import prOpenImg from './pull-request-open.svg' import css from './PullRequests.module.scss' export default function PullRequests() { const { getString } = useStrings() const history = useHistory() const { routes } = useAppContext() + const [searchTerm, setSearchTerm] = useState('') + const [pageIndex, setPageIndex] = usePageIndex() const { repoMetadata, error, loading, refetch } = useGetRepositoryMetadata() + const { + data, + error: prError, + loading: prLoading + } = useGet({ + path: `/api/v1/repos/${repoMetadata?.path}/+/pullreq`, + queryParams: { + per_page: LIST_FETCHING_PER_PAGE, + page: pageIndex + 1, + sort: 'date', + direction: 'desc', + include_commit: true, + query: searchTerm + }, + lazy: !repoMetadata + }) + const columns: Column[] = useMemo( + () => [ + { + id: 'title', + width: '100%', + Cell: ({ row }: CellProps) => { + return ( + + + + + + {row.original.title} + + + {row.original.number}, + time: , + user: row.original.createdBy + }} + /> + + + + + ) + } + } + ], + [getString] + ) return ( @@ -24,11 +92,13 @@ export default function PullRequests() { dataTooltipId="repositoryPullRequests" /> refetch()} noData={{ - when: () => repoMetadata !== null, + // TODO: Use NoDataCard, this won't render toolbar + // when search returns empty response + when: () => data?.length === 0, message: getString('pullRequestEmpty'), image: emptyStateImage, button: ( @@ -47,7 +117,39 @@ export default function PullRequests() { /> ) }}> - {/* TODO: Render pull request table here - https://www.figma.com/file/PgBvi804VdQNyLS8fD9K0p/SCM?node-id=1220%3A119902&t=D3DaDpST8oO95WSu-0 */} + {repoMetadata && ( + + { + setPageIndex(0) + }} + onSearchTermChanged={value => { + setSearchTerm(value) + setPageIndex(0) + }} + /> + {!!data?.length && ( + + + className={css.table} + hideHeaders + columns={columns} + data={data} + getRowClassName={() => css.row} + onRowClick={row => { + history.push( + routes.toCODEPullRequest({ + repoPath: repoMetadata.path as string, + pullRequestId: String(row.number) + }) + ) + }} + /> + + )} + + )} ) diff --git a/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.module.scss b/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.module.scss new file mode 100644 index 000000000..99d681553 --- /dev/null +++ b/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.module.scss @@ -0,0 +1,16 @@ +.main { + div[class*='TextInput'] { + margin-bottom: 0 !important; + margin-left: 0 !important; + } + + > div { + align-items: center; + } + + padding-bottom: 0 !important; +} + +.branchDropdown { + background-color: var(--white); +} diff --git a/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.module.scss.d.ts b/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.module.scss.d.ts new file mode 100644 index 000000000..4978d5867 --- /dev/null +++ b/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.module.scss.d.ts @@ -0,0 +1,7 @@ +/* eslint-disable */ +// this is an auto-generated file +declare const styles: { + readonly main: string + readonly branchDropdown: string +} +export default styles diff --git a/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.tsx b/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.tsx new file mode 100644 index 000000000..f55f7e9ab --- /dev/null +++ b/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.tsx @@ -0,0 +1,78 @@ +import { useHistory } from 'react-router-dom' +import React, { useMemo, useState } from 'react' +import { Container, Layout, FlexExpander, DropDown, ButtonVariation, TextInput, Button } from '@harness/uicore' +import { useStrings } from 'framework/strings' +import { CodeIcon, GitInfoProps, makeDiffRefs, PullRequestFilterOption } from 'utils/GitUtils' +import { useAppContext } from 'AppContext' +import css from './PullRequestsContentHeader.module.scss' + +interface PullRequestsContentHeaderProps extends Pick { + activePullRequestFilterOption?: string + onPullRequestFilterChanged: (filter: string) => void + onSearchTermChanged: (searchTerm: string) => void +} + +export function PullRequestsContentHeader({ + onPullRequestFilterChanged, + onSearchTermChanged, + activePullRequestFilterOption = PullRequestFilterOption.ALL, + repoMetadata +}: PullRequestsContentHeaderProps) { + const history = useHistory() + const { routes } = useAppContext() + const { getString } = useStrings() + const [filterOption, setFilterOption] = useState(activePullRequestFilterOption) + const [searchTerm, setSearchTerm] = useState('') + const items = useMemo( + () => [ + { label: getString('open'), value: PullRequestFilterOption.OPEN }, + { label: getString('merged'), value: PullRequestFilterOption.MERGED }, + { label: getString('closed'), value: PullRequestFilterOption.CLOSED }, + { label: getString('rejected'), value: PullRequestFilterOption.REJECTED }, + { label: getString('yours'), value: PullRequestFilterOption.YOURS }, + { label: getString('all'), value: PullRequestFilterOption.ALL } + ], + [getString] + ) + + return ( + + + { + setFilterOption(value as string) + onPullRequestFilterChanged(value as string) + }} + popoverClassName={css.branchDropdown} + /> + + event.target.select()} + value={searchTerm} + onInput={event => { + const value = event.currentTarget.value + setSearchTerm(value) + onSearchTermChanged(value) + }} + /> +