From 94f58a505b3f344286e81bac655a2ea4e4ad859a Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Tue, 28 Jul 2020 16:21:47 +0300 Subject: [PATCH 01/53] CVAT UI: batch of fixes (#1952) --- .stylelintrc.json | 8 ++++++-- CHANGELOG.md | 3 ++- cvat-canvas/src/typescript/canvasView.ts | 9 +++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.stylelintrc.json b/.stylelintrc.json index 528bc373..4a37e44d 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -11,6 +11,10 @@ "selector-type-no-unknown": [true, { "ignoreTypes": ["first-child"] }] - } - + }, + "ignoreFiles": [ + "**/*.js", + "**/*.ts", + "**/*.py" + ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index a2ae5ce7..231738bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Points are dublicated during polygon interpolation sometimes () - When redraw a shape with activated autobordering, previous points are visible () - No mapping between side object element and context menu in some attributes () -- Interpolated shapes exported as `keyframe = True` (https://github.com/opencv/cvat/pull/1937) +- Interpolated shapes exported as `keyframe = True` () +- Stylelint filetype scans () ### Security - diff --git a/cvat-canvas/src/typescript/canvasView.ts b/cvat-canvas/src/typescript/canvasView.ts index 7194b0da..4eb95a8f 100644 --- a/cvat-canvas/src/typescript/canvasView.ts +++ b/cvat-canvas/src/typescript/canvasView.ts @@ -189,7 +189,7 @@ export class CanvasViewImpl implements CanvasView, Listener { } private onEditDone(state: any, points: number[]): void { - if (state && points) { + if (state && points) { const event: CustomEvent = new CustomEvent('canvas.edited', { bubbles: false, cancelable: true, @@ -1732,7 +1732,12 @@ export class CanvasViewImpl implements CanvasView, Listener { private addText(state: any): SVG.Text { const { undefinedAttrValue } = this.configuration; - const { label, clientID, attributes, source } = state; + const { + label, + clientID, + attributes, + source, + } = state; const attrNames = label.attributes.reduce((acc: any, val: any): void => { acc[val.id] = val.name; return acc; From 7679434bc200385d5ceb7544ac2f094403756587 Mon Sep 17 00:00:00 2001 From: Liron Ilouz <43831550+ilouzl@users.noreply.github.com> Date: Tue, 28 Jul 2020 16:46:45 +0300 Subject: [PATCH 02/53] add https flag to python cli (#1942) * add https flag to python cli * update changelog Co-authored-by: Liron Ilouz --- CHANGELOG.md | 1 + utils/cli/README.md | 2 ++ utils/cli/cli.py | 2 +- utils/cli/core/core.py | 5 +++-- utils/cli/core/definition.py | 6 ++++++ 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 231738bc..cf868054 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Source type support for tags, shapes and tracks () - Source type support for CVAT Dumper/Loader () - Intelligent polygon editing () +- python cli over https () ### Changed - Smaller object details () diff --git a/utils/cli/README.md b/utils/cli/README.md index 07b708d7..f582e2e3 100644 --- a/utils/cli/README.md +++ b/utils/cli/README.md @@ -31,6 +31,8 @@ optional arguments: host (default: localhost) --server-port SERVER_PORT port (default: 8080) + --https + using https connection (default: False) --debug show debug output ``` **Examples** diff --git a/utils/cli/cli.py b/utils/cli/cli.py index 9ac826b4..ae08ad1a 100755 --- a/utils/cli/cli.py +++ b/utils/cli/cli.py @@ -28,7 +28,7 @@ def main(): args = parser.parse_args() config_log(args.loglevel) with requests.Session() as session: - api = CVAT_API_V1('%s:%s' % (args.server_host, args.server_port)) + api = CVAT_API_V1('%s:%s' % (args.server_host, args.server_port), args.https) cli = CLI(session, api, args.auth) try: actions[args.action](cli, **args.__dict__) diff --git a/utils/cli/core/core.py b/utils/cli/core/core.py index a5136428..a9386884 100644 --- a/utils/cli/core/core.py +++ b/utils/cli/core/core.py @@ -179,8 +179,9 @@ class CLI(): class CVAT_API_V1(): """ Build parameterized API URLs """ - def __init__(self, host): - self.base = 'http://{}/api/v1/'.format(host) + def __init__(self, host, https=False): + prefix = 'https' if https else 'http' + self.base = '{}://{}/api/v1/'.format(prefix, host) @property def tasks(self): diff --git a/utils/cli/core/definition.py b/utils/cli/core/definition.py index d8892d19..4e1937eb 100644 --- a/utils/cli/core/definition.py +++ b/utils/cli/core/definition.py @@ -78,6 +78,12 @@ parser.add_argument( default='8080', help='port (default: %(default)s)' ) +parser.add_argument( + '--https', + default=False, + action='store_true', + help='using https connection (default: %(default)s)' +) parser.add_argument( '--debug', action='store_const', From 667a3f92fed31655e7e9e711a7703b32228c686d Mon Sep 17 00:00:00 2001 From: Dmitry Kalinin Date: Wed, 29 Jul 2020 12:22:02 +0300 Subject: [PATCH 03/53] CVAT UI: batch of fixes (#1955) --- CHANGELOG.md | 1 + cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- .../annotations-filters-input.tsx | 2 +- .../attribute-switcher.tsx | 6 +- .../object-switcher.tsx | 6 +- .../canvas-point-context-menu.tsx | 2 +- .../standard-workspace/canvas-wrapper.tsx | 2 +- .../controls-side-bar/cursor-control.tsx | 2 +- .../controls-side-bar/dextr-plugin.tsx | 2 +- .../controls-side-bar/draw-shape-popover.tsx | 4 +- .../controls-side-bar/fit-control.tsx | 2 +- .../controls-side-bar/group-control.tsx | 2 +- .../controls-side-bar/merge-control.tsx | 2 +- .../controls-side-bar/move-control.tsx | 2 +- .../controls-side-bar/resize-control.tsx | 2 +- .../controls-side-bar/rotate-control.tsx | 4 +- .../controls-side-bar/setup-tag-popover.tsx | 2 +- .../controls-side-bar/split-control.tsx | 2 +- .../objects-side-bar/object-item-basics.tsx | 2 +- .../objects-side-bar/object-item-buttons.tsx | 26 +++---- .../objects-side-bar/object-item-menu.tsx | 10 +-- .../objects-side-bar/objects-list-header.tsx | 6 +- .../shortcuts-select.tsx | 67 ++++++++++--------- .../top-bar/player-buttons.tsx | 16 ++--- .../top-bar/player-navigation.tsx | 6 +- .../annotation-page/top-bar/reid-plugin.tsx | 6 +- .../annotation-page/top-bar/right-group.tsx | 2 +- .../top-bar/statistics-modal.tsx | 2 +- .../create-model-content.tsx | 14 ++-- .../create-model-page/create-model-form.tsx | 2 +- .../advanced-configuration-form.tsx | 7 +- .../create-task-page/create-task-content.tsx | 4 +- cvat-ui/src/components/cvat-app.tsx | 1 + .../global-error-boundary.tsx | 2 +- .../labels-editor/constructor-viewer-item.tsx | 4 +- .../components/labels-editor/label-form.tsx | 16 ++--- .../labels-editor/labels-editor.tsx | 2 +- .../components/labels-editor/raw-viewer.tsx | 4 +- .../model-runner-modal/model-runner-modal.tsx | 4 +- cvat-ui/src/components/task-page/job-list.tsx | 10 +-- .../src/components/tasks-page/task-item.tsx | 2 +- cvat-ui/src/containers/header/header.tsx | 2 +- cvat-ui/src/utils/enviroment.ts | 3 + 44 files changed, 141 insertions(+), 128 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf868054..e50e059a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - No mapping between side object element and context menu in some attributes () - Interpolated shapes exported as `keyframe = True` () - Stylelint filetype scans () +- Fixed toolip closing issue () ### Security - diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 26e0217c..f6ff3fd8 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.6.4", + "version": "1.6.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index add2deab..922033db 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.6.4", + "version": "1.6.5", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { diff --git a/cvat-ui/src/components/annotation-page/annotations-filters-input.tsx b/cvat-ui/src/components/annotation-page/annotations-filters-input.tsx index f2ddbac9..f11893db 100644 --- a/cvat-ui/src/components/annotation-page/annotations-filters-input.tsx +++ b/cvat-ui/src/components/annotation-page/annotations-filters-input.tsx @@ -147,7 +147,7 @@ function AnnotationsFiltersInput(props: StateToProps & DispatchToProps): JSX.Ele placeholder={ underCursor ? ( <> - + { diff --git a/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-switcher.tsx b/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-switcher.tsx index da835b60..23675d0b 100644 --- a/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-switcher.tsx +++ b/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-switcher.tsx @@ -28,16 +28,16 @@ function AttributeSwitcher(props: Props): JSX.Element { const title = `${currentAttribute} [${currentIndex + 1}/${attributesCount}]`; return (
- + - + {currentAttribute} {` [${currentIndex + 1}/${attributesCount}]`} - + diff --git a/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/object-switcher.tsx b/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/object-switcher.tsx index 97e77d0b..a6a92a56 100644 --- a/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/object-switcher.tsx +++ b/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/object-switcher.tsx @@ -32,17 +32,17 @@ function ObjectSwitcher(props: Props): JSX.Element { const title = `${currentLabel} ${clientID} [${currentIndex + 1}/${objectsCount}]`; return (
- + - + {currentLabel} {` ${clientID} `} {`[${currentIndex + 1}/${objectsCount}]`} - + diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-point-context-menu.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-point-context-menu.tsx index 2e782a4f..9d6f56c0 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-point-context-menu.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-point-context-menu.tsx @@ -111,7 +111,7 @@ function CanvasPointContextMenu(props: Props): React.ReactPortal | null { return visible && contextMenuFor && type === ContextMenuType.CANVAS_SHAPE_POINT ? (ReactDOM.createPortal(
- + diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx index b10cd3d6..14a13014 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx @@ -876,7 +876,7 @@ export default class CanvasWrapperComponent extends React.PureComponent { defaultValue={0} onChange={(value: SliderValue): void => onSwitchZLayer(value as number)} /> - +
diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/cursor-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/cursor-control.tsx index 0222008d..e4f0ec15 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/cursor-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/cursor-control.tsx @@ -24,7 +24,7 @@ function CursorControl(props: Props): JSX.Element { } = props; return ( - + + - + - + diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/fit-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/fit-control.tsx index 4de7cfc4..0ad4e788 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/fit-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/fit-control.tsx @@ -19,7 +19,7 @@ function FitControl(props: Props): JSX.Element { } = props; return ( - + canvasInstance.fit()} /> ); diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/group-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/group-control.tsx index 968b4b3f..15cf9be1 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/group-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/group-control.tsx @@ -45,7 +45,7 @@ function GroupControl(props: Props): JSX.Element { const title = `Group shapes/tracks ${switchGroupShortcut}.` + ` Select and press ${resetGroupShortcut} to reset a group`; return ( - + ); diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/merge-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/merge-control.tsx index c70a90c0..2ac9f432 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/merge-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/merge-control.tsx @@ -41,7 +41,7 @@ function MergeControl(props: Props): JSX.Element { }; return ( - + ); diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/move-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/move-control.tsx index 3446a595..1a25f2bf 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/move-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/move-control.tsx @@ -19,7 +19,7 @@ function MoveControl(props: Props): JSX.Element { const { canvasInstance, activeControl } = props; return ( - + + - + rotateFrame(Rotation.ANTICLOCKWISE90)} component={RotateIcon} /> - + rotateFrame(Rotation.CLOCKWISE90)} diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx index 3366079d..11c1c1f6 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/setup-tag-popover.tsx @@ -61,7 +61,7 @@ function SetupTagPopover(props: Props): JSX.Element { - + diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/split-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/split-control.tsx index 7624e6f0..e700d287 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/split-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/split-control.tsx @@ -41,7 +41,7 @@ function SplitControl(props: Props): JSX.Element { }; return ( - + ); diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item-basics.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item-basics.tsx index 08536f87..99a243b8 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item-basics.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item-basics.tsx @@ -74,7 +74,7 @@ function ItemTopComponent(props: Props): JSX.Element { {type} - + { - onChangeShortcutLabel(value, Number.parseInt(id, 10)); - }} - size='default' - style={{ width: 200 }} - className='cvat-tag-annotation-label-select' - > - - - None - - - { - (labels as any[]).map((label: any) => ( - - {label.name} + { + shift(Object.keys(shortcutLabelMap), 1).slice(0, Math.min(labels.length, 10)) + .map((id) => ( + + + {`Key ${id}:`} + - - - ))} + { + (labels as any[]).map((label: any) => ( + + {label.name} + + )) + } + + + + )) + }
); }; diff --git a/cvat-ui/src/components/annotation-page/top-bar/player-buttons.tsx b/cvat-ui/src/components/annotation-page/top-bar/player-buttons.tsx index 5033c9be..2813e729 100644 --- a/cvat-ui/src/components/annotation-page/top-bar/player-buttons.tsx +++ b/cvat-ui/src/components/annotation-page/top-bar/player-buttons.tsx @@ -54,19 +54,19 @@ function PlayerButtons(props: Props): JSX.Element { return ( - + - + - + {!playing ? ( - + ) : ( - + )} - + - + - + diff --git a/cvat-ui/src/components/annotation-page/top-bar/player-navigation.tsx b/cvat-ui/src/components/annotation-page/top-bar/player-navigation.tsx index bf723a77..f536b081 100644 --- a/cvat-ui/src/components/annotation-page/top-bar/player-navigation.tsx +++ b/cvat-ui/src/components/annotation-page/top-bar/player-navigation.tsx @@ -62,19 +62,19 @@ function PlayerNavigation(props: Props): JSX.Element { - + {frameFilename} - + - + - + Similarity threshold: @@ -62,7 +62,7 @@ function InputModal(props: InputModalProps): JSX.Element { - + Max pixel distance: @@ -189,6 +189,8 @@ function ReIDPlugin(props: StateToProps & DispatchToProps): JSX.Element { }); await jobInstance.annotations.clear(); updateAnnotations(); // one more call to do not confuse canvas + // False positive of no-unsanitized/method + // eslint-disable-next-line no-unsanitized/method await jobInstance.annotations.import(merged); updateAnnotations(); } catch (error) { diff --git a/cvat-ui/src/components/annotation-page/top-bar/right-group.tsx b/cvat-ui/src/components/annotation-page/top-bar/right-group.tsx index ae7f8832..54c7723e 100644 --- a/cvat-ui/src/components/annotation-page/top-bar/right-group.tsx +++ b/cvat-ui/src/components/annotation-page/top-bar/right-group.tsx @@ -49,7 +49,7 @@ function RightGroup(props: Props): JSX.Element { value={workspace} > {Object.values(Workspace).map((ws) => ( - + {ws} ))} diff --git a/cvat-ui/src/components/annotation-page/top-bar/statistics-modal.tsx b/cvat-ui/src/components/annotation-page/top-bar/statistics-modal.tsx index eb4e3796..d68d58d9 100644 --- a/cvat-ui/src/components/annotation-page/top-bar/statistics-modal.tsx +++ b/cvat-ui/src/components/annotation-page/top-bar/statistics-modal.tsx @@ -89,7 +89,7 @@ export default function StatisticsModalComponent(props: Props): JSX.Element { }); const makeShapesTracksTitle = (title: string): JSX.Element => ( - + {title} diff --git a/cvat-ui/src/components/create-model-page/create-model-content.tsx b/cvat-ui/src/components/create-model-page/create-model-content.tsx index a320b805..a562bfce 100644 --- a/cvat-ui/src/components/create-model-page/create-model-content.tsx +++ b/cvat-ui/src/components/create-model-page/create-model-content.tsx @@ -18,8 +18,8 @@ import ConnectedFileManager, { } from 'containers/file-manager/file-manager'; import { ModelFiles } from 'reducers/interfaces'; -import CreateModelForm, { - CreateModelForm as WrappedCreateModelForm, +import WrappedCreateModelForm, { + CreateModelForm, } from './create-model-form'; interface Props { @@ -29,12 +29,12 @@ interface Props { } export default class CreateModelContent extends React.PureComponent { - private modelForm: WrappedCreateModelForm; + private modelForm: CreateModelForm; private fileManagerContainer: FileManagerContainer; public constructor(props: Props) { super(props); - this.modelForm = null as any as WrappedCreateModelForm; + this.modelForm = null as any as CreateModelForm; this.fileManagerContainer = null as any as FileManagerContainer; } @@ -107,7 +107,7 @@ export default class CreateModelContent extends React.PureComponent { return ( - + { // false positive @@ -119,9 +119,9 @@ export default class CreateModelContent extends React.PureComponent { - { + (ref: CreateModelForm): void => { this.modelForm = ref; } } diff --git a/cvat-ui/src/components/create-model-page/create-model-form.tsx b/cvat-ui/src/components/create-model-page/create-model-form.tsx index e1dbcb33..004e9645 100644 --- a/cvat-ui/src/components/create-model-page/create-model-form.tsx +++ b/cvat-ui/src/components/create-model-page/create-model-form.tsx @@ -57,7 +57,7 @@ export class CreateModelForm extends React.PureComponent { - + { getFieldDecorator('global', { initialValue: false, valuePropName: 'checked', diff --git a/cvat-ui/src/components/create-task-page/advanced-configuration-form.tsx b/cvat-ui/src/components/create-task-page/advanced-configuration-form.tsx index b038408b..a5ed8eae 100644 --- a/cvat-ui/src/components/create-task-page/advanced-configuration-form.tsx +++ b/cvat-ui/src/components/create-task-page/advanced-configuration-form.tsx @@ -142,7 +142,7 @@ class AdvancedConfigurationForm extends React.PureComponent { return ( Image quality}> - + {form.getFieldDecorator('imageQuality', { initialValue: 70, rules: [{ @@ -168,7 +168,7 @@ class AdvancedConfigurationForm extends React.PureComponent { return ( Overlap size}> - + {form.getFieldDecorator('overlapSize', { rules: [{ validator: isNonNegativeInteger, @@ -186,7 +186,7 @@ class AdvancedConfigurationForm extends React.PureComponent { return ( Segment size}> - + {form.getFieldDecorator('segmentSize', { rules: [{ validator: isPositiveInteger, @@ -403,6 +403,7 @@ class AdvancedConfigurationForm extends React.PureComponent { More: 1 - 4 )} + mouseLeaveDelay={0} > {form.getFieldDecorator('dataChunkSize', { rules: [{ diff --git a/cvat-ui/src/components/create-task-page/create-task-content.tsx b/cvat-ui/src/components/create-task-page/create-task-content.tsx index 2bd32807..7ee99a6a 100644 --- a/cvat-ui/src/components/create-task-page/create-task-content.tsx +++ b/cvat-ui/src/components/create-task-page/create-task-content.tsx @@ -10,7 +10,7 @@ import Collapse from 'antd/lib/collapse'; import notification from 'antd/lib/notification'; import Text from 'antd/lib/typography/Text'; -import FileManagerContainer from 'containers/file-manager/file-manager'; +import ConnectedFileManager from 'containers/file-manager/file-manager'; import BasicConfigurationForm, { BaseConfiguration } from './basic-configuration-form'; import AdvancedConfigurationForm, { AdvancedConfiguration } from './advanced-configuration-form'; import LabelsEditor from '../labels-editor/labels-editor'; @@ -184,7 +184,7 @@ export default class CreateTaskContent extends React.PureComponent * Select files: - { this.fileManagerContainer = container; } } diff --git a/cvat-ui/src/components/cvat-app.tsx b/cvat-ui/src/components/cvat-app.tsx index 9eeecd78..22dccb88 100644 --- a/cvat-ui/src/components/cvat-app.tsx +++ b/cvat-ui/src/components/cvat-app.tsx @@ -189,6 +189,7 @@ class CVATApplication extends React.PureComponent 200 ? 'Open the Browser Console to get details' : error, }); + // eslint-disable-next-line no-console console.error(error); } diff --git a/cvat-ui/src/components/global-error-boundary/global-error-boundary.tsx b/cvat-ui/src/components/global-error-boundary/global-error-boundary.tsx index fc8ca195..9be93aae 100644 --- a/cvat-ui/src/components/global-error-boundary/global-error-boundary.tsx +++ b/cvat-ui/src/components/global-error-boundary/global-error-boundary.tsx @@ -153,7 +153,7 @@ class GlobalErrorBoundary extends React.PureComponent {
  • - + {/* eslint-disable-next-line */} {copy(message)}}> Copy diff --git a/cvat-ui/src/components/labels-editor/constructor-viewer-item.tsx b/cvat-ui/src/components/labels-editor/constructor-viewer-item.tsx index a21962e0..67bf7937 100644 --- a/cvat-ui/src/components/labels-editor/constructor-viewer-item.tsx +++ b/cvat-ui/src/components/labels-editor/constructor-viewer-item.tsx @@ -27,7 +27,7 @@ export default function ConstructorViewerItem(props: ConstructorViewerItemProps) return (
    {label.name} - + { label.id < 0 && ( - + { return ( - + { form.getFieldDecorator(`type[${key}]`, { initialValue: type, })( @@ -187,7 +187,7 @@ class LabelForm extends React.PureComponent { }; return ( - + { form.getFieldDecorator(`values[${key}]`, { initialValue: existedValues, @@ -214,7 +214,7 @@ class LabelForm extends React.PureComponent { const { form } = this.props; return ( - + { form.getFieldDecorator(`values[${key}]`, { initialValue: value, @@ -304,7 +304,7 @@ class LabelForm extends React.PureComponent { return ( - + { form.getFieldDecorator(`mutable[${key}]`, { initialValue: value, valuePropName: 'checked', @@ -321,7 +321,7 @@ class LabelForm extends React.PureComponent { return ( - + | - @@ -150,7 +152,7 @@ function JobListComponent(props: Props & RouteComponentProps): JSX.Element { Jobs - + - - - ); - } -} diff --git a/cvat-ui/src/components/create-model-page/create-model-form.tsx b/cvat-ui/src/components/create-model-page/create-model-form.tsx deleted file mode 100644 index 004e9645..00000000 --- a/cvat-ui/src/components/create-model-page/create-model-form.tsx +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (C) 2020 Intel Corporation -// -// SPDX-License-Identifier: MIT - -import React from 'react'; -import { Row, Col } from 'antd/lib/grid'; -import Form, { FormComponentProps } from 'antd/lib/form/Form'; -import Input from 'antd/lib/input'; -import Tooltip from 'antd/lib/tooltip'; -import Checkbox from 'antd/lib/checkbox'; -import Text from 'antd/lib/typography/Text'; - -type Props = FormComponentProps; - -export class CreateModelForm extends React.PureComponent { - public submit(): Promise<{name: string; global: boolean}> { - const { form } = this.props; - return new Promise((resolve, reject) => { - form.validateFields((errors, values): void => { - if (!errors) { - resolve({ - name: values.name, - global: values.global, - }); - } else { - reject(errors); - } - }); - }); - } - - public resetFields(): void { - const { form } = this.props; - form.resetFields(); - } - - public render(): JSX.Element { - const { form } = this.props; - const { getFieldDecorator } = form; - - return ( -
    e.preventDefault()}> - - - * - Name: - - - - { getFieldDecorator('name', { - rules: [{ - required: true, - message: 'Please, specify a model name', - }], - })()} - - - - - - { getFieldDecorator('global', { - initialValue: false, - valuePropName: 'checked', - })( - - - Load globally - - , - )} - - - - -
    - ); - } -} - -export default Form.create()(CreateModelForm); diff --git a/cvat-ui/src/components/create-model-page/create-model-page.tsx b/cvat-ui/src/components/create-model-page/create-model-page.tsx deleted file mode 100644 index 7c81aca0..00000000 --- a/cvat-ui/src/components/create-model-page/create-model-page.tsx +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2020 Intel Corporation -// -// SPDX-License-Identifier: MIT - -import './styles.scss'; -import React from 'react'; -import { Row, Col } from 'antd/lib/grid'; -import Text from 'antd/lib/typography/Text'; - -import { ModelFiles } from 'reducers/interfaces'; -import CreateModelContent from './create-model-content'; - -interface Props { - createModel(name: string, files: ModelFiles, global: boolean): void; - isAdmin: boolean; - modelCreatingStatus: string; -} - -export default function CreateModelPageComponent(props: Props): JSX.Element { - const { - isAdmin, - modelCreatingStatus, - createModel, - } = props; - - return ( - - - Upload a new model - - - - ); -} diff --git a/cvat-ui/src/components/create-model-page/styles.scss b/cvat-ui/src/components/create-model-page/styles.scss deleted file mode 100644 index 65df22b2..00000000 --- a/cvat-ui/src/components/create-model-page/styles.scss +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2020 Intel Corporation -// -// SPDX-License-Identifier: MIT - -@import '../../base.scss'; - -.cvat-create-model-form-wrapper { - text-align: center; - margin-top: 40px; - overflow-y: auto; - height: 90%; - - > div > span { - font-size: 36px; - } - - .cvat-create-model-content { - margin-top: 20px; - width: 100%; - height: auto; - border: 1px solid $border-color-1; - border-radius: 3px; - padding: 20px; - background: $background-color-1; - text-align: initial; - - > div:nth-child(1) > i { - float: right; - font-size: 20px; - color: $danger-icon-color; - } - - > div:nth-child(4) { - margin-top: 10px; - } - - > div:nth-child(6) > button { - margin-top: 10px; - float: right; - width: 120px; - } - } -} diff --git a/cvat-ui/src/components/cvat-app.tsx b/cvat-ui/src/components/cvat-app.tsx index 22dccb88..19c26f66 100644 --- a/cvat-ui/src/components/cvat-app.tsx +++ b/cvat-ui/src/components/cvat-app.tsx @@ -18,7 +18,6 @@ import TasksPageContainer from 'containers/tasks-page/tasks-page'; import CreateTaskPageContainer from 'containers/create-task-page/create-task-page'; import TaskPageContainer from 'containers/task-page/task-page'; import ModelsPageContainer from 'containers/models-page/models-page'; -import CreateModelPageContainer from 'containers/create-model-page/create-model-page'; import AnnotationPageContainer from 'containers/annotation-page/annotation-page'; import LoginPageContainer from 'containers/login-page/login-page'; import RegisterPageContainer from 'containers/register-page/register-page'; @@ -50,9 +49,6 @@ interface CVATAppProps { usersFetching: boolean; aboutInitialized: boolean; aboutFetching: boolean; - installedAutoAnnotation: boolean; - installedTFAnnotation: boolean; - installedTFSegmentation: boolean; userAgreementsFetching: boolean; userAgreementsInitialized: boolean; notifications: NotificationsState; @@ -222,9 +218,6 @@ class CVATApplication extends React.PureComponent - {withModels - && } - {installedAutoAnnotation - && } + diff --git a/cvat-ui/src/components/header/header.tsx b/cvat-ui/src/components/header/header.tsx index dc01678b..9d3e5fee 100644 --- a/cvat-ui/src/components/header/header.tsx +++ b/cvat-ui/src/components/header/header.tsx @@ -24,9 +24,6 @@ interface HeaderContainerProps { switchSettingsDialog: (show: boolean) => void; logoutFetching: boolean; installedAnalytics: boolean; - installedAutoAnnotation: boolean; - installedTFAnnotation: boolean; - installedTFSegmentation: boolean; serverHost: string; username: string; toolName: string; @@ -43,9 +40,6 @@ type Props = HeaderContainerProps & RouteComponentProps; function HeaderContainer(props: Props): JSX.Element { const { - installedTFSegmentation, - installedAutoAnnotation, - installedTFAnnotation, installedAnalytics, username, toolName, @@ -62,10 +56,6 @@ function HeaderContainer(props: Props): JSX.Element { switchSettingsDialog, } = props; - const renderModels = installedAutoAnnotation - || installedTFAnnotation - || installedTFSegmentation; - const { CHANGELOG_URL, LICENSE_URL, @@ -172,19 +162,16 @@ function HeaderContainer(props: Props): JSX.Element { > Tasks - { renderModels - && ( - - )} + { installedAnalytics && (
    + ); + } + private renderContent(): JSX.Element { const { selectedModel, - cleanOut, + cleanup, mapping, } = this.state; const { @@ -311,8 +371,9 @@ export default class ModelRunnerModalComponent extends React.PureComponent _model.name === selectedModel)[0]; const excludedModelLabels: string[] = Object.keys(mapping); - const withMapping = model && !model.primary; - const tags = withMapping ? excludedModelLabels + const isDetector = model && model.type === 'detector'; + const isReId = model && model.type === 'reid'; + const tags = isDetector ? excludedModelLabels .map((modelLabel: string) => this.renderMappingTag( modelLabel, mapping[modelLabel], @@ -332,23 +393,24 @@ export default class ModelRunnerModalComponent extends React.PureComponent { this.renderModelSelector() } - { withMapping && tags} - { withMapping + { isDetector && tags} + { isDetector && mappingISAvailable && this.renderMappingInput(availableModelLabels, taskLabels)} - { withMapping + { isDetector && (
    this.setState({ - cleanOut: e.target.checked, + cleanup: e.target.checked, })} > Clean old annotations
    )} + { isReId && this.renderReidContent() }
); } @@ -357,7 +419,9 @@ export default class ModelRunnerModalComponent extends React.PureComponent model.name === selectedModel, )[0]; - const enabledSubmit = (!!activeModel - && activeModel.primary) || !!Object.keys(mapping).length; + const enabledSubmit = !!activeModel && (activeModel.type === 'reid' + || !!Object.keys(mapping).length); return ( visible && ( @@ -387,8 +451,13 @@ export default class ModelRunnerModalComponent extends React.PureComponent model.name === selectedModel)[0], - mapping, - cleanOut, + activeModel.type === 'detector' ? { + mapping, + cleanup, + } : { + threshold, + max_distance: maxDistance, + }, ); closeDialog(); }} diff --git a/cvat-ui/src/components/models-page/built-model-item.tsx b/cvat-ui/src/components/models-page/built-model-item.tsx index 83dda54e..f100dfe5 100644 --- a/cvat-ui/src/components/models-page/built-model-item.tsx +++ b/cvat-ui/src/components/models-page/built-model-item.tsx @@ -20,7 +20,7 @@ export default function BuiltModelItemComponent(props: Props): JSX.Element { return ( - Tensorflow + {model.framework} diff --git a/cvat-ui/src/components/models-page/deployed-model-item.tsx b/cvat-ui/src/components/models-page/deployed-model-item.tsx new file mode 100644 index 00000000..69ad3fcd --- /dev/null +++ b/cvat-ui/src/components/models-page/deployed-model-item.tsx @@ -0,0 +1,55 @@ +// Copyright (C) 2020 Intel Corporation +// +// SPDX-License-Identifier: MIT + +import React from 'react'; +import { Row, Col } from 'antd/lib/grid'; +import Tag from 'antd/lib/tag'; +import Select from 'antd/lib/select'; +import Text from 'antd/lib/typography/Text'; +import { Model } from 'reducers/interfaces'; + +interface Props { + model: Model; +} + +export default function DeployedModelItem(props: Props): JSX.Element { + const { model } = props; + + return ( + + + {model.framework} + + + + {model.name} + + + + + {model.type} + + + + {model.description} + + + + + + ); +} diff --git a/cvat-ui/src/components/models-page/built-models-list.tsx b/cvat-ui/src/components/models-page/deployed-models-list.tsx similarity index 63% rename from cvat-ui/src/components/models-page/built-models-list.tsx rename to cvat-ui/src/components/models-page/deployed-models-list.tsx index a71d3e4a..c9d9ec6e 100644 --- a/cvat-ui/src/components/models-page/built-models-list.tsx +++ b/cvat-ui/src/components/models-page/deployed-models-list.tsx @@ -7,35 +7,38 @@ import { Row, Col } from 'antd/lib/grid'; import Text from 'antd/lib/typography/Text'; import { Model } from 'reducers/interfaces'; -import BuiltModelItemComponent from './built-model-item'; +import DeployedModelItem from './deployed-model-item'; + interface Props { models: Model[]; } -export default function IntegratedModelsListComponent(props: Props): JSX.Element { +export default function DeployedModelsListComponent(props: Props): JSX.Element { const { models } = props; + const items = models.map((model): JSX.Element => ( - + )); return ( <> - - - Primary - - - + Framework - + Name - + + Type + + + Description + + Labels diff --git a/cvat-ui/src/components/models-page/empty-list.tsx b/cvat-ui/src/components/models-page/empty-list.tsx index e850cff9..3eb9bde7 100644 --- a/cvat-ui/src/components/models-page/empty-list.tsx +++ b/cvat-ui/src/components/models-page/empty-list.tsx @@ -3,14 +3,12 @@ // SPDX-License-Identifier: MIT import React from 'react'; -import { Link } from 'react-router-dom'; import Text from 'antd/lib/typography/Text'; import { Row, Col } from 'antd/lib/grid'; import Icon from 'antd/lib/icon'; -import { - EmptyTasksIcon as EmptyModelsIcon, -} from 'icons'; +import consts from 'consts'; +import { EmptyTasksIcon as EmptyModelsIcon } from 'icons'; export default function EmptyListComponent(): JSX.Element { return ( @@ -22,7 +20,7 @@ export default function EmptyListComponent(): JSX.Element { - No models uploaded yet ... + No models deployed yet... @@ -32,7 +30,8 @@ export default function EmptyListComponent(): JSX.Element { - upload a new model + deploy a model with + nuclio diff --git a/cvat-ui/src/components/models-page/models-page.tsx b/cvat-ui/src/components/models-page/models-page.tsx index 80c41eaf..7c744c8d 100644 --- a/cvat-ui/src/components/models-page/models-page.tsx +++ b/cvat-ui/src/components/models-page/models-page.tsx @@ -7,35 +7,23 @@ import React from 'react'; import Spin from 'antd/lib/spin'; import TopBarComponent from './top-bar'; -import UploadedModelsList from './uploaded-models-list'; -import BuiltModelsList from './built-models-list'; +import DeployedModelsList from './deployed-models-list'; import EmptyListComponent from './empty-list'; import FeedbackComponent from '../feedback/feedback'; import { Model } from '../../reducers/interfaces'; interface Props { - installedAutoAnnotation: boolean; - installedTFSegmentation: boolean; - installedTFAnnotation: boolean; modelsInitialized: boolean; modelsFetching: boolean; - registeredUsers: any[]; - models: Model[]; + deployedModels: Model[]; getModels(): void; - deleteModel(id: number): void; } export default function ModelsPageComponent(props: Props): JSX.Element { const { - installedAutoAnnotation, - installedTFSegmentation, - installedTFAnnotation, modelsInitialized, modelsFetching, - registeredUsers, - models, - - deleteModel, + deployedModels, } = props; if (!modelsInitialized) { @@ -47,26 +35,15 @@ export default function ModelsPageComponent(props: Props): JSX.Element { ); } - const uploadedModels = models.filter((model): boolean => model.id !== null); - const integratedModels = models.filter((model): boolean => model.id === null); - return (
- - { !!integratedModels.length - && } - { !!uploadedModels.length && ( - - )} - { installedAutoAnnotation - && !uploadedModels.length - && !installedTFAnnotation - && !installedTFSegmentation - && } + + { deployedModels.length + ? ( + + ) : ( + + )}
); diff --git a/cvat-ui/src/components/models-page/styles.scss b/cvat-ui/src/components/models-page/styles.scss index c67c893c..f566e92f 100644 --- a/cvat-ui/src/components/models-page/styles.scss +++ b/cvat-ui/src/components/models-page/styles.scss @@ -52,7 +52,7 @@ .cvat-models-list-item { width: 100%; - height: 60px; + height: auto; border: 1px solid $border-color-1; border-radius: 3px; margin-bottom: 15px; diff --git a/cvat-ui/src/components/models-page/top-bar.tsx b/cvat-ui/src/components/models-page/top-bar.tsx index b58abd73..584fa83c 100644 --- a/cvat-ui/src/components/models-page/top-bar.tsx +++ b/cvat-ui/src/components/models-page/top-bar.tsx @@ -3,49 +3,15 @@ // SPDX-License-Identifier: MIT import React from 'react'; -import { RouteComponentProps } from 'react-router'; -import { withRouter } from 'react-router-dom'; import { Row, Col } from 'antd/lib/grid'; -import Button from 'antd/lib/button'; import Text from 'antd/lib/typography/Text'; -type Props = { - installedAutoAnnotation: boolean; -} & RouteComponentProps; - -function TopBarComponent(props: Props): JSX.Element { - const { - installedAutoAnnotation, - history, - } = props; - +export default function TopBarComponent(): JSX.Element { return ( Models - - { installedAutoAnnotation - && ( - - )} - ); } - -export default withRouter(TopBarComponent); diff --git a/cvat-ui/src/components/models-page/uploaded-model-item.tsx b/cvat-ui/src/components/models-page/uploaded-model-item.tsx deleted file mode 100644 index b108ec8d..00000000 --- a/cvat-ui/src/components/models-page/uploaded-model-item.tsx +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (C) 2020 Intel Corporation -// -// SPDX-License-Identifier: MIT - -import React from 'react'; -import { Row, Col } from 'antd/lib/grid'; -import Tag from 'antd/lib/tag'; -import Select from 'antd/lib/select'; -import Icon from 'antd/lib/icon'; -import Menu from 'antd/lib/menu'; -import Dropdown from 'antd/lib/dropdown'; -import Text from 'antd/lib/typography/Text'; -import moment from 'moment'; - -import { MenuIcon } from 'icons'; -import { Model } from 'reducers/interfaces'; - -interface Props { - model: Model; - owner: any; - onDelete(): void; -} - -export default function UploadedModelItem(props: Props): JSX.Element { - const { - model, - owner, - onDelete, - } = props; - - return ( - - - OpenVINO - - - - {model.name} - - - - - {owner ? owner.username : 'undefined'} - - - - - {moment(model.uploadDate).format('MMMM Do YYYY')} - - - - - - - Actions - - { - onDelete(); - }} - key='delete' - > - Delete - - - ) - } - > - - - - - ); -} diff --git a/cvat-ui/src/components/models-page/uploaded-models-list.tsx b/cvat-ui/src/components/models-page/uploaded-models-list.tsx deleted file mode 100644 index be5a0354..00000000 --- a/cvat-ui/src/components/models-page/uploaded-models-list.tsx +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2020 Intel Corporation -// -// SPDX-License-Identifier: MIT - -import React from 'react'; -import { Row, Col } from 'antd/lib/grid'; -import Text from 'antd/lib/typography/Text'; - -import { Model } from 'reducers/interfaces'; -import UploadedModelItem from './uploaded-model-item'; - - -interface Props { - registeredUsers: any[]; - models: Model[]; - deleteModel(id: number): void; -} - -export default function UploadedModelsListComponent(props: Props): JSX.Element { - const { - models, - registeredUsers, - deleteModel, - } = props; - - const items = models.map((model): JSX.Element => { - const owner = registeredUsers.filter((user) => user.id === model.ownerID)[0]; - return ( - deleteModel(model.id as number)} - /> - ); - }); - - return ( - <> - - - Uploaded by a user - - - - - - - Framework - - - Name - - - Owner - - - Uploaded - - - Labels - - - - { items } - - - - ); -} diff --git a/cvat-ui/src/consts.ts b/cvat-ui/src/consts.ts index e0a94454..e5df33c7 100644 --- a/cvat-ui/src/consts.ts +++ b/cvat-ui/src/consts.ts @@ -11,8 +11,8 @@ const GITTER_PUBLIC_URL = 'https://gitter.im/opencv-cvat/public'; const FORUM_URL = 'https://software.intel.com/en-us/forums/intel-distribution-of-openvino-toolkit'; const GITHUB_URL = 'https://github.com/opencv/cvat'; const GITHUB_IMAGE_URL = 'https://raw.githubusercontent.com/opencv/cvat/develop/cvat/apps/documentation/static/documentation/images/cvat.jpg'; -const AUTO_ANNOTATION_GUIDE_URL = 'https://github.com/opencv/cvat/blob/develop/cvat/apps/auto_annotation/README.md'; const SHARE_MOUNT_GUIDE_URL = 'https://github.com/opencv/cvat/blob/master/cvat/apps/documentation/installation.md#share-path'; +const NUCLIO_GUIDE = 'https://github.com/opencv/cvat/blob/develop/cvat/apps/documentation/installation.md#semi-automatic-and-automatic-annotation'; const CANVAS_BACKGROUND_COLORS = ['#ffffff', '#f1f1f1', '#e5e5e5', '#d8d8d8', '#CCCCCC', '#B3B3B3', '#999999']; export default { @@ -25,7 +25,7 @@ export default { FORUM_URL, GITHUB_URL, GITHUB_IMAGE_URL, - AUTO_ANNOTATION_GUIDE_URL, SHARE_MOUNT_GUIDE_URL, CANVAS_BACKGROUND_COLORS, + NUCLIO_GUIDE, }; diff --git a/cvat-ui/src/containers/actions-menu/actions-menu.tsx b/cvat-ui/src/containers/actions-menu/actions-menu.tsx index a92a42bb..206201f7 100644 --- a/cvat-ui/src/containers/actions-menu/actions-menu.tsx +++ b/cvat-ui/src/containers/actions-menu/actions-menu.tsx @@ -28,9 +28,6 @@ interface StateToProps { loadActivity: string | null; dumpActivities: string[] | null; exportActivities: string[] | null; - installedTFAnnotation: boolean; - installedTFSegmentation: boolean; - installedAutoAnnotation: boolean; inferenceIsActive: boolean; } @@ -53,13 +50,6 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps { formats: { annotationFormats, }, - plugins: { - list: { - TF_ANNOTATION: installedTFAnnotation, - TF_SEGMENTATION: installedTFSegmentation, - AUTO_ANNOTATION: installedAutoAnnotation, - }, - }, tasks: { activities: { dumps, @@ -70,9 +60,6 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps { } = state; return { - installedTFAnnotation, - installedTFSegmentation, - installedAutoAnnotation, dumpActivities: tid in dumps ? dumps[tid] : null, exportActivities: tid in activeExports ? activeExports[tid] : null, loadActivity: tid in loads ? loads[tid] : null, @@ -112,9 +99,6 @@ function ActionsMenuContainer(props: OwnProps & StateToProps & DispatchToProps): dumpActivities, exportActivities, inferenceIsActive, - installedAutoAnnotation, - installedTFAnnotation, - installedTFSegmentation, loadAnnotations, dumpAnnotations, @@ -172,9 +156,6 @@ function ActionsMenuContainer(props: OwnProps & StateToProps & DispatchToProps): dumpActivities={dumpActivities} exportActivities={exportActivities} inferenceIsActive={inferenceIsActive} - installedAutoAnnotation={installedAutoAnnotation} - installedTFAnnotation={installedTFAnnotation} - installedTFSegmentation={installedTFSegmentation} onClickMenu={onClickMenu} /> ); diff --git a/cvat-ui/src/containers/annotation-page/top-bar/annotation-menu.tsx b/cvat-ui/src/containers/annotation-page/top-bar/annotation-menu.tsx index 139168a8..74edb4c2 100644 --- a/cvat-ui/src/containers/annotation-page/top-bar/annotation-menu.tsx +++ b/cvat-ui/src/containers/annotation-page/top-bar/annotation-menu.tsx @@ -26,7 +26,6 @@ interface StateToProps { loadActivity: string | null; dumpActivities: string[] | null; exportActivities: string[] | null; - installedReID: boolean; } interface DispatchToProps { @@ -56,9 +55,6 @@ function mapStateToProps(state: CombinedState): StateToProps { exports: activeExports, }, }, - plugins: { - list, - }, } = state; const taskID = jobInstance.task.id; @@ -71,7 +67,6 @@ function mapStateToProps(state: CombinedState): StateToProps { ? loads[taskID] || jobLoads[jobID] : null, jobInstance, annotationFormats, - installedReID: list.REID, }; } @@ -109,7 +104,6 @@ function AnnotationMenuContainer(props: Props): JSX.Element { loadActivity, dumpActivities, exportActivities, - installedReID, } = props; const onClickMenu = (params: ClickParam, file?: File): void => { @@ -155,7 +149,6 @@ function AnnotationMenuContainer(props: Props): JSX.Element { loadActivity={loadActivity} dumpActivities={dumpActivities} exportActivities={exportActivities} - installedReID={installedReID} onClickMenu={onClickMenu} taskID={jobInstance.task.id} /> diff --git a/cvat-ui/src/containers/create-model-page/create-model-page.tsx b/cvat-ui/src/containers/create-model-page/create-model-page.tsx deleted file mode 100644 index 74cd406e..00000000 --- a/cvat-ui/src/containers/create-model-page/create-model-page.tsx +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2020 Intel Corporation -// -// SPDX-License-Identifier: MIT - -import { connect } from 'react-redux'; - -import CreateModelPageComponent from 'components/create-model-page/create-model-page'; -import { createModelAsync } from 'actions/models-actions'; -import { - ModelFiles, - CombinedState, -} from 'reducers/interfaces'; - -interface StateToProps { - isAdmin: boolean; - modelCreatingStatus: string; -} - -interface DispatchToProps { - createModel(name: string, files: ModelFiles, global: boolean): void; -} - -function mapStateToProps(state: CombinedState): StateToProps { - const { models } = state; - - return { - isAdmin: state.auth.user.isAdmin, - modelCreatingStatus: models.creatingStatus, - }; -} - -function mapDispatchToProps(dispatch: any): DispatchToProps { - return { - createModel(name: string, files: ModelFiles, global: boolean): void { - dispatch(createModelAsync(name, files, global)); - }, - }; -} - -export default connect( - mapStateToProps, - mapDispatchToProps, -)(CreateModelPageComponent); diff --git a/cvat-ui/src/containers/header/header.tsx b/cvat-ui/src/containers/header/header.tsx index 185226a7..abda8b46 100644 --- a/cvat-ui/src/containers/header/header.tsx +++ b/cvat-ui/src/containers/header/header.tsx @@ -15,9 +15,6 @@ const core = getCore(); interface StateToProps { logoutFetching: boolean; installedAnalytics: boolean; - installedAutoAnnotation: boolean; - installedTFSegmentation: boolean; - installedTFAnnotation: boolean; username: string; toolName: string; serverHost: string; @@ -61,9 +58,6 @@ function mapStateToProps(state: CombinedState): StateToProps { return { logoutFetching, installedAnalytics: list[SupportedPlugins.ANALYTICS], - installedAutoAnnotation: list[SupportedPlugins.AUTO_ANNOTATION], - installedTFSegmentation: list[SupportedPlugins.TF_SEGMENTATION], - installedTFAnnotation: list[SupportedPlugins.TF_ANNOTATION], username, toolName: server.name as string, serverHost: core.config.backendAPI.slice(0, -7), diff --git a/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx b/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx index 4855f62d..9ec5b670 100644 --- a/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx +++ b/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx @@ -31,10 +31,7 @@ interface DispatchToProps { runInference( taskInstance: any, model: Model, - mapping: { - [index: string]: string; - }, - cleanOut: boolean, + body: object, ): void; getModels(): void; closeDialog(): void; @@ -58,12 +55,9 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { runInference( taskInstance: any, model: Model, - mapping: { - [index: string]: string; - }, - cleanOut: boolean, + body: object, ): void { - dispatch(startInferenceAsync(taskInstance, model, mapping, cleanOut)); + dispatch(startInferenceAsync(taskInstance, model, body)); }, getModels(): void { dispatch(getModelsAsync()); diff --git a/cvat-ui/src/containers/models-page/models-page.tsx b/cvat-ui/src/containers/models-page/models-page.tsx index 6e2150a8..27eb9df9 100644 --- a/cvat-ui/src/containers/models-page/models-page.tsx +++ b/cvat-ui/src/containers/models-page/models-page.tsx @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: MIT -import React from 'react'; import { connect } from 'react-redux'; import ModelsPageComponent from 'components/models-page/models-page'; @@ -10,38 +9,25 @@ import { Model, CombinedState, } from 'reducers/interfaces'; -import { - getModelsAsync, - deleteModelAsync, -} from 'actions/models-actions'; +import { getModelsAsync } from 'actions/models-actions'; interface StateToProps { - installedAutoAnnotation: boolean; - installedTFAnnotation: boolean; - installedTFSegmentation: boolean; modelsInitialized: boolean; modelsFetching: boolean; - models: Model[]; - registeredUsers: any[]; + deployedModels: Model[]; } interface DispatchToProps { getModels(): void; - deleteModel(id: number): void; } function mapStateToProps(state: CombinedState): StateToProps { - const { list } = state.plugins; const { models } = state; return { - installedAutoAnnotation: list.AUTO_ANNOTATION, - installedTFAnnotation: list.TF_ANNOTATION, - installedTFSegmentation: list.TF_SEGMENTATION, modelsInitialized: models.initialized, modelsFetching: models.fetching, - models: models.models, - registeredUsers: state.users.users, + deployedModels: models.models, }; } @@ -50,29 +36,10 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { getModels(): void { dispatch(getModelsAsync()); }, - deleteModel(id: number): void { - dispatch(deleteModelAsync(id)); - }, }; } -function ModelsPageContainer(props: DispatchToProps & StateToProps): JSX.Element | null { - const { - installedAutoAnnotation, - installedTFSegmentation, - installedTFAnnotation, - } = props; - - const render = installedAutoAnnotation - || installedTFAnnotation - || installedTFSegmentation; - - return ( - render ? : null - ); -} - export default connect( mapStateToProps, mapDispatchToProps, -)(ModelsPageContainer); +)(ModelsPageComponent); diff --git a/cvat-ui/src/index.tsx b/cvat-ui/src/index.tsx index 439ba395..6d614837 100644 --- a/cvat-ui/src/index.tsx +++ b/cvat-ui/src/index.tsx @@ -48,9 +48,6 @@ interface StateToProps { formatsFetching: boolean; userAgreementsInitialized: boolean; userAgreementsFetching: boolean; - installedAutoAnnotation: boolean; - installedTFSegmentation: boolean; - installedTFAnnotation: boolean; notifications: NotificationsState; user: any; keyMap: Record; @@ -66,7 +63,7 @@ interface DispatchToProps { resetMessages: () => void; switchShortcutsDialog: () => void; loadUserAgreements: () => void; - switchSettingsDialog: (show: boolean) => void; + switchSettingsDialog: () => void; } function mapStateToProps(state: CombinedState): StateToProps { @@ -91,9 +88,6 @@ function mapStateToProps(state: CombinedState): StateToProps { formatsFetching: formats.fetching, userAgreementsInitialized: userAgreements.initialized, userAgreementsFetching: userAgreements.fetching, - installedAutoAnnotation: plugins.list.AUTO_ANNOTATION, - installedTFSegmentation: plugins.list.TF_SEGMENTATION, - installedTFAnnotation: plugins.list.TF_ANNOTATION, notifications: state.notifications, user: auth.user, keyMap: shortcuts.keyMap, diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts index 5af1ef99..065b0dd8 100644 --- a/cvat-ui/src/reducers/interfaces.ts +++ b/cvat-ui/src/reducers/interfaces.ts @@ -71,12 +71,8 @@ export interface FormatsState { // eslint-disable-next-line import/prefer-default-export export enum SupportedPlugins { GIT_INTEGRATION = 'GIT_INTEGRATION', - AUTO_ANNOTATION = 'AUTO_ANNOTATION', - TF_ANNOTATION = 'TF_ANNOTATION', - TF_SEGMENTATION = 'TF_SEGMENTATION', DEXTR_SEGMENTATION = 'DEXTR_SEGMENTATION', ANALYTICS = 'ANALYTICS', - REID = 'REID', } export interface PluginsState { @@ -133,13 +129,12 @@ export interface ShareState { } export interface Model { - id: number | null; // null for preinstalled models - ownerID: number | null; // null for preinstalled models + id: string; name: string; - primary: boolean; - uploadDate: string; - updateDate: string; labels: string[]; + framework: string; + description: string; + type: string; } export enum RQStatus { @@ -150,17 +145,11 @@ export enum RQStatus { failed = 'failed', } -export enum ModelType { - OPENVINO = 'openvino', - RCNN = 'rcnn', - MASK_RCNN = 'mask_rcnn', -} - export interface ActiveInference { status: RQStatus; progress: number; error: string; - modelType: ModelType; + id: string; } export interface ModelsState { @@ -175,14 +164,6 @@ export interface ModelsState { activeRunTask: any; } -export interface ModelFiles { - [key: string]: string | File; - xml: string | File; - bin: string | File; - py: string | File; - json: string | File; -} - export interface ErrorState { message: string; reason: string; diff --git a/cvat-ui/src/reducers/models-reducer.ts b/cvat-ui/src/reducers/models-reducer.ts index cfe788b3..3e369584 100644 --- a/cvat-ui/src/reducers/models-reducer.ts +++ b/cvat-ui/src/reducers/models-reducer.ts @@ -44,39 +44,6 @@ export default function ( fetching: false, }; } - case ModelsActionTypes.DELETE_MODEL_SUCCESS: { - return { - ...state, - models: state.models.filter( - (model): boolean => model.id !== action.payload.id, - ), - }; - } - case ModelsActionTypes.CREATE_MODEL: { - return { - ...state, - creatingStatus: '', - }; - } - case ModelsActionTypes.CREATE_MODEL_STATUS_UPDATED: { - return { - ...state, - creatingStatus: action.payload.status, - }; - } - case ModelsActionTypes.CREATE_MODEL_FAILED: { - return { - ...state, - creatingStatus: '', - }; - } - case ModelsActionTypes.CREATE_MODEL_SUCCESS: { - return { - ...state, - initialized: false, - creatingStatus: 'CREATED', - }; - } case ModelsActionTypes.SHOW_RUN_MODEL_DIALOG: { return { ...state, diff --git a/cvat-ui/src/reducers/notifications-reducer.ts b/cvat-ui/src/reducers/notifications-reducer.ts index f7d4b5db..68a65ca5 100644 --- a/cvat-ui/src/reducers/notifications-reducer.ts +++ b/cvat-ui/src/reducers/notifications-reducer.ts @@ -361,21 +361,6 @@ export default function (state = defaultState, action: AnyAction): Notifications }, }; } - case ModelsActionTypes.DELETE_MODEL_FAILED: { - return { - ...state, - errors: { - ...state.errors, - models: { - ...state.errors.models, - deleting: { - message: 'Could not delete the model', - reason: action.payload.error.toString(), - }, - }, - }, - }; - } case ModelsActionTypes.GET_INFERENCE_STATUS_SUCCESS: { if (action.payload.activeInference.status === 'finished') { const { taskID } = action.payload; @@ -420,7 +405,7 @@ export default function (state = defaultState, action: AnyAction): Notifications models: { ...state.errors.models, inferenceStatusFetching: { - message: 'Could not fetch inference status for the ' + message: 'Fetching inference status for the ' + `task ${taskID}`, reason: action.payload.error.toString(), }, diff --git a/cvat-ui/src/reducers/plugins-reducer.ts b/cvat-ui/src/reducers/plugins-reducer.ts index 0bdc6fd2..71cfc3ab 100644 --- a/cvat-ui/src/reducers/plugins-reducer.ts +++ b/cvat-ui/src/reducers/plugins-reducer.ts @@ -5,21 +5,15 @@ import { PluginsActionTypes, PluginActions } from 'actions/plugins-actions'; import { registerGitPlugin } from 'utils/git-utils'; import { registerDEXTRPlugin } from 'utils/dextr-utils'; -import { - PluginsState, -} from './interfaces'; +import { PluginsState } from './interfaces'; const defaultState: PluginsState = { fetching: false, initialized: false, list: { GIT_INTEGRATION: false, - AUTO_ANNOTATION: false, - TF_ANNOTATION: false, - TF_SEGMENTATION: false, DEXTR_SEGMENTATION: false, ANALYTICS: false, - REID: false, }, }; diff --git a/cvat-ui/src/utils/dextr-utils.ts b/cvat-ui/src/utils/dextr-utils.ts index 03280cfa..a9d92abf 100644 --- a/cvat-ui/src/utils/dextr-utils.ts +++ b/cvat-ui/src/utils/dextr-utils.ts @@ -4,11 +4,10 @@ import getCore from 'cvat-core-wrapper'; import { Canvas } from 'cvat-canvas-wrapper'; -import { ShapeType, RQStatus, CombinedState } from 'reducers/interfaces'; +import { ShapeType, CombinedState } from 'reducers/interfaces'; import { getCVATStore } from 'cvat-store'; const core = getCore(); -const baseURL = core.config.backendAPI.slice(0, -7); interface DEXTRPlugin { name: string; @@ -71,79 +70,33 @@ antModal.append(antModalContent); antModalWrap.append(antModal); antModalRoot.append(antModalMask, antModalWrap); - -function serverRequest( - plugin: DEXTRPlugin, - jid: number, +async function serverRequest( + taskInstance: any, frame: number, points: number[], ): Promise { - return new Promise((resolve, reject) => { - const reducer = (acc: Point[], _: number, index: number, array: number[]): Point[] => { - if (!(index % 2)) { // 0, 2, 4 - acc.push({ - x: array[index], - y: array[index + 1], - }); - } - - return acc; - }; - - const reducedPoints = points.reduce(reducer, []); - core.server.request( - `${baseURL}/dextr/create/${jid}`, { - method: 'POST', - data: JSON.stringify({ - frame, - points: reducedPoints, - }), - headers: { - 'Content-Type': 'application/json', - }, - }, - ).then(() => { - const timeoutCallback = (): void => { - core.server.request( - `${baseURL}/dextr/check/${jid}`, { - method: 'GET', - }, - ).then((response: any) => { - const { status } = response; - if (status === RQStatus.finished) { - resolve(response.result.split(/\s|,/).map((coord: string) => +coord)); - } else if (status === RQStatus.failed) { - reject(new Error(response.stderr)); - } else if (status === RQStatus.unknown) { - reject(new Error('Unknown DEXTR status has been received')); - } else { - if (status === RQStatus.queued) { - antModalButton.disabled = false; - } - if (!plugin.data.canceled) { - setTimeout(timeoutCallback, 1000); - } else { - core.server.request( - `${baseURL}/dextr/cancel/${jid}`, { - method: 'GET', - }, - ).then(() => { - resolve(points); - }).catch((error: Error) => { - reject(error); - }); - } - } - }).catch((error: Error) => { - reject(error); - }); - }; + const reducer = (acc: number[][], + _: number, index: number, + array: number[]): number[][] => { + if (!(index % 2)) { // 0, 2, 4 + acc.push([ + array[index], + array[index + 1], + ]); + } + return acc; + }; - setTimeout(timeoutCallback, 1000); - }).catch((error: Error) => { - reject(error); - }); + const reducedPoints = points.reduce(reducer, []); + const models = await core.lambda.list(); + const model = models.filter((func: any): boolean => func.id === 'openvino.dextr')[0]; + const result = await core.lambda.call(taskInstance, model, { + task: taskInstance, + frame, + points: reducedPoints, }); + + return result.flat(); } async function enter(this: any, self: DEXTRPlugin, objects: any[]): Promise { @@ -159,8 +112,7 @@ async function enter(this: any, self: DEXTRPlugin, objects: any[]): Promise= 8) { promises[i] = serverRequest( - self, - this.id, + this.task, objects[i].frame, objects[i].points, ); diff --git a/cvat-ui/src/utils/plugin-checker.ts b/cvat-ui/src/utils/plugin-checker.ts index 54113f9a..eb9f7a5d 100644 --- a/cvat-ui/src/utils/plugin-checker.ts +++ b/cvat-ui/src/utils/plugin-checker.ts @@ -26,24 +26,13 @@ class PluginChecker { case SupportedPlugins.GIT_INTEGRATION: { return isReachable(`${serverHost}/git/repository/meta/get`, 'OPTIONS'); } - case SupportedPlugins.AUTO_ANNOTATION: { - return isReachable(`${serverHost}/auto_annotation/meta/get`, 'OPTIONS'); - } - case SupportedPlugins.TF_ANNOTATION: { - return isReachable(`${serverHost}/tensorflow/annotation/meta/get`, 'OPTIONS'); - } - case SupportedPlugins.TF_SEGMENTATION: { - return isReachable(`${serverHost}/tensorflow/segmentation/meta/get`, 'OPTIONS'); - } case SupportedPlugins.DEXTR_SEGMENTATION: { - return isReachable(`${serverHost}/dextr/enabled`, 'GET'); + const list = await core.lambda.list(); + return list.map((func: any): boolean => func.id).includes('openvino.dextr'); } case SupportedPlugins.ANALYTICS: { return isReachable(`${serverHost}/analytics/app/kibana`, 'GET'); } - case SupportedPlugins.REID: { - return isReachable(`${serverHost}/reid/enabled`, 'GET'); - } default: return false; } diff --git a/cvat-ui/src/utils/reid-utils.ts b/cvat-ui/src/utils/reid-utils.ts deleted file mode 100644 index f628b95f..00000000 --- a/cvat-ui/src/utils/reid-utils.ts +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (C) 2020 Intel Corporation -// -// SPDX-License-Identifier: MIT - -import getCore from 'cvat-core-wrapper'; -import { ShapeType, RQStatus } from 'reducers/interfaces'; - - -const core = getCore(); -const baseURL = core.config.backendAPI.slice(0, -7); - -type Params = { - threshold: number; - distance: number; - onUpdatePercentage(percentage: number): void; - jobID: number; - annotations: any; -}; - -export function run(params: Params): Promise { - return new Promise((resolve, reject) => { - const { - threshold, - distance, - onUpdatePercentage, - jobID, - annotations, - } = params; - const { shapes, ...rest } = annotations; - - const boxes = shapes.filter((shape: any): boolean => shape.type === ShapeType.RECTANGLE); - const others = shapes.filter((shape: any): boolean => shape.type !== ShapeType.RECTANGLE); - - core.server.request( - `${baseURL}/reid/start/job/${params.jobID}`, { - method: 'POST', - data: JSON.stringify({ - threshold, - maxDistance: distance, - boxes, - }), - headers: { - 'Content-Type': 'application/json', - }, - }, - ).then(() => { - const timeoutCallback = (): void => { - core.server.request( - `${baseURL}/reid/check/${jobID}`, { - method: 'GET', - }, - ).then((response: any) => { - const { status } = response; - if (status === RQStatus.finished) { - if (!response.result) { - // cancelled - resolve(annotations); - } - - const result = JSON.parse(response.result); - const collection = rest; - Array.prototype.push.apply(collection.tracks, result); - collection.shapes = others; - resolve(collection); - } else if (status === RQStatus.started) { - const { progress } = response; - if (typeof (progress) === 'number') { - onUpdatePercentage(+progress.toFixed(2)); - } - setTimeout(timeoutCallback, 1000); - } else if (status === RQStatus.failed) { - reject(new Error(response.stderr)); - } else if (status === RQStatus.unknown) { - reject(new Error('Unknown REID status has been received')); - } else { - setTimeout(timeoutCallback, 1000); - } - }).catch((error: Error) => { - reject(error); - }); - }; - - setTimeout(timeoutCallback, 1000); - }).catch((error: Error) => { - reject(error); - }); - }); -} - -export function cancel(jobID: number): void { - core.server.request( - `${baseURL}/reid/cancel/${jobID}`, { - method: 'GET', - }, - ); -} diff --git a/cvat/apps/auto_annotation/README.md b/cvat/apps/auto_annotation/README.md deleted file mode 100644 index 27fecdf8..00000000 --- a/cvat/apps/auto_annotation/README.md +++ /dev/null @@ -1,372 +0,0 @@ -## Auto annotation - -- [Description](#description) -- [Installation](#installation) -- [Usage](#usage) -- [Testing script](#testing) -- [Examples](#examples) - - [Person-vehicle-bike-detection-crossroad-0078](#person-vehicle-bike-detection-crossroad-0078-openvino-toolkit) - - [Landmarks-regression-retail-0009](#landmarks-regression-retail-0009-openvino-toolkit) - - [Semantic Segmentation](#semantic-segmentation) -- [Available interpretation scripts](#available-interpretation-scripts) - -### Description - -The application will be enabled automatically if -[OpenVINO™ component](../../../components/openvino) -is installed. It allows to use custom models for auto annotation. Only models in -OpenVINO™ toolkit format are supported. If you would like to annotate a -task with a custom model please convert it to the intermediate representation -(IR) format via the model optimizer tool. See [OpenVINO documentation](https://software.intel.com/en-us/articles/OpenVINO-InferEngine) for details. - -### Installation - -See the installation instructions for [the OpenVINO component](../../../components/openvino) - -### Usage - -To annotate a task with a custom model you need to prepare 4 files: -1. __Model config__ (*.xml) - a text file with network configuration. -1. __Model weights__ (*.bin) - a binary file with trained weights. -1. __Label map__ (*.json) - a simple json file with `label_map` dictionary like -object with string values for label numbers. - Example: - ```json - { - "label_map": { - "0": "background", - "1": "aeroplane", - "2": "bicycle", - "3": "bird", - "4": "boat", - "5": "bottle", - "6": "bus", - "7": "car", - "8": "cat", - "9": "chair", - "10": "cow", - "11": "diningtable", - "12": "dog", - "13": "horse", - "14": "motorbike", - "15": "person", - "16": "pottedplant", - "17": "sheep", - "18": "sofa", - "19": "train", - "20": "tvmonitor" - } - } - ``` -1. __Interpretation script__ (*.py) - a file used to convert net output layer -to a predefined structure which can be processed by CVAT. This code will be run -inside a restricted python's environment, but it's possible to use some -builtin functions like __str, int, float, max, min, range__. - - Also two variables are available in the scope: - - - __detections__ - a list of dictionaries with detections for each frame: - * __frame_id__ - frame number - * __frame_height__ - frame height - * __frame_width__ - frame width - * __detections__ - output np.ndarray (See [ExecutableNetwork.infer](https://software.intel.com/en-us/articles/OpenVINO-InferEngine#inpage-nav-11-6-3) for details). - - - __results__ - an instance of python class with converted results. - Following methods should be used to add shapes: - ```python - # xtl, ytl, xbr, ybr - expected values are float or int - # label - expected value is int - # frame_number - expected value is int - # attributes - dictionary of attribute_name: attribute_value pairs, for example {"confidence": "0.83"} - add_box(self, xtl, ytl, xbr, ybr, label, frame_number, attributes=None) - - # points - list of (x, y) pairs of float or int, for example [(57.3, 100), (67, 102.7)] - # label - expected value is int - # frame_number - expected value is int - # attributes - dictionary of attribute_name: attribute_value pairs, for example {"confidence": "0.83"} - add_points(self, points, label, frame_number, attributes=None) - add_polygon(self, points, label, frame_number, attributes=None) - add_polyline(self, points, label, frame_number, attributes=None) - ``` - -### Testing script - -CVAT comes prepackaged with a small command line helper script to help develop interpretation scripts. - -It includes a small user interface which allows users to feed in images and see the results using -the user interfaces provided by OpenCV. - -See the script and the documentation in the -[auto_annotation directory](https://github.com/opencv/cvat/tree/develop/utils/auto_annotation). - -When using the Auto Annotation runner, it is often helpful to drop into a REPL prompt to interact with the variables -directly. You can do this using the `interact` method from the `code` module. - -```python -# Import the interact method from the `code` module -from code import interact - - -for frame_results in detections: - frame_height = frame_results["frame_height"] - frame_width = frame_results["frame_width"] - frame_number = frame_results["frame_id"] - # Unsure what other data members are in the `frame_results`? Use the `interact method! - interact(local=locals()) -``` - -```bash -$ python cvat/utils/auto_annotation/run_models.py --py /path/to/myfile.py --json /path/to/mapping.json --xml /path/to/inference.xml --bin /path/to/inference.bin -Python 3.6.6 (default, Sep 26 2018, 15:10:10) -[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.10.44.2)] on darwin -Type "help", "copyright", "credits" or "license" for more information. ->>> dir() -['__builtins__', 'frame_results', 'detections', 'frame_number', 'frame_height', 'interact', 'results', 'frame_width'] ->>> type(frame_results) - ->>> frame_results.keys() -dict_keys(['frame_id', 'frame_height', 'frame_width', 'detections']) -``` - -When using the `interact` method, make sure you are running using the _testing script_, and ensure that you _remove it_ - before submitting to the server! If you don't remove it from the server, the code runners will hang during execution, - and you'll have to restart the server to fix them. - -Another useful development method is visualizing the results using OpenCV. This will be discussed more in the -[Semantic Segmentation](#segmentation) section. - -### Examples - -#### [Person-vehicle-bike-detection-crossroad-0078](https://github.com/opencv/open_model_zoo/blob/2018/intel_models/person-vehicle-bike-detection-crossroad-0078/description/person-vehicle-bike-detection-crossroad-0078.md) (OpenVINO toolkit) - -__Links__ -- [person-vehicle-bike-detection-crossroad-0078.xml](https://download.01.org/openvinotoolkit/2018_R5/open_model_zoo/person-vehicle-bike-detection-crossroad-0078/FP32/person-vehicle-bike-detection-crossroad-0078.xml) -- [person-vehicle-bike-detection-crossroad-0078.bin](https://download.01.org/openvinotoolkit/2018_R5/open_model_zoo/person-vehicle-bike-detection-crossroad-0078/FP32/person-vehicle-bike-detection-crossroad-0078.bin) - -__Task labels__: person vehicle non-vehicle - -__label_map.json__: -```json -{ -"label_map": { - "1": "person", - "2": "vehicle", - "3": "non-vehicle" - } -} -``` -__Interpretation script for SSD based networks__: -```python -def clip(value): - return max(min(1.0, value), 0.0) - -for frame_results in detections: - frame_height = frame_results["frame_height"] - frame_width = frame_results["frame_width"] - frame_number = frame_results["frame_id"] - - for i in range(frame_results["detections"].shape[2]): - confidence = frame_results["detections"][0, 0, i, 2] - if confidence < 0.5: - continue - - results.add_box( - xtl=clip(frame_results["detections"][0, 0, i, 3]) * frame_width, - ytl=clip(frame_results["detections"][0, 0, i, 4]) * frame_height, - xbr=clip(frame_results["detections"][0, 0, i, 5]) * frame_width, - ybr=clip(frame_results["detections"][0, 0, i, 6]) * frame_height, - label=int(frame_results["detections"][0, 0, i, 1]), - frame_number=frame_number, - attributes={ - "confidence": "{:.2f}".format(confidence), - }, - ) -``` - -#### [Landmarks-regression-retail-0009](https://github.com/opencv/open_model_zoo/blob/2018/intel_models/landmarks-regression-retail-0009/description/landmarks-regression-retail-0009.md) (OpenVINO toolkit) - -__Links__ -- [landmarks-regression-retail-0009.xml](https://download.01.org/openvinotoolkit/2018_R5/open_model_zoo/landmarks-regression-retail-0009/FP32/landmarks-regression-retail-0009.xml) -- [landmarks-regression-retail-0009.bin](https://download.01.org/openvinotoolkit/2018_R5/open_model_zoo/landmarks-regression-retail-0009/FP32/landmarks-regression-retail-0009.bin) - -__Task labels__: left_eye right_eye tip_of_nose left_lip_corner right_lip_corner - -__label_map.json__: -```json -{ - "label_map": { - "0": "left_eye", - "1": "right_eye", - "2": "tip_of_nose", - "3": "left_lip_corner", - "4": "right_lip_corner" - } -} -``` -__Interpretation script__: -```python -def clip(value): - return max(min(1.0, value), 0.0) - -for frame_results in detections: - frame_height = frame_results["frame_height"] - frame_width = frame_results["frame_width"] - frame_number = frame_results["frame_id"] - - for i in range(0, frame_results["detections"].shape[1], 2): - x = frame_results["detections"][0, i, 0, 0] - y = frame_results["detections"][0, i + 1, 0, 0] - - results.add_points( - points=[(clip(x) * frame_width, clip(y) * frame_height)], - label=i // 2, # see label map and model output specification, - frame_number=frame_number, - ) -``` - -#### Semantic Segmentation - -__Links__ -- [masck_rcnn_resnet50_atrous_coco][1] (OpenvVINO toolkit) -- [CVAT Implemenation][2] - -__label_map.json__: -```json -{ -"label_map": { - "1": "person", - "2": "bicycle", - "3": "car", - } -} -``` - -Note that the above labels are not all the labels in the model! See [here](https://github.com/opencv/cvat/blob/develop/utils/open_model_zoo/mask_rcnn_inception_resnet_v2_atrous_coco/mapping.json). - -**Interpretation script for a semantic segmentation network**: -```python -import numpy as np -import cv2 -from skimage.measure import approximate_polygon, find_contours - - -for frame_results in detections: - frame_height = frame_results['frame_height'] - frame_width = frame_results['frame_width'] - frame_number = frame_results['frame_id'] - detection = frame_results['detections'] - - # The keys for the below two members will vary based on the model - masks = frame_results['masks'] - boxes = frame_results['reshape_do_2d'] - - for box_index, box in enumerate(boxes): - # Again, these indexes specific to this model - class_label = int(box[1]) - box_class_probability = box[2] - - if box_class_probability > 0.2: - xmin = box[3] * frame_width - ymin = box[4] * frame_height - xmax = box[5] * frame_width - ymax = box[6] * frame_width - - box_width = int(xmax - xmin) - box_height = int(ymin - ymax) - - # use the box index and class label index to find the appropriate mask - # note that we need to convert the class label to a zero indexed array by subtracting `1` - class_mask = masks[box_index][class_label - 1] - - # Class mask is a 33 x 33 matrix - # resize it to the bounding box - resized_mask = cv2.resize(class_mask, dsize(box_height, box_width), interpolation=cv2.INTER_CUBIC) - - # Each pixel is a probability, select every pixel above the probability threshold, 0.5 - # Do this using the boolean `>` method - boolean_mask = (resized_mask > 0.5) - - # Convert the boolean values to uint8 - uint8_mask = boolean_mask.astype(np.uint8) * 255 - - # Change the x and y coordinates into integers - xmin = int(round(xmin)) - ymin = int(round(ymin)) - xmax = xmin + box_width - ymax = ymin + box_height - - # Create an empty blank frame, so that we can get the mask polygon in frame coordinates - mask_frame = np.zeros((frame_height, frame_width), dtype=np.uint8) - - # Put the uint8_mask on the mask frame using the integer coordinates - mask_frame[xmin:xmax, ymin:ymax] = uint8_mask - - mask_probability_threshold = 0.5 - # find the contours - contours = find_contours(mask_frame, mask_probability_threshold) - # every bounding box should only have a single contour - contour = contours[0] - contour = np.flip(contour, axis=1) - - # reduce the precision on the polygon - polygon_mask = approximate_polygon(contour, tolerance=2.5) - polygon_mask = polygon_mask.tolist() - - results.add_polygon(polygon_mask, class_label, frame_number) -``` - -Note that it is sometimes hard to see or understand what is happening in a script. -Use of the computer vision module can help you visualize what is happening. - -```python -import cv2 - - -for frame_results in detections: - frame_height = frame_results['frame_height'] - frame_width = frame_results['frame_width'] - detection = frame_results['detections'] - - masks = frame_results['masks'] - boxes = frame_results['reshape_do_2d'] - - for box_index, box in enumerate(boxes): - class_label = int(box[1]) - box_class_probability = box[2] - - if box_class_probability > 0.2: - xmin = box[3] * frame_width - ymin = box[4] * frame_height - xmax = box[5] * frame_width - ymax = box[6] * frame_width - - box_width = int(xmax - xmin) - box_height = int(ymin - ymax) - - class_mask = masks[box_index][class_label - 1] - # Visualize the class mask! - cv2.imshow('class mask', class_mask) - # wait until user presses keys - cv2.waitKeys() - - boolean_mask = (resized_mask > 0.5) - uint8_mask = boolean_mask.astype(np.uint8) * 255 - - # Visualize the class mask after it's been resized! - cv2.imshow('class mask', uint8_mask) - cv2.waitKeys() -``` - -Note that you should _only_ use the above commands while running the [Auto Annotation Model Runner][3]. -Running on the server will likely require a server restart to fix. -The method `cv2.destroyAllWindows()` or `cv2.destroyWindow('your-name-here')` might be required depending on your - implementation. - -### Available interpretation scripts - -CVAT comes prepackaged with several out of the box interpretation scripts. -See them in the [open model zoo directory](https://github.com/opencv/cvat/tree/develop/utils/open_model_zoo) - -[1]: https://github.com/opencv/open_model_zoo/blob/master/models/public/mask_rcnn_resnet50_atrous_coco/model.yml -[2]: https://github.com/opencv/cvat/tree/develop/utils/open_model_zoo/mask_rcnn_inception_resnet_v2_atrous_coco -[3]: https://github.com/opencv/cvat/tree/develop/utils/auto_annotation diff --git a/cvat/apps/auto_annotation/__init__.py b/cvat/apps/auto_annotation/__init__.py deleted file mode 100644 index c929093f..00000000 --- a/cvat/apps/auto_annotation/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ - -# Copyright (C) 2018-2019 Intel Corporation -# -# SPDX-License-Identifier: MIT - -default_app_config = 'cvat.apps.auto_annotation.apps.AutoAnnotationConfig' diff --git a/cvat/apps/auto_annotation/admin.py b/cvat/apps/auto_annotation/admin.py deleted file mode 100644 index da1eabb4..00000000 --- a/cvat/apps/auto_annotation/admin.py +++ /dev/null @@ -1,15 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.contrib import admin -from .models import AnnotationModel - -@admin.register(AnnotationModel) -class AnnotationModelAdmin(admin.ModelAdmin): - list_display = ('name', 'owner', 'created_date', 'updated_date', - 'shared', 'primary', 'framework') - - def has_add_permission(self, request): - return False diff --git a/cvat/apps/auto_annotation/apps.py b/cvat/apps/auto_annotation/apps.py deleted file mode 100644 index cea75abf..00000000 --- a/cvat/apps/auto_annotation/apps.py +++ /dev/null @@ -1,15 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.apps import AppConfig - - -class AutoAnnotationConfig(AppConfig): - name = "cvat.apps.auto_annotation" - - def ready(self): - from .permissions import setup_permissions - - setup_permissions() diff --git a/cvat/apps/auto_annotation/image_loader.py b/cvat/apps/auto_annotation/image_loader.py deleted file mode 100644 index 17335beb..00000000 --- a/cvat/apps/auto_annotation/image_loader.py +++ /dev/null @@ -1,22 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -import cv2 -import numpy as np - -class ImageLoader(): - def __init__(self, frame_provider): - self._frame_provider = frame_provider - - def __iter__(self): - for frame, _ in self._frame_provider.get_frames(self._frame_provider.Quality.ORIGINAL): - yield self._load_image(frame) - - def __len__(self): - return len(self._frame_provider) - - @staticmethod - def _load_image(image): - return cv2.imdecode(np.fromstring(image.read(), np.uint8), cv2.IMREAD_COLOR) diff --git a/cvat/apps/auto_annotation/inference.py b/cvat/apps/auto_annotation/inference.py deleted file mode 100644 index b51cc10e..00000000 --- a/cvat/apps/auto_annotation/inference.py +++ /dev/null @@ -1,163 +0,0 @@ -import itertools -from .model_loader import ModelLoader -from cvat.apps.engine.utils import import_modules, execute_python_code - -def _process_detections(detections, path_to_conv_script, restricted=True): - results = Results() - local_vars = { - "detections": detections, - "results": results, - } - source_code = open(path_to_conv_script).read() - - if restricted: - global_vars = { - "__builtins__": { - "str": str, - "int": int, - "float": float, - "max": max, - "min": min, - "range": range, - }, - } - else: - global_vars = globals() - imports = import_modules(source_code) - global_vars.update(imports) - - - execute_python_code(source_code, global_vars, local_vars) - - return results - -def _process_attributes(shape_attributes, label_attr_spec): - attributes = [] - for attr_text, attr_value in shape_attributes.items(): - if attr_text in label_attr_spec: - attributes.append({ - "spec_id": label_attr_spec[attr_text], - "value": attr_value, - }) - - return attributes - -class Results(): - def __init__(self): - self._results = { - "shapes": [], - "tracks": [] - } - - # https://stackoverflow.com/a/50928627/2701402 - def add_box(self, xtl: float, ytl: float, xbr: float, ybr: float, label: int, frame_number: int, attributes: dict=None): - """ - xtl - x coordinate, top left - ytl - y coordinate, top left - xbr - x coordinate, bottom right - ybr - y coordinate, bottom right - """ - self.get_shapes().append({ - "label": label, - "frame": frame_number, - "points": [xtl, ytl, xbr, ybr], - "type": "rectangle", - "attributes": attributes or {}, - }) - - def add_points(self, points: list, label: int, frame_number: int, attributes: dict=None): - points = self._create_polyshape(points, label, frame_number, attributes) - points["type"] = "points" - self.get_shapes().append(points) - - def add_polygon(self, points: list, label: int, frame_number: int, attributes: dict=None): - polygon = self._create_polyshape(points, label, frame_number, attributes) - polygon["type"] = "polygon" - self.get_shapes().append(polygon) - - def add_polyline(self, points: list, label: int, frame_number: int, attributes: dict=None): - polyline = self._create_polyshape(points, label, frame_number, attributes) - polyline["type"] = "polyline" - self.get_shapes().append(polyline) - - def get_shapes(self): - return self._results["shapes"] - - def get_tracks(self): - return self._results["tracks"] - - @staticmethod - def _create_polyshape(points: list, label: int, frame_number: int, attributes: dict=None): - return { - "label": label, - "frame": frame_number, - "points": list(itertools.chain.from_iterable(points)), - "attributes": attributes or {}, - } - -class InferenceAnnotationRunner: - def __init__(self, data, model_file, weights_file, labels_mapping, - attribute_spec, convertation_file): - self.data = iter(data) - self.data_len = len(data) - self.model = ModelLoader(model=model_file, weights=weights_file) - self.frame_counter = 0 - self.attribute_spec = attribute_spec - self.convertation_file = convertation_file - self.iteration_size = 128 - self.labels_mapping = labels_mapping - - - def run(self, job=None, update_progress=None, restricted=True): - result = { - "shapes": [], - "tracks": [], - "tags": [], - "version": 0 - } - - detections = [] - for _ in range(self.iteration_size): - try: - frame = next(self.data) - except StopIteration: - break - - orig_rows, orig_cols = frame.shape[:2] - - detections.append({ - "frame_id": self.frame_counter, - "frame_height": orig_rows, - "frame_width": orig_cols, - "detections": self.model.infer(frame), - }) - - self.frame_counter += 1 - if job and update_progress and not update_progress(job, self.frame_counter * 100 / self.data_len): - return None, False - - processed_detections = _process_detections(detections, self.convertation_file, restricted=restricted) - - self._add_shapes(processed_detections.get_shapes(), result["shapes"]) - - more_items = self.frame_counter != self.data_len - - return result, more_items - - def _add_shapes(self, shapes, target_container): - for shape in shapes: - if shape["label"] not in self.labels_mapping: - continue - - db_label = self.labels_mapping[shape["label"]] - label_attr_spec = self.attribute_spec.get(db_label) - target_container.append({ - "label_id": db_label, - "frame": shape["frame"], - "points": shape["points"], - "type": shape["type"], - "z_order": 0, - "group": None, - "occluded": False, - "attributes": _process_attributes(shape["attributes"], label_attr_spec), - }) diff --git a/cvat/apps/auto_annotation/inference_engine.py b/cvat/apps/auto_annotation/inference_engine.py deleted file mode 100644 index 766c0eb0..00000000 --- a/cvat/apps/auto_annotation/inference_engine.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from openvino.inference_engine import IENetwork, IEPlugin, IECore, get_version - -import subprocess -import os -import platform - -_IE_PLUGINS_PATH = os.getenv("IE_PLUGINS_PATH", None) - -def _check_instruction(instruction): - return instruction == str.strip( - subprocess.check_output( - 'lscpu | grep -o "{}" | head -1'.format(instruction), shell=True - ).decode('utf-8') - ) - - -def make_plugin_or_core(): - version = get_version() - use_core_openvino = False - try: - major, minor, reference = [int(x) for x in version.split('.')] - if major >= 2 and minor >= 1: - use_core_openvino = True - except Exception: - pass - - if use_core_openvino: - ie = IECore() - return ie - - if _IE_PLUGINS_PATH is None: - raise OSError('Inference engine plugin path env not found in the system.') - - plugin = IEPlugin(device='CPU', plugin_dirs=[_IE_PLUGINS_PATH]) - if (_check_instruction('avx2')): - plugin.add_cpu_extension(os.path.join(_IE_PLUGINS_PATH, 'libcpu_extension_avx2.so')) - elif (_check_instruction('sse4')): - plugin.add_cpu_extension(os.path.join(_IE_PLUGINS_PATH, 'libcpu_extension_sse4.so')) - elif platform.system() == 'Darwin': - plugin.add_cpu_extension(os.path.join(_IE_PLUGINS_PATH, 'libcpu_extension.dylib')) - else: - raise Exception('Inference engine requires a support of avx2 or sse4.') - - return plugin - - -def make_network(model, weights): - return IENetwork(model = model, weights = weights) diff --git a/cvat/apps/auto_annotation/migrations/0001_initial.py b/cvat/apps/auto_annotation/migrations/0001_initial.py deleted file mode 100644 index ebd8a6e1..00000000 --- a/cvat/apps/auto_annotation/migrations/0001_initial.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 2.1.3 on 2019-01-24 14:05 - -import cvat.apps.auto_annotation.models -from django.conf import settings -import django.core.files.storage -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='AnnotationModel', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', cvat.apps.auto_annotation.models.SafeCharField(max_length=256)), - ('created_date', models.DateTimeField(auto_now_add=True)), - ('updated_date', models.DateTimeField(auto_now_add=True)), - ('model_file', models.FileField(storage=django.core.files.storage.FileSystemStorage(), upload_to=cvat.apps.auto_annotation.models.upload_path_handler)), - ('weights_file', models.FileField(storage=django.core.files.storage.FileSystemStorage(), upload_to=cvat.apps.auto_annotation.models.upload_path_handler)), - ('labelmap_file', models.FileField(storage=django.core.files.storage.FileSystemStorage(), upload_to=cvat.apps.auto_annotation.models.upload_path_handler)), - ('interpretation_file', models.FileField(storage=django.core.files.storage.FileSystemStorage(), upload_to=cvat.apps.auto_annotation.models.upload_path_handler)), - ('shared', models.BooleanField(default=False)), - ('primary', models.BooleanField(default=False)), - ('framework', models.CharField(default=cvat.apps.auto_annotation.models.FrameworkChoice('openvino'), max_length=32)), - ('owner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'default_permissions': (), - }, - ), - ] diff --git a/cvat/apps/auto_annotation/migrations/__init__.py b/cvat/apps/auto_annotation/migrations/__init__.py deleted file mode 100644 index d8e62e54..00000000 --- a/cvat/apps/auto_annotation/migrations/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - diff --git a/cvat/apps/auto_annotation/model_loader.py b/cvat/apps/auto_annotation/model_loader.py deleted file mode 100644 index e48d5c8e..00000000 --- a/cvat/apps/auto_annotation/model_loader.py +++ /dev/null @@ -1,76 +0,0 @@ - -# Copyright (C) 2018-2019 Intel Corporation -# -# SPDX-License-Identifier: MIT - -import json -import cv2 -import os -import numpy as np - -from cvat.apps.auto_annotation.inference_engine import make_plugin_or_core, make_network - -class ModelLoader(): - def __init__(self, model, weights): - self._model = model - self._weights = weights - - core_or_plugin = make_plugin_or_core() - network = make_network(self._model, self._weights) - - if getattr(core_or_plugin, 'get_supported_layers', False): - supported_layers = core_or_plugin.get_supported_layers(network) - not_supported_layers = [l for l in network.layers.keys() if l not in supported_layers] - if len(not_supported_layers) != 0: - raise Exception("Following layers are not supported by the plugin for specified device {}:\n {}". - format(core_or_plugin.device, ", ".join(not_supported_layers))) - - iter_inputs = iter(network.inputs) - self._input_blob_name = next(iter_inputs) - self._input_info_name = '' - self._output_blob_name = next(iter(network.outputs)) - - self._require_image_info = False - - info_names = ('image_info', 'im_info') - - # NOTE: handeling for the inclusion of `image_info` in OpenVino2019 - if any(s in network.inputs for s in info_names): - self._require_image_info = True - self._input_info_name = set(network.inputs).intersection(info_names) - self._input_info_name = self._input_info_name.pop() - if self._input_blob_name in info_names: - self._input_blob_name = next(iter_inputs) - - if getattr(core_or_plugin, 'load_network', False): - self._net = core_or_plugin.load_network(network, - "CPU", - num_requests=2) - else: - self._net = core_or_plugin.load(network=network, num_requests=2) - input_type = network.inputs[self._input_blob_name] - self._input_layout = input_type if isinstance(input_type, list) else input_type.shape - - def infer(self, image): - _, _, h, w = self._input_layout - in_frame = image if image.shape[:-1] == (h, w) else cv2.resize(image, (w, h)) - in_frame = in_frame.transpose((2, 0, 1)) # Change data layout from HWC to CHW - inputs = {self._input_blob_name: in_frame} - if self._require_image_info: - info = np.zeros([1, 3]) - info[0, 0] = h - info[0, 1] = w - # frame number - info[0, 2] = 1 - inputs[self._input_info_name] = info - - results = self._net.infer(inputs) - if len(results) == 1: - return results[self._output_blob_name].copy() - else: - return results.copy() - - -def load_labelmap(labels_path): - with open(labels_path, "r") as f: - return json.load(f)["label_map"] diff --git a/cvat/apps/auto_annotation/model_manager.py b/cvat/apps/auto_annotation/model_manager.py deleted file mode 100644 index 7bac221a..00000000 --- a/cvat/apps/auto_annotation/model_manager.py +++ /dev/null @@ -1,276 +0,0 @@ -# Copyright (C) 2018-2020 Intel Corporation -# -# SPDX-License-Identifier: MIT - -import django_rq -import numpy as np -import os -import rq -import shutil -import tempfile - -from django.db import transaction -from django.utils import timezone -from django.conf import settings - -from cvat.apps.engine.log import slogger -from cvat.apps.engine.models import Task as TaskModel -from cvat.apps.authentication.auth import has_admin_role -from cvat.apps.engine.serializers import LabeledDataSerializer -from cvat.apps.dataset_manager.task import put_task_data, patch_task_data -from cvat.apps.engine.frame_provider import FrameProvider -from cvat.apps.engine.utils import av_scan_paths - -from .models import AnnotationModel, FrameworkChoice -from .model_loader import load_labelmap -from .image_loader import ImageLoader -from .inference import InferenceAnnotationRunner - - -def _remove_old_file(model_file_field): - if model_file_field and os.path.exists(model_file_field.name): - os.remove(model_file_field.name) - -def _update_dl_model_thread(dl_model_id, name, is_shared, model_file, weights_file, labelmap_file, - interpretation_file, run_tests, is_local_storage, delete_if_test_fails, restricted=True): - def _get_file_content(filename): - return os.path.basename(filename), open(filename, "rb") - - def _delete_source_files(): - for f in [model_file, weights_file, labelmap_file, interpretation_file]: - if f: - os.remove(f) - - def _run_test(model_file, weights_file, labelmap_file, interpretation_file): - test_image = np.ones((1024, 1980, 3), np.uint8) * 255 - try: - dummy_labelmap = {key: key for key in load_labelmap(labelmap_file).keys()} - runner = InferenceAnnotationRunner( - data=[test_image,], - model_file=model_file, - weights_file=weights_file, - labels_mapping=dummy_labelmap, - attribute_spec={}, - convertation_file=interpretation_file) - - runner.run(restricted=restricted) - except Exception as e: - return False, str(e) - - return True, "" - - job = rq.get_current_job() - job.meta["progress"] = "Saving data" - job.save_meta() - - with transaction.atomic(): - dl_model = AnnotationModel.objects.select_for_update().get(pk=dl_model_id) - - test_res = True - message = "" - if run_tests: - job.meta["progress"] = "Test started" - job.save_meta() - - test_res, message = _run_test( - model_file=model_file or dl_model.model_file.name, - weights_file=weights_file or dl_model.weights_file.name, - labelmap_file=labelmap_file or dl_model.labelmap_file.name, - interpretation_file=interpretation_file or dl_model.interpretation_file.name, - ) - - if not test_res: - job.meta["progress"] = "Test failed" - if delete_if_test_fails: - shutil.rmtree(dl_model.get_dirname(), ignore_errors=True) - dl_model.delete() - else: - job.meta["progress"] = "Test passed" - job.save_meta() - - # update DL model - if test_res: - if model_file: - _remove_old_file(dl_model.model_file) - dl_model.model_file.save(*_get_file_content(model_file)) - if weights_file: - _remove_old_file(dl_model.weights_file) - dl_model.weights_file.save(*_get_file_content(weights_file)) - if labelmap_file: - _remove_old_file(dl_model.labelmap_file) - dl_model.labelmap_file.save(*_get_file_content(labelmap_file)) - if interpretation_file: - _remove_old_file(dl_model.interpretation_file) - dl_model.interpretation_file.save(*_get_file_content(interpretation_file)) - - if name: - dl_model.name = name - - if is_shared != None: - dl_model.shared = is_shared - - dl_model.updated_date = timezone.now() - dl_model.save() - - if is_local_storage: - _delete_source_files() - - if not test_res: - raise Exception("Model was not properly created/updated. Test failed: {}".format(message)) - -def create_or_update(dl_model_id, name, model_file, weights_file, labelmap_file, interpretation_file, owner, storage, is_shared): - def get_abs_path(share_path): - if not share_path: - return share_path - share_root = settings.SHARE_ROOT - relpath = os.path.normpath(share_path).lstrip('/') - if '..' in relpath.split(os.path.sep): - raise Exception('Permission denied') - abspath = os.path.abspath(os.path.join(share_root, relpath)) - if os.path.commonprefix([share_root, abspath]) != share_root: - raise Exception('Bad file path on share: ' + abspath) - return abspath - - def save_file_as_tmp(data): - if not data: - return None - fd, filename = tempfile.mkstemp() - with open(filename, 'wb') as tmp_file: - for chunk in data.chunks(): - tmp_file.write(chunk) - os.close(fd) - return filename - - is_create_request = dl_model_id is None - if is_create_request: - dl_model_id = create_empty(owner=owner) - - run_tests = bool(model_file or weights_file or labelmap_file or interpretation_file) - if storage != "local": - model_file = get_abs_path(model_file) - weights_file = get_abs_path(weights_file) - labelmap_file = get_abs_path(labelmap_file) - interpretation_file = get_abs_path(interpretation_file) - else: - model_file = save_file_as_tmp(model_file) - weights_file = save_file_as_tmp(weights_file) - labelmap_file = save_file_as_tmp(labelmap_file) - interpretation_file = save_file_as_tmp(interpretation_file) - - files_to_scan = [] - if model_file: - files_to_scan.append(model_file) - if weights_file: - files_to_scan.append(weights_file) - if labelmap_file: - files_to_scan.append(labelmap_file) - if interpretation_file: - files_to_scan.append(interpretation_file) - av_scan_paths(*files_to_scan) - - if owner: - restricted = not has_admin_role(owner) - else: - restricted = not has_admin_role(AnnotationModel.objects.get(pk=dl_model_id).owner) - - rq_id = "auto_annotation.create.{}".format(dl_model_id) - queue = django_rq.get_queue("default") - queue.enqueue_call( - func=_update_dl_model_thread, - args=( - dl_model_id, - name, - is_shared, - model_file, - weights_file, - labelmap_file, - interpretation_file, - run_tests, - storage == "local", - is_create_request, - restricted - ), - job_id=rq_id - ) - - return rq_id - -@transaction.atomic -def create_empty(owner, framework=FrameworkChoice.OPENVINO): - db_model = AnnotationModel( - owner=owner, - ) - db_model.save() - - model_path = db_model.get_dirname() - if os.path.isdir(model_path): - shutil.rmtree(model_path) - os.mkdir(model_path) - - return db_model.id - -@transaction.atomic -def delete(dl_model_id): - dl_model = AnnotationModel.objects.select_for_update().get(pk=dl_model_id) - if dl_model: - if dl_model.primary: - raise Exception("Can not delete primary model {}".format(dl_model_id)) - - shutil.rmtree(dl_model.get_dirname(), ignore_errors=True) - dl_model.delete() - else: - raise Exception("Requested DL model {} doesn't exist".format(dl_model_id)) - -def run_inference_thread(tid, model_file, weights_file, labels_mapping, attributes, convertation_file, reset, user, restricted=True): - def update_progress(job, progress): - job.refresh() - if "cancel" in job.meta: - del job.meta["cancel"] - job.save() - return False - job.meta["progress"] = progress - job.save_meta() - return True - - try: - job = rq.get_current_job() - job.meta["progress"] = 0 - job.save_meta() - db_task = TaskModel.objects.get(pk=tid) - - result = None - slogger.glob.info("auto annotation with openvino toolkit for task {}".format(tid)) - more_data = True - runner = InferenceAnnotationRunner( - data=ImageLoader(FrameProvider(db_task.data)), - model_file=model_file, - weights_file=weights_file, - labels_mapping=labels_mapping, - attribute_spec=attributes, - convertation_file= convertation_file) - while more_data: - result, more_data = runner.run( - job=job, - update_progress=update_progress, - restricted=restricted) - - if result is None: - slogger.glob.info("auto annotation for task {} canceled by user".format(tid)) - return - - serializer = LabeledDataSerializer(data = result) - if serializer.is_valid(raise_exception=True): - if reset: - put_task_data(tid, result) - else: - patch_task_data(tid, result, "create") - - slogger.glob.info("auto annotation for task {} done".format(tid)) - except Exception as e: - try: - slogger.task[tid].exception("exception was occurred during auto annotation of the task", exc_info=True) - except Exception as ex: - slogger.glob.exception("exception was occurred during auto annotation of the task {}: {}".format(tid, str(ex)), exc_info=True) - raise ex - - raise e diff --git a/cvat/apps/auto_annotation/models.py b/cvat/apps/auto_annotation/models.py deleted file mode 100644 index 467997e0..00000000 --- a/cvat/apps/auto_annotation/models.py +++ /dev/null @@ -1,56 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -import os -from enum import Enum - -from django.db import models -from django.conf import settings -from django.contrib.auth.models import User -from django.core.files.storage import FileSystemStorage - -fs = FileSystemStorage() - -def upload_path_handler(instance, filename): - return os.path.join(settings.MODELS_ROOT, str(instance.id), filename) - -class FrameworkChoice(Enum): - OPENVINO = 'openvino' - TENSORFLOW = 'tensorflow' - PYTORCH = 'pytorch' - - def __str__(self): - return self.value - - -class SafeCharField(models.CharField): - def get_prep_value(self, value): - value = super().get_prep_value(value) - if value: - return value[:self.max_length] - return value - -class AnnotationModel(models.Model): - name = SafeCharField(max_length=256) - owner = models.ForeignKey(User, null=True, blank=True, - on_delete=models.SET_NULL) - created_date = models.DateTimeField(auto_now_add=True) - updated_date = models.DateTimeField(auto_now_add=True) - model_file = models.FileField(upload_to=upload_path_handler, storage=fs) - weights_file = models.FileField(upload_to=upload_path_handler, storage=fs) - labelmap_file = models.FileField(upload_to=upload_path_handler, storage=fs) - interpretation_file = models.FileField(upload_to=upload_path_handler, storage=fs) - shared = models.BooleanField(default=False) - primary = models.BooleanField(default=False) - framework = models.CharField(max_length=32, default=FrameworkChoice.OPENVINO) - - class Meta: - default_permissions = () - - def get_dirname(self): - return "{models_root}/{id}".format(models_root=settings.MODELS_ROOT, id=self.id) - - def __str__(self): - return self.name diff --git a/cvat/apps/auto_annotation/permissions.py b/cvat/apps/auto_annotation/permissions.py deleted file mode 100644 index ede8d611..00000000 --- a/cvat/apps/auto_annotation/permissions.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -import rules - -from cvat.apps.authentication.auth import has_admin_role, has_user_role - -@rules.predicate -def is_model_owner(db_user, db_dl_model): - return db_dl_model.owner == db_user - -@rules.predicate -def is_shared_model(_, db_dl_model): - return db_dl_model.shared - -@rules.predicate -def is_primary_model(_, db_dl_model): - return db_dl_model.primary - -def setup_permissions(): - rules.add_perm('auto_annotation.model.create', has_admin_role | has_user_role) - - rules.add_perm('auto_annotation.model.update', (has_admin_role | is_model_owner) & ~is_primary_model) - - rules.add_perm('auto_annotation.model.delete', (has_admin_role | is_model_owner) & ~is_primary_model) - - rules.add_perm('auto_annotation.model.access', has_admin_role | is_model_owner | - is_shared_model | is_primary_model) diff --git a/cvat/apps/auto_annotation/tests.py b/cvat/apps/auto_annotation/tests.py deleted file mode 100644 index a59acdef..00000000 --- a/cvat/apps/auto_annotation/tests.py +++ /dev/null @@ -1,4 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT diff --git a/cvat/apps/auto_annotation/urls.py b/cvat/apps/auto_annotation/urls.py deleted file mode 100644 index 2aa75c5e..00000000 --- a/cvat/apps/auto_annotation/urls.py +++ /dev/null @@ -1,19 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.urls import path -from . import views - -urlpatterns = [ - path("create", views.create_model), - path("update/", views.update_model), - path("delete/", views.delete_model), - - path("start//", views.start_annotation), - path("check/", views.check), - path("cancel/", views.cancel), - - path("meta/get", views.get_meta_info), -] diff --git a/cvat/apps/auto_annotation/views.py b/cvat/apps/auto_annotation/views.py deleted file mode 100644 index c521424d..00000000 --- a/cvat/apps/auto_annotation/views.py +++ /dev/null @@ -1,265 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -import django_rq -import json -import os - -from django.http import HttpResponse, JsonResponse, HttpResponseBadRequest -from rest_framework.decorators import api_view -from django.db.models import Q -from rules.contrib.views import permission_required, objectgetter - -from cvat.apps.authentication.decorators import login_required -from cvat.apps.engine.models import Task as TaskModel -from cvat.apps.authentication.auth import has_admin_role -from cvat.apps.engine.log import slogger - -from .model_loader import load_labelmap -from . import model_manager -from .models import AnnotationModel - -@login_required -@permission_required(perm=["engine.task.change"], - fn=objectgetter(TaskModel, "tid"), raise_exception=True) -def cancel(request, tid): - try: - queue = django_rq.get_queue("low") - job = queue.fetch_job("auto_annotation.run.{}".format(tid)) - if job is None or job.is_finished or job.is_failed: - raise Exception("Task is not being annotated currently") - elif "cancel" not in job.meta: - job.meta["cancel"] = True - job.save() - - except Exception as ex: - try: - slogger.task[tid].exception("cannot cancel auto annotation for task #{}".format(tid), exc_info=True) - except Exception as logger_ex: - slogger.glob.exception("exception was occured during cancel auto annotation request for task {}: {}".format(tid, str(logger_ex)), exc_info=True) - return HttpResponseBadRequest(str(ex)) - - return HttpResponse() - -@login_required -@permission_required(perm=["auto_annotation.model.create"], raise_exception=True) -def create_model(request): - if request.method != 'POST': - return HttpResponseBadRequest("Only POST requests are accepted") - - try: - params = request.POST - storage = params["storage"] - name = params["name"] - is_shared = params["shared"].lower() == "true" - if is_shared and not has_admin_role(request.user): - raise Exception("Only admin can create shared models") - - files = request.FILES if storage == "local" else params - model = files["xml"] - weights = files["bin"] - labelmap = files["json"] - interpretation_script = files["py"] - owner = request.user - - rq_id = model_manager.create_or_update( - dl_model_id=None, - name=name, - model_file=model, - weights_file=weights, - labelmap_file=labelmap, - interpretation_file=interpretation_script, - owner=owner, - storage=storage, - is_shared=is_shared, - ) - - return JsonResponse({"id": rq_id}) - except Exception as e: - return HttpResponseBadRequest(str(e)) - -@login_required -@permission_required(perm=["auto_annotation.model.update"], - fn=objectgetter(AnnotationModel, "mid"), raise_exception=True) -def update_model(request, mid): - if request.method != 'POST': - return HttpResponseBadRequest("Only POST requests are accepted") - - try: - params = request.POST - storage = params["storage"] - name = params.get("name") - is_shared = params.get("shared") - is_shared = is_shared.lower() == "true" if is_shared else None - if is_shared and not has_admin_role(request.user): - raise Exception("Only admin can create shared models") - files = request.FILES - model = files.get("xml") - weights = files.get("bin") - labelmap = files.get("json") - interpretation_script = files.get("py") - - rq_id = model_manager.create_or_update( - dl_model_id=mid, - name=name, - model_file=model, - weights_file=weights, - labelmap_file=labelmap, - interpretation_file=interpretation_script, - owner=None, - storage=storage, - is_shared=is_shared, - ) - - return JsonResponse({"id": rq_id}) - except Exception as e: - return HttpResponseBadRequest(str(e)) - -@login_required -@permission_required(perm=["auto_annotation.model.delete"], - fn=objectgetter(AnnotationModel, "mid"), raise_exception=True) -def delete_model(request, mid): - if request.method != 'DELETE': - return HttpResponseBadRequest("Only DELETE requests are accepted") - model_manager.delete(mid) - return HttpResponse() - -@api_view(['POST']) -@login_required -def get_meta_info(request): - try: - tids = request.data - response = { - "admin": has_admin_role(request.user), - "models": [], - "run": {}, - } - dl_model_list = list(AnnotationModel.objects.filter(Q(owner=request.user) | Q(primary=True) | Q(shared=True)).order_by('-created_date')) - for dl_model in dl_model_list: - labels = [] - if dl_model.labelmap_file and os.path.exists(dl_model.labelmap_file.name): - with dl_model.labelmap_file.open('r') as f: - labels = list(json.load(f)["label_map"].values()) - - response["models"].append({ - "id": dl_model.id, - "name": dl_model.name, - "primary": dl_model.primary, - "uploadDate": dl_model.created_date, - "updateDate": dl_model.updated_date, - "labels": labels, - "owner": dl_model.owner.id, - }) - - queue = django_rq.get_queue("low") - for tid in tids: - rq_id = "auto_annotation.run.{}".format(tid) - job = queue.fetch_job(rq_id) - if job is not None: - response["run"][tid] = { - "status": job.get_status(), - "rq_id": rq_id, - } - - return JsonResponse(response) - except Exception as e: - return HttpResponseBadRequest(str(e)) - -@login_required -@permission_required(perm=["engine.task.change"], - fn=objectgetter(TaskModel, "tid"), raise_exception=True) -@permission_required(perm=["auto_annotation.model.access"], - fn=objectgetter(AnnotationModel, "mid"), raise_exception=True) -def start_annotation(request, mid, tid): - slogger.glob.info("auto annotation create request for task {} via DL model {}".format(tid, mid)) - try: - db_task = TaskModel.objects.get(pk=tid) - queue = django_rq.get_queue("low") - job = queue.fetch_job("auto_annotation.run.{}".format(tid)) - if job is not None and (job.is_started or job.is_queued): - raise Exception("The process is already running") - - data = json.loads(request.body.decode('utf-8')) - - should_reset = data["reset"] - user_defined_labels_mapping = data["labels"] - - dl_model = AnnotationModel.objects.get(pk=mid) - - model_file_path = dl_model.model_file.name - weights_file_path = dl_model.weights_file.name - labelmap_file = dl_model.labelmap_file.name - convertation_file_path = dl_model.interpretation_file.name - restricted = not has_admin_role(dl_model.owner) - - db_labels = db_task.label_set.prefetch_related("attributespec_set").all() - db_attributes = {db_label.id: - {db_attr.name: db_attr.id for db_attr in db_label.attributespec_set.all()} for db_label in db_labels} - db_labels = {db_label.name:db_label.id for db_label in db_labels} - - model_labels = {value: key for key, value in load_labelmap(labelmap_file).items()} - - labels_mapping = {} - for user_model_label, user_db_label in user_defined_labels_mapping.items(): - if user_model_label in model_labels and user_db_label in db_labels: - labels_mapping[int(model_labels[user_model_label])] = db_labels[user_db_label] - - if not labels_mapping: - raise Exception("No labels found for annotation") - - rq_id="auto_annotation.run.{}".format(tid) - queue.enqueue_call(func=model_manager.run_inference_thread, - args=( - tid, - model_file_path, - weights_file_path, - labels_mapping, - db_attributes, - convertation_file_path, - should_reset, - request.user, - restricted, - ), - job_id = rq_id, - timeout=604800) # 7 days - - slogger.task[tid].info("auto annotation job enqueued") - - except Exception as ex: - try: - slogger.task[tid].exception("exception was occurred during annotation request", exc_info=True) - except Exception as logger_ex: - slogger.glob.exception("exception was occurred during create auto annotation request for task {}: {}".format(tid, str(logger_ex)), exc_info=True) - return HttpResponseBadRequest(str(ex)) - - return JsonResponse({"id": rq_id}) - -@login_required -def check(request, rq_id): - try: - target_queue = "low" if "auto_annotation.run" in rq_id else "default" - queue = django_rq.get_queue(target_queue) - job = queue.fetch_job(rq_id) - if job is not None and "cancel" in job.meta: - return JsonResponse({"status": "finished"}) - data = {} - if job is None: - data["status"] = "unknown" - elif job.is_queued: - data["status"] = "queued" - elif job.is_started: - data["status"] = "started" - data["progress"] = job.meta["progress"] if "progress" in job.meta else "" - elif job.is_finished: - data["status"] = "finished" - job.delete() - else: - data["status"] = "failed" - data["error"] = job.exc_info - job.delete() - - except Exception: - data["status"] = "unknown" - - return JsonResponse(data) diff --git a/cvat/apps/auto_segmentation/__init__.py b/cvat/apps/auto_segmentation/__init__.py deleted file mode 100644 index a0fca4cb..00000000 --- a/cvat/apps/auto_segmentation/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ - -# Copyright (C) 2018-2019 Intel Corporation -# -# SPDX-License-Identifier: MIT diff --git a/cvat/apps/auto_segmentation/admin.py b/cvat/apps/auto_segmentation/admin.py deleted file mode 100644 index 3c40ebdf..00000000 --- a/cvat/apps/auto_segmentation/admin.py +++ /dev/null @@ -1,8 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - - -# Register your models here. - diff --git a/cvat/apps/auto_segmentation/apps.py b/cvat/apps/auto_segmentation/apps.py deleted file mode 100644 index 03322710..00000000 --- a/cvat/apps/auto_segmentation/apps.py +++ /dev/null @@ -1,11 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.apps import AppConfig - - -class AutoSegmentationConfig(AppConfig): - name = 'auto_segmentation' - diff --git a/cvat/apps/auto_segmentation/migrations/__init__.py b/cvat/apps/auto_segmentation/migrations/__init__.py deleted file mode 100644 index d8e62e54..00000000 --- a/cvat/apps/auto_segmentation/migrations/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - diff --git a/cvat/apps/auto_segmentation/models.py b/cvat/apps/auto_segmentation/models.py deleted file mode 100644 index 37401bdd..00000000 --- a/cvat/apps/auto_segmentation/models.py +++ /dev/null @@ -1,8 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - - -# Create your models here. - diff --git a/cvat/apps/auto_segmentation/tests.py b/cvat/apps/auto_segmentation/tests.py deleted file mode 100644 index d20a46ab..00000000 --- a/cvat/apps/auto_segmentation/tests.py +++ /dev/null @@ -1,8 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - - -# Create your tests here. - diff --git a/cvat/apps/auto_segmentation/urls.py b/cvat/apps/auto_segmentation/urls.py deleted file mode 100644 index f84019be..00000000 --- a/cvat/apps/auto_segmentation/urls.py +++ /dev/null @@ -1,14 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.urls import path -from . import views - -urlpatterns = [ - path('create/task/', views.create), - path('check/task/', views.check), - path('cancel/task/', views.cancel), - path('meta/get', views.get_meta_info), -] diff --git a/cvat/apps/auto_segmentation/views.py b/cvat/apps/auto_segmentation/views.py deleted file mode 100644 index 4b15b094..00000000 --- a/cvat/apps/auto_segmentation/views.py +++ /dev/null @@ -1,310 +0,0 @@ - -# Copyright (C) 2018-2020 Intel Corporation -# -# SPDX-License-Identifier: MIT - - -from django.http import HttpResponse, JsonResponse, HttpResponseBadRequest -from rest_framework.decorators import api_view -from rules.contrib.views import permission_required, objectgetter -from cvat.apps.authentication.decorators import login_required -from cvat.apps.dataset_manager.task import put_task_data -from cvat.apps.engine.models import Task as TaskModel -from cvat.apps.engine.serializers import LabeledDataSerializer -from cvat.apps.engine.frame_provider import FrameProvider - -import django_rq -import os -import rq - -import numpy as np - -from cvat.apps.engine.log import slogger - -import sys -import skimage.io -from skimage.measure import find_contours, approximate_polygon - -def run_tensorflow_auto_segmentation(frame_provider, labels_mapping, treshold): - def _convert_to_int(boolean_mask): - return boolean_mask.astype(np.uint8) - - def _convert_to_segmentation(mask): - contours = find_contours(mask, 0.5) - # only one contour exist in our case - contour = contours[0] - contour = np.flip(contour, axis=1) - # Approximate the contour and reduce the number of points - contour = approximate_polygon(contour, tolerance=2.5) - segmentation = contour.ravel().tolist() - return segmentation - - ## INITIALIZATION - - # workarround for tf.placeholder() is not compatible with eager execution - # https://github.com/tensorflow/tensorflow/issues/18165 - import tensorflow as tf - tf.compat.v1.disable_eager_execution() - - # Root directory of the project - ROOT_DIR = os.environ.get('AUTO_SEGMENTATION_PATH') - # Import Mask RCNN - sys.path.append(ROOT_DIR) # To find local version of the library - import mrcnn.model as modellib - - # Import COCO config - sys.path.append(os.path.join(ROOT_DIR, "samples/coco/")) # To find local version - import coco - - # Directory to save logs and trained model - MODEL_DIR = os.path.join(ROOT_DIR, "logs") - - # Local path to trained weights file - COCO_MODEL_PATH = os.path.join(ROOT_DIR, "mask_rcnn_coco.h5") - if COCO_MODEL_PATH is None: - raise OSError('Model path env not found in the system.') - job = rq.get_current_job() - - ## CONFIGURATION - - class InferenceConfig(coco.CocoConfig): - # Set batch size to 1 since we'll be running inference on - # one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU - GPU_COUNT = 1 - IMAGES_PER_GPU = 1 - - # Print config details - config = InferenceConfig() - config.display() - - ## CREATE MODEL AND LOAD TRAINED WEIGHTS - - # Create model object in inference mode. - model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config) - # Load weights trained on MS-COCO - model.load_weights(COCO_MODEL_PATH, by_name=True) - - ## RUN OBJECT DETECTION - result = {} - frames = frame_provider.get_frames(frame_provider.Quality.ORIGINAL) - for image_num, (image_bytes, _) in enumerate(frames): - job.refresh() - if 'cancel' in job.meta: - del job.meta['cancel'] - job.save() - return None - job.meta['progress'] = image_num * 100 / len(frame_provider) - job.save_meta() - - image = skimage.io.imread(image_bytes) - - # for multiple image detection, "batch size" must be equal to number of images - r = model.detect([image], verbose=1) - - r = r[0] - # "r['rois'][index]" gives bounding box around the object - for index, c_id in enumerate(r['class_ids']): - if c_id in labels_mapping.keys(): - if r['scores'][index] >= treshold: - mask = _convert_to_int(r['masks'][:,:,index]) - segmentation = _convert_to_segmentation(mask) - label = labels_mapping[c_id] - if label not in result: - result[label] = [] - result[label].append( - [image_num, segmentation]) - - return result - -def convert_to_cvat_format(data): - result = { - "tracks": [], - "shapes": [], - "tags": [], - "version": 0, - } - - for label in data: - segments = data[label] - for segment in segments: - result['shapes'].append({ - "type": "polygon", - "label_id": label, - "frame": segment[0], - "points": segment[1], - "z_order": 0, - "group": None, - "occluded": False, - "attributes": [], - }) - - return result - -def create_thread(tid, labels_mapping, user): - try: - # If detected object accuracy bigger than threshold it will returend - TRESHOLD = 0.5 - # Init rq job - job = rq.get_current_job() - job.meta['progress'] = 0 - job.save_meta() - # Get job indexes and segment length - db_task = TaskModel.objects.get(pk=tid) - # Get image list - frame_provider = FrameProvider(db_task.data) - - # Run auto segmentation by tf - result = None - slogger.glob.info("auto segmentation with tensorflow framework for task {}".format(tid)) - result = run_tensorflow_auto_segmentation(frame_provider, labels_mapping, TRESHOLD) - - if result is None: - slogger.glob.info('auto segmentation for task {} canceled by user'.format(tid)) - return - - # Modify data format and save - result = convert_to_cvat_format(result) - serializer = LabeledDataSerializer(data = result) - if serializer.is_valid(raise_exception=True): - put_task_data(tid, result) - slogger.glob.info('auto segmentation for task {} done'.format(tid)) - except Exception as ex: - try: - slogger.task[tid].exception('exception was occured during auto segmentation of the task', exc_info=True) - except Exception: - slogger.glob.exception('exception was occured during auto segmentation of the task {}'.format(tid), exc_info=True) - raise ex - -@api_view(['POST']) -@login_required -def get_meta_info(request): - try: - queue = django_rq.get_queue('low') - tids = request.data - result = {} - for tid in tids: - job = queue.fetch_job('auto_segmentation.create/{}'.format(tid)) - if job is not None: - result[tid] = { - "active": job.is_queued or job.is_started, - "success": not job.is_failed - } - - return JsonResponse(result) - except Exception as ex: - slogger.glob.exception('exception was occured during tf meta request', exc_info=True) - return HttpResponseBadRequest(str(ex)) - - -@login_required -@permission_required(perm=['engine.task.change'], - fn=objectgetter(TaskModel, 'tid'), raise_exception=True) -def create(request, tid): - slogger.glob.info('auto segmentation create request for task {}'.format(tid)) - try: - db_task = TaskModel.objects.get(pk=tid) - queue = django_rq.get_queue('low') - job = queue.fetch_job('auto_segmentation.create/{}'.format(tid)) - if job is not None and (job.is_started or job.is_queued): - raise Exception("The process is already running") - - db_labels = db_task.label_set.prefetch_related('attributespec_set').all() - db_labels = {db_label.id:db_label.name for db_label in db_labels} - - # COCO Labels - auto_segmentation_labels = { "BG": 0, - "person": 1, "bicycle": 2, "car": 3, "motorcycle": 4, "airplane": 5, - "bus": 6, "train": 7, "truck": 8, "boat": 9, "traffic_light": 10, - "fire_hydrant": 11, "stop_sign": 12, "parking_meter": 13, "bench": 14, - "bird": 15, "cat": 16, "dog": 17, "horse": 18, "sheep": 19, "cow": 20, - "elephant": 21, "bear": 22, "zebra": 23, "giraffe": 24, "backpack": 25, - "umbrella": 26, "handbag": 27, "tie": 28, "suitcase": 29, "frisbee": 30, - "skis": 31, "snowboard": 32, "sports_ball": 33, "kite": 34, "baseball_bat": 35, - "baseball_glove": 36, "skateboard": 37, "surfboard": 38, "tennis_racket": 39, - "bottle": 40, "wine_glass": 41, "cup": 42, "fork": 43, "knife": 44, "spoon": 45, - "bowl": 46, "banana": 47, "apple": 48, "sandwich": 49, "orange": 50, "broccoli": 51, - "carrot": 52, "hot_dog": 53, "pizza": 54, "donut": 55, "cake": 56, "chair": 57, - "couch": 58, "potted_plant": 59, "bed": 60, "dining_table": 61, "toilet": 62, - "tv": 63, "laptop": 64, "mouse": 65, "remote": 66, "keyboard": 67, "cell_phone": 68, - "microwave": 69, "oven": 70, "toaster": 71, "sink": 72, "refrigerator": 73, - "book": 74, "clock": 75, "vase": 76, "scissors": 77, "teddy_bear": 78, "hair_drier": 79, - "toothbrush": 80 - } - - labels_mapping = {} - for key, labels in db_labels.items(): - if labels in auto_segmentation_labels.keys(): - labels_mapping[auto_segmentation_labels[labels]] = key - - if not len(labels_mapping.values()): - raise Exception('No labels found for auto segmentation') - - # Run auto segmentation job - queue.enqueue_call(func=create_thread, - args=(tid, labels_mapping, request.user), - job_id='auto_segmentation.create/{}'.format(tid), - timeout=604800) # 7 days - - slogger.task[tid].info('tensorflow segmentation job enqueued with labels {}'.format(labels_mapping)) - - except Exception as ex: - try: - slogger.task[tid].exception("exception was occured during tensorflow segmentation request", exc_info=True) - except Exception: - pass - return HttpResponseBadRequest(str(ex)) - - return HttpResponse() - -@login_required -@permission_required(perm=['engine.task.access'], - fn=objectgetter(TaskModel, 'tid'), raise_exception=True) -def check(request, tid): - try: - queue = django_rq.get_queue('low') - job = queue.fetch_job('auto_segmentation.create/{}'.format(tid)) - if job is not None and 'cancel' in job.meta: - return JsonResponse({'status': 'finished'}) - data = {} - if job is None: - data['status'] = 'unknown' - elif job.is_queued: - data['status'] = 'queued' - elif job.is_started: - data['status'] = 'started' - data['progress'] = job.meta['progress'] - elif job.is_finished: - data['status'] = 'finished' - job.delete() - else: - data['status'] = 'failed' - data['stderr'] = job.exc_info - job.delete() - - except Exception: - data['status'] = 'unknown' - - return JsonResponse(data) - - -@login_required -@permission_required(perm=['engine.task.change'], - fn=objectgetter(TaskModel, 'tid'), raise_exception=True) -def cancel(request, tid): - try: - queue = django_rq.get_queue('low') - job = queue.fetch_job('auto_segmentation.create/{}'.format(tid)) - if job is None or job.is_finished or job.is_failed: - raise Exception('Task is not being segmented currently') - elif 'cancel' not in job.meta: - job.meta['cancel'] = True - job.save() - - except Exception as ex: - try: - slogger.task[tid].exception("cannot cancel tensorflow segmentation for task #{}".format(tid), exc_info=True) - except Exception: - pass - return HttpResponseBadRequest(str(ex)) - - return HttpResponse() diff --git a/cvat/apps/dataset_manager/annotation.py b/cvat/apps/dataset_manager/annotation.py index 040788bc..30393dd5 100644 --- a/cvat/apps/dataset_manager/annotation.py +++ b/cvat/apps/dataset_manager/annotation.py @@ -316,7 +316,10 @@ class ShapeManager(ObjectManager): def _calc_objects_similarity(obj0, obj1, start_frame, overlap): def _calc_polygons_similarity(p0, p1): overlap_area = p0.intersection(p1).area - return overlap_area / (p0.area + p1.area - overlap_area) + if p0.area == 0 or p1.area == 0: # a line with many points + return 0 + else: + return overlap_area / (p0.area + p1.area - overlap_area) has_same_type = obj0["type"] == obj1["type"] has_same_label = obj0.get("label_id") == obj1.get("label_id") @@ -328,7 +331,7 @@ class ShapeManager(ObjectManager): return _calc_polygons_similarity(p0, p1) elif obj0["type"] == ShapeType.POLYGON: p0 = geometry.Polygon(pairwise(obj0["points"])) - p1 = geometry.Polygon(pairwise(obj0["points"])) + p1 = geometry.Polygon(pairwise(obj1["points"])) return _calc_polygons_similarity(p0, p1) else: diff --git a/cvat/apps/dextr_segmentation/README.md b/cvat/apps/dextr_segmentation/README.md deleted file mode 100644 index 2382a380..00000000 --- a/cvat/apps/dextr_segmentation/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Semi-Automatic Segmentation with [Deep Extreme Cut](http://www.vision.ee.ethz.ch/~cvlsegmentation/dextr/) - -## About the application - -The application allows to use deep learning models for semi-automatic semantic and instance segmentation. -You can get a segmentation polygon from four (or more) extreme points of an object. -This application uses the pre-trained DEXTR model which has been converted to Inference Engine format. - -We are grateful to K.K. Maninis, S. Caelles, J. Pont-Tuset, and L. Van Gool who permitted using their models in our tool - -## Build docker image -```bash -# OpenVINO component is also needed -docker-compose -f docker-compose.yml -f components/openvino/docker-compose.openvino.yml -f cvat/apps/dextr_segmentation/docker-compose.dextr.yml build -``` - -## Run docker container -```bash -docker-compose -f docker-compose.yml -f components/openvino/docker-compose.openvino.yml -f cvat/apps/dextr_segmentation/docker-compose.dextr.yml up -d -``` - -## Using - -1. Open a job -2. Select "Auto Segmentation" in the list of shapes -3. Run the draw mode as usually (by press the "Create Shape" button or by "N" shortcut) -4. Click four-six (or more if it's need) extreme points of an object -5. Close the draw mode as usually (by shortcut or pressing the button "Stop Creation") -6. Wait a moment and you will get a class agnostic annotation polygon -7. You can close an annotation request if it is too long -(in case if it is queued to rq worker and all workers are busy) diff --git a/cvat/apps/dextr_segmentation/__init__.py b/cvat/apps/dextr_segmentation/__init__.py deleted file mode 100644 index 472c2ac3..00000000 --- a/cvat/apps/dextr_segmentation/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from cvat.settings.base import JS_3RDPARTY - -JS_3RDPARTY['engine'] = JS_3RDPARTY.get('engine', []) + ['dextr_segmentation/js/enginePlugin.js'] diff --git a/cvat/apps/dextr_segmentation/apps.py b/cvat/apps/dextr_segmentation/apps.py deleted file mode 100644 index d5d43a88..00000000 --- a/cvat/apps/dextr_segmentation/apps.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.apps import AppConfig - -class DextrSegmentationConfig(AppConfig): - name = 'dextr_segmentation' diff --git a/cvat/apps/dextr_segmentation/dextr.py b/cvat/apps/dextr_segmentation/dextr.py deleted file mode 100644 index d6eb2002..00000000 --- a/cvat/apps/dextr_segmentation/dextr.py +++ /dev/null @@ -1,119 +0,0 @@ - -# Copyright (C) 2018-2020 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from cvat.apps.auto_annotation.inference_engine import make_plugin_or_core, make_network -from cvat.apps.engine.frame_provider import FrameProvider - -import os -import cv2 -import PIL -import numpy as np - -_IE_CPU_EXTENSION = os.getenv("IE_CPU_EXTENSION", "libcpu_extension_avx2.so") -_IE_PLUGINS_PATH = os.getenv("IE_PLUGINS_PATH", None) - -_DEXTR_MODEL_DIR = os.getenv("DEXTR_MODEL_DIR", None) -_DEXTR_PADDING = 50 -_DEXTR_TRESHOLD = 0.9 -_DEXTR_SIZE = 512 - -class DEXTR_HANDLER: - def __init__(self): - self._plugin = None - self._network = None - self._exec_network = None - self._input_blob = None - self._output_blob = None - if not _DEXTR_MODEL_DIR: - raise Exception("DEXTR_MODEL_DIR is not defined") - - - def handle(self, db_data, frame, points): - # Lazy initialization - if not self._plugin: - self._plugin = make_plugin_or_core() - self._network = make_network(os.path.join(_DEXTR_MODEL_DIR, 'dextr.xml'), - os.path.join(_DEXTR_MODEL_DIR, 'dextr.bin')) - self._input_blob = next(iter(self._network.inputs)) - self._output_blob = next(iter(self._network.outputs)) - if getattr(self._plugin, 'load_network', False): - self._exec_network = self._plugin.load_network(self._network, 'CPU') - else: - self._exec_network = self._plugin.load(network=self._network) - - frame_provider = FrameProvider(db_data) - image = frame_provider.get_frame(frame, frame_provider.Quality.ORIGINAL) - image = PIL.Image.open(image[0]) - numpy_image = np.array(image) - points = np.asarray([[int(p["x"]), int(p["y"])] for p in points], dtype=int) - - # Padding mustn't be more than the closest distance to an edge of an image - [height, width] = numpy_image.shape[:2] - x_values = points[:, 0] - y_values = points[:, 1] - [min_x, max_x] = [np.min(x_values), np.max(x_values)] - [min_y, max_y] = [np.min(y_values), np.max(y_values)] - padding = min(min_x, min_y, width - max_x, height - max_y, _DEXTR_PADDING) - bounding_box = ( - max(min(points[:, 0]) - padding, 0), - max(min(points[:, 1]) - padding, 0), - min(max(points[:, 0]) + padding, width - 1), - min(max(points[:, 1]) + padding, height - 1) - ) - - # Prepare an image - numpy_cropped = np.array(image.crop(bounding_box)) - resized = cv2.resize(numpy_cropped, (_DEXTR_SIZE, _DEXTR_SIZE), - interpolation = cv2.INTER_CUBIC).astype(np.float32) - - # Make a heatmap - points = points - [min(points[:, 0]), min(points[:, 1])] + [padding, padding] - points = (points * [_DEXTR_SIZE / numpy_cropped.shape[1], _DEXTR_SIZE / numpy_cropped.shape[0]]).astype(int) - heatmap = np.zeros(shape=resized.shape[:2], dtype=np.float64) - for point in points: - gaussian_x_axis = np.arange(0, _DEXTR_SIZE, 1, float) - point[0] - gaussian_y_axis = np.arange(0, _DEXTR_SIZE, 1, float)[:, np.newaxis] - point[1] - gaussian = np.exp(-4 * np.log(2) * ((gaussian_x_axis ** 2 + gaussian_y_axis ** 2) / 100)).astype(np.float64) - heatmap = np.maximum(heatmap, gaussian) - cv2.normalize(heatmap, heatmap, 0, 255, cv2.NORM_MINMAX) - - # Concat an image and a heatmap - input_dextr = np.concatenate((resized, heatmap[:, :, np.newaxis].astype(resized.dtype)), axis=2) - input_dextr = input_dextr.transpose((2,0,1)) - - pred = self._exec_network.infer(inputs={self._input_blob: input_dextr[np.newaxis, ...]})[self._output_blob][0, 0, :, :] - pred = cv2.resize(pred, tuple(reversed(numpy_cropped.shape[:2])), interpolation = cv2.INTER_CUBIC) - result = np.zeros(numpy_image.shape[:2]) - result[bounding_box[1]:bounding_box[1] + pred.shape[0], bounding_box[0]:bounding_box[0] + pred.shape[1]] = pred > _DEXTR_TRESHOLD - - # Convert a mask to a polygon - result = np.array(result, dtype=np.uint8) - cv2.normalize(result,result,0,255,cv2.NORM_MINMAX) - contours = None - if int(cv2.__version__.split('.')[0]) > 3: - contours = cv2.findContours(result, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS)[0] - else: - contours = cv2.findContours(result, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS)[1] - - contours = max(contours, key=lambda arr: arr.size) - if contours.shape.count(1): - contours = np.squeeze(contours) - if contours.size < 3 * 2: - raise Exception('Less then three point have been detected. Can not build a polygon.') - - result = "" - for point in contours: - result += "{},{} ".format(int(point[0]), int(point[1])) - result = result[:-1] - - return result - - def __del__(self): - if self._exec_network: - del self._exec_network - if self._network: - del self._network - if self._plugin: - del self._plugin diff --git a/cvat/apps/dextr_segmentation/docker-compose.dextr.yml b/cvat/apps/dextr_segmentation/docker-compose.dextr.yml deleted file mode 100644 index 468523b8..00000000 --- a/cvat/apps/dextr_segmentation/docker-compose.dextr.yml +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT -# - -version: "2.3" - -services: - cvat: - build: - context: . - args: - WITH_DEXTR: "yes" diff --git a/cvat/apps/dextr_segmentation/static/dextr_segmentation/js/enginePlugin.js b/cvat/apps/dextr_segmentation/static/dextr_segmentation/js/enginePlugin.js deleted file mode 100644 index 0869ba8d..00000000 --- a/cvat/apps/dextr_segmentation/static/dextr_segmentation/js/enginePlugin.js +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2018 Intel Corporation - * - * SPDX-License-Identifier: MIT - */ - -/* global - AREA_TRESHOLD:false - PolyShapeModel:false - ShapeCreatorModel:true - ShapeCreatorView:true - showMessage:false -*/ - -/* eslint no-underscore-dangle: 0 */ - -window.addEventListener('DOMContentLoaded', () => { - $('').appendTo('#shapeTypeSelector'); - - const dextrCancelButtonId = 'dextrCancelButton'; - const dextrOverlay = $(` - `).appendTo('body'); - - const dextrCancelButton = $(`#${dextrCancelButtonId}`); - dextrCancelButton.on('click', () => { - dextrCancelButton.prop('disabled', true); - $.ajax({ - url: `/dextr/cancel/${window.cvat.job.id}`, - type: 'GET', - error: (errorData) => { - const message = `Can not cancel segmentation. Code: ${errorData.status}. - Message: ${errorData.responseText || errorData.statusText}`; - showMessage(message); - }, - complete: () => { - dextrCancelButton.prop('disabled', false); - }, - }); - }); - - function ShapeCreatorModelWrapper(OriginalClass) { - // Constructor will patch some properties for a created instance - function constructorDecorator(...args) { - const instance = new OriginalClass(...args); - - // Decorator for the defaultType property - Object.defineProperty(instance, 'defaultType', { - get: () => instance._defaultType, - set: (type) => { - if (!['box', 'box_by_4_points', 'points', 'polygon', - 'polyline', 'auto_segmentation', 'cuboid'].includes(type)) { - throw Error(`Unknown shape type found ${type}`); - } - instance._defaultType = type; - }, - }); - - // Decorator for finish method. - const decoratedFinish = instance.finish; - instance.finish = (result) => { - if (instance._defaultType === 'auto_segmentation') { - try { - instance._defaultType = 'polygon'; - decoratedFinish.call(instance, result); - } finally { - instance._defaultType = 'auto_segmentation'; - } - } else { - decoratedFinish.call(instance, result); - } - }; - - return instance; - } - - constructorDecorator.prototype = OriginalClass.prototype; - constructorDecorator.prototype.constructor = constructorDecorator; - return constructorDecorator; - } - - - function ShapeCreatorViewWrapper(OriginalClass) { - // Constructor will patch some properties for each instance - function constructorDecorator(...args) { - const instance = new OriginalClass(...args); - - // Decorator for the _create() method. - // We save the decorated _create() and we will use it if type != 'auto_segmentation' - const decoratedCreate = instance._create; - instance._create = () => { - if (instance._type !== 'auto_segmentation') { - decoratedCreate.call(instance); - return; - } - - instance._drawInstance = instance._frameContent.polyline().draw({ snapToGrid: 0.1 }).addClass('shapeCreation').attr({ - 'stroke-width': 0, - z_order: Number.MAX_SAFE_INTEGER, - }); - instance._createPolyEvents(); - - /* the _createPolyEvents method have added "drawdone" - * event handler which invalid for this case - * because of that reason we remove the handler and - * create the valid handler instead - */ - instance._drawInstance.off('drawdone').on('drawdone', (e) => { - let actualPoints = window.cvat.translate.points.canvasToActual(e.target.getAttribute('points')); - actualPoints = PolyShapeModel.convertStringToNumberArray(actualPoints); - - if (actualPoints.length < 4) { - showMessage('It is need to specify minimum four extreme points for an object'); - instance._controller.switchCreateMode(true); - return; - } - - const { frameWidth } = window.cvat.player.geometry; - const { frameHeight } = window.cvat.player.geometry; - for (let idx = 0; idx < actualPoints.length; idx += 1) { - const point = actualPoints[idx]; - point.x = Math.clamp(point.x, 0, frameWidth); - point.y = Math.clamp(point.y, 0, frameHeight); - } - - e.target.setAttribute('points', - window.cvat.translate.points.actualToCanvas( - PolyShapeModel.convertNumberArrayToString(actualPoints), - )); - - const polybox = e.target.getBBox(); - const area = polybox.width * polybox.height; - - if (area > AREA_TRESHOLD) { - $.ajax({ - url: `/dextr/create/${window.cvat.job.id}`, - type: 'POST', - data: JSON.stringify({ - frame: window.cvat.player.frames.current, - points: actualPoints, - }), - contentType: 'application/json', - success: () => { - function intervalCallback() { - $.ajax({ - url: `/dextr/check/${window.cvat.job.id}`, - type: 'GET', - success: (jobData) => { - if (['queued', 'started'].includes(jobData.status)) { - if (jobData.status === 'queued') { - dextrCancelButton.prop('disabled', false); - } - setTimeout(intervalCallback, 1000); - } else { - dextrOverlay.addClass('hidden'); - if (jobData.status === 'finished') { - if (jobData.result) { - instance._controller.finish({ points: jobData.result }, 'polygon'); - } - } else if (jobData.status === 'failed') { - const message = `Segmentation has fallen. Error: '${jobData.stderr}'`; - showMessage(message); - } else { - let message = `Check segmentation request returned "${jobData.status}" status.`; - if (jobData.stderr) { - message += ` Error: ${jobData.stderr}`; - } - showMessage(message); - } - } - }, - error: (errorData) => { - dextrOverlay.addClass('hidden'); - const message = `Can not check segmentation. Code: ${errorData.status}.` - + ` Message: ${errorData.responseText || errorData.statusText}`; - showMessage(message); - }, - }); - } - - dextrCancelButton.prop('disabled', true); - dextrOverlay.removeClass('hidden'); - setTimeout(intervalCallback, 1000); - }, - error: (errorData) => { - const message = `Can not cancel ReID process. Code: ${errorData.status}.` - + ` Message: ${errorData.responseText || errorData.statusText}`; - showMessage(message); - }, - }); - } - - instance._controller.switchCreateMode(true); - }); // end of "drawdone" handler - }; // end of _create() method - - return instance; - } // end of constructorDecorator() - - constructorDecorator.prototype = OriginalClass.prototype; - constructorDecorator.prototype.constructor = constructorDecorator; - return constructorDecorator; - } // end of ShapeCreatorViewWrapper - - // Apply patch for classes - ShapeCreatorModel = ShapeCreatorModelWrapper(ShapeCreatorModel); - ShapeCreatorView = ShapeCreatorViewWrapper(ShapeCreatorView); -}); diff --git a/cvat/apps/dextr_segmentation/urls.py b/cvat/apps/dextr_segmentation/urls.py deleted file mode 100644 index 6b3120b6..00000000 --- a/cvat/apps/dextr_segmentation/urls.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (C) 2018-2020 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.urls import path -from . import views - -urlpatterns = [ - path('create/', views.create), - path('cancel/', views.cancel), - path('check/', views.check), - path('enabled', views.enabled) -] diff --git a/cvat/apps/dextr_segmentation/views.py b/cvat/apps/dextr_segmentation/views.py deleted file mode 100644 index dd78a2b0..00000000 --- a/cvat/apps/dextr_segmentation/views.py +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.http import HttpResponse, HttpResponseBadRequest, JsonResponse -from cvat.apps.authentication.decorators import login_required -from rules.contrib.views import permission_required, objectgetter - -from cvat.apps.engine.models import Job -from cvat.apps.engine.log import slogger -from cvat.apps.dextr_segmentation.dextr import DEXTR_HANDLER - -import django_rq -import json -import rq - -__RQ_QUEUE_NAME = "default" -__DEXTR_HANDLER = DEXTR_HANDLER() - -def _dextr_thread(db_data, frame, points): - job = rq.get_current_job() - job.meta["result"] = __DEXTR_HANDLER.handle(db_data, frame, points) - job.save_meta() - - -@login_required -@permission_required(perm=["engine.job.change"], - fn=objectgetter(Job, "jid"), raise_exception=True) -def create(request, jid): - try: - data = json.loads(request.body.decode("utf-8")) - - points = data["points"] - frame = int(data["frame"]) - username = request.user.username - - slogger.job[jid].info("create dextr request for the JOB: {} ".format(jid) - + "by the USER: {} on the FRAME: {}".format(username, frame)) - - db_data = Job.objects.select_related("segment__task__data").get(id=jid).segment.task.data - - queue = django_rq.get_queue(__RQ_QUEUE_NAME) - rq_id = "dextr.create/{}/{}".format(jid, username) - job = queue.fetch_job(rq_id) - - if job is not None and (job.is_started or job.is_queued): - if "cancel" not in job.meta: - raise Exception("Segmentation process has been already run for the " + - "JOB: {} and the USER: {}".format(jid, username)) - else: - job.delete() - - queue.enqueue_call(func=_dextr_thread, - args=(db_data, frame, points), - job_id=rq_id, - timeout=15, - ttl=30) - - return HttpResponse() - except Exception as ex: - slogger.job[jid].error("can't create a dextr request for the job {}".format(jid), exc_info=True) - return HttpResponseBadRequest(str(ex)) - - -@login_required -@permission_required(perm=["engine.job.change"], - fn=objectgetter(Job, "jid"), raise_exception=True) -def cancel(request, jid): - try: - username = request.user.username - slogger.job[jid].info("cancel dextr request for the JOB: {} ".format(jid) - + "by the USER: {}".format(username)) - - queue = django_rq.get_queue(__RQ_QUEUE_NAME) - rq_id = "dextr.create/{}/{}".format(jid, username) - job = queue.fetch_job(rq_id) - - if job is None or job.is_finished or job.is_failed: - raise Exception("Segmentation isn't running now") - elif "cancel" not in job.meta: - job.meta["cancel"] = True - job.save_meta() - - return HttpResponse() - except Exception as ex: - slogger.job[jid].error("can't cancel a dextr request for the job {}".format(jid), exc_info=True) - return HttpResponseBadRequest(str(ex)) - - -@login_required -@permission_required(perm=["engine.job.change"], - fn=objectgetter(Job, "jid"), raise_exception=True) -def check(request, jid): - try: - username = request.user.username - slogger.job[jid].info("check dextr request for the JOB: {} ".format(jid) - + "by the USER: {}".format(username)) - - queue = django_rq.get_queue(__RQ_QUEUE_NAME) - rq_id = "dextr.create/{}/{}".format(jid, username) - job = queue.fetch_job(rq_id) - data = {} - - if job is None: - data["status"] = "unknown" - else: - if "cancel" in job.meta: - data["status"] = "finished" - elif job.is_queued: - data["status"] = "queued" - elif job.is_started: - data["status"] = "started" - elif job.is_finished: - data["status"] = "finished" - data["result"] = job.meta["result"] - job.delete() - else: - data["status"] = "failed" - data["stderr"] = job.exc_info - job.delete() - - return JsonResponse(data) - except Exception as ex: - slogger.job[jid].error("can't check a dextr request for the job {}".format(jid), exc_info=True) - return HttpResponseBadRequest(str(ex)) - -def enabled(request): - return HttpResponse() diff --git a/cvat/apps/documentation/faq.md b/cvat/apps/documentation/faq.md index 4271e193..d846a093 100644 --- a/cvat/apps/documentation/faq.md +++ b/cvat/apps/documentation/faq.md @@ -4,14 +4,11 @@ - [How to change default CVAT hostname or port](#how-to-change-default-cvat-hostname-or-port) - [How to configure connected share folder on Windows](#how-to-configure-connected-share-folder-on-windows) - [How to make unassigned tasks not visible to all users](#how-to-make-unassigned-tasks-not-visible-to-all-users) -- [Can Nvidia GPU be used to run inference with my own model](#can-nvidia-gpu-be-used-to-run-inference-with-my-own-model) -- [What versions of OpenVINO toolkit are supported](#what-versions-of-openvino-toolkit-are-supported) - [Where are uploaded images/videos stored](#where-are-uploaded-imagesvideos-stored) - [Where are annotations stored](#where-are-annotations-stored) - [How to mark job/task as completed](#how-to-mark-jobtask-as-completed) - [How to install CVAT on Windows 10 Home](#how-to-install-cvat-on-windows-10-home) - ## How to update CVAT Before upgrading, please follow the official docker [manual](https://docs.docker.com/storage/volumes/#backup-restore-or-migrate-data-volumes) and backup all CVAT volumes. @@ -81,14 +78,6 @@ volumes: ## How to make unassigned tasks not visible to all users Set [reduce_task_visibility](../../settings/base.py#L424) variable to `True`. -## Can Nvidia GPU be used to run inference with my own model -Nvidia GPU can be used to accelerate inference of [tf_annotation](../../../components/tf_annotation/README.md) and [auto_segmentation](../../../components/auto_segmentation/README.md) models. - -OpenVino doesn't support Nvidia cards, so you can run your own models only on CPU. - -## What versions of OpenVINO toolkit are supported -These versions are supported: `2019 R3`, `2019 R3.1`, `2020 1`, `2020 2` - ## Where are uploaded images/videos stored The uploaded data is stored in the `cvat_data` docker volume: ```yml diff --git a/cvat/apps/documentation/installation.md b/cvat/apps/documentation/installation.md index 0f5ed35c..286c7392 100644 --- a/cvat/apps/documentation/installation.md +++ b/cvat/apps/documentation/installation.md @@ -4,6 +4,7 @@ - [Mac OS Mojave](#mac-os-mojave) - [Advanced topics](#advanced-topics) - [Additional components](#additional-components) + - [Semi-automatic and automatic annotation](#semi-automatic-and-automatic-annotation) - [Stop all containers](#stop-all-containers) - [Advanced settings](#advanced-settings) - [Share path](#share-path) @@ -246,22 +247,52 @@ server. Proxy is an advanced topic and it is not covered by the guide. ### Additional components -- [Auto annotation using DL models in OpenVINO toolkit format](/cvat/apps/auto_annotation/README.md) - [Analytics: management and monitoring of data annotation team](/components/analytics/README.md) -- [TF Object Detection API: auto annotation](/components/tf_annotation/README.md) -- [Support for NVIDIA GPUs](/components/cuda/README.md) -- [Semi-automatic segmentation with Deep Extreme Cut](/cvat/apps/dextr_segmentation/README.md) -- [Auto segmentation: Keras+Tensorflow Mask R-CNN Segmentation](/components/auto_segmentation/README.md) ```bash -# Build and run containers with CUDA and OpenVINO support -# IMPORTANT: need to download OpenVINO package before running the command -docker-compose -f docker-compose.yml -f components/cuda/docker-compose.cuda.yml -f components/openvino/docker-compose.openvino.yml up -d --build - # Build and run containers with Analytics component support: docker-compose -f docker-compose.yml -f components/analytics/docker-compose.analytics.yml up -d --build ``` +### Semi-automatic and automatic annotation + +- You have to install `nuctl` command line tool to build and deploy serverless +functions. Download [the latest release](https://github.com/nuclio/nuclio/releases). +- Create `cvat` project inside nuclio dashboard where you will deploy new +serverless functions and deploy a couple of DL models. Commands below should +be run only after CVAT has been installed using docker-compose because it +runs nuclio dashboard which manages all serverless functions. + +```bash +nuctl create project cvat +``` + +```bash +nuctl deploy --project-name cvat \ + --path serverless/openvino/dextr/nuclio \ + --volume `pwd`/serverless/openvino/common:/opt/nuclio/common +``` + +```bash +nuctl deploy --project-name cvat \ + --path serverless/openvino/omz/public/yolo-v3-tf/nuclio \ + --volume `pwd`/serverless/openvino/common:/opt/nuclio/common +``` + +Note: see [deploy.sh](/serverless/deploy.sh) script for more examples. + +List of DL models as serverless functions: + +- [Deep Extreme Cut (OpenVINO)](/serverless/openvino/dextr/nuclio) +- [Faster RCNN (TensorFlow)](/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio) +- [Mask RCNN (OpenVINO)](/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio) +- [YOLO v3 (OpenVINO)](/serverless/openvino/omz/public/yolo-v3-tf/nuclio) +- [Faster RCNN (OpenVINO)](/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio) +- [Text detection v4 (OpenVINO)](/serverless/openvino/omz/intel/text-detection-0004/nuclio) +- [Semantic segmentation for ADAS (OpenVINO)](/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio) +- [Mask RCNN (TensorFlow)](/serverless/tensorflow/matterport/mask_rcnn/nuclio) +- [Person ReID (OpenVINO)](/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio) + ### Stop all containers The command below stops and removes containers, networks, volumes, and images @@ -327,9 +358,9 @@ our server connection. We assume that -- you have sudo access on your server machine, -- you have an IP address to use for remote access, and -- that the local CVAT installation works on your server. +- you have sudo access on your server machine, +- you have an IP address to use for remote access, and +- that the local CVAT installation works on your server. If this is not the case, please complete the steps in the installation manual first. @@ -525,7 +556,7 @@ server { proxy_set_header Host $http_host; proxy_pass_header Set-Cookie; - location ~* /api/.*|git/.*|tensorflow/.*|auto_annotation/.*|analytics/.*|static/.*|admin|admin/.*|documentation/.*|dextr/.*|reid/.* { + location ~* /api/.*|git/.*|analytics/.*|static/.*|admin|admin/.*|documentation/.* { proxy_pass http://cvat:8080; } @@ -550,6 +581,6 @@ server { Start cvat_proxy container with https enabled. -``` +```bash docker start cvat_proxy -``` \ No newline at end of file +``` diff --git a/cvat/apps/engine/models.py b/cvat/apps/engine/models.py index d4c46eb3..d410ef7c 100644 --- a/cvat/apps/engine/models.py +++ b/cvat/apps/engine/models.py @@ -302,7 +302,7 @@ class ShapeType(str, Enum): def __str__(self): return self.value -class source(str, Enum): +class SourceType(str, Enum): AUTO = 'auto' MANUAL = 'manual' @@ -319,7 +319,8 @@ class Annotation(models.Model): label = models.ForeignKey(Label, on_delete=models.CASCADE) frame = models.PositiveIntegerField() group = models.PositiveIntegerField(null=True) - source = models.CharField(max_length=16, choices=source.choices(), default="manual", null=True) + source = models.CharField(max_length=16, choices=SourceType.choices(), + default=str(SourceType.MANUAL), null=True) class Meta: abstract = True @@ -392,20 +393,3 @@ class TrackedShape(Shape): class TrackedShapeAttributeVal(AttributeVal): shape = models.ForeignKey(TrackedShape, on_delete=models.CASCADE) - -class Plugin(models.Model): - name = models.SlugField(max_length=32, primary_key=True) - description = SafeCharField(max_length=8192) - maintainer = models.ForeignKey(User, null=True, blank=True, - on_delete=models.SET_NULL, related_name="maintainers") - created_at = models.DateTimeField(auto_now_add=True) - updated_at = models.DateTimeField(auto_now_add=True) - - # Extend default permission model - class Meta: - default_permissions = () - -class PluginOption(models.Model): - plugin = models.ForeignKey(Plugin, on_delete=models.CASCADE) - name = SafeCharField(max_length=32) - value = SafeCharField(max_length=1024) diff --git a/cvat/apps/engine/serializers.py b/cvat/apps/engine/serializers.py index 90e24714..9edac559 100644 --- a/cvat/apps/engine/serializers.py +++ b/cvat/apps/engine/serializers.py @@ -451,12 +451,6 @@ class FileInfoSerializer(serializers.Serializer): name = serializers.CharField(max_length=1024) type = serializers.ChoiceField(choices=["REG", "DIR"]) -class PluginSerializer(serializers.ModelSerializer): - class Meta: - model = models.Plugin - fields = ('name', 'description', 'maintainer', 'created_at', - 'updated_at') - class LogEventSerializer(serializers.Serializer): job_id = serializers.IntegerField(required=False) task_id = serializers.IntegerField(required=False) diff --git a/cvat/apps/engine/urls.py b/cvat/apps/engine/urls.py index 6c608a00..bb547753 100644 --- a/cvat/apps/engine/urls.py +++ b/cvat/apps/engine/urls.py @@ -30,7 +30,6 @@ router.register('tasks', views.TaskViewSet) router.register('jobs', views.JobViewSet) router.register('users', views.UserViewSet) router.register('server', views.ServerViewSet, basename='server') -router.register('plugins', views.PluginViewSet) router.register('restrictions', RestrictionsViewSet, basename='restrictions') urlpatterns = [ diff --git a/cvat/apps/engine/views.py b/cvat/apps/engine/views.py index 120125ea..c9d6e5d0 100644 --- a/cvat/apps/engine/views.py +++ b/cvat/apps/engine/views.py @@ -37,13 +37,13 @@ from cvat.apps.authentication import auth from cvat.apps.authentication.decorators import login_required from cvat.apps.dataset_manager.serializers import DatasetFormatsSerializer from cvat.apps.engine.frame_provider import FrameProvider -from cvat.apps.engine.models import Job, Plugin, StatusChoice, Task +from cvat.apps.engine.models import Job, StatusChoice, Task from cvat.apps.engine.serializers import ( AboutSerializer, AnnotationFileSerializer, BasicUserSerializer, DataMetaSerializer, DataSerializer, ExceptionSerializer, FileInfoSerializer, JobSerializer, LabeledDataSerializer, - LogEventSerializer, PluginSerializer, ProjectSerializer, - RqStatusSerializer, TaskSerializer, UserSerializer) + LogEventSerializer, ProjectSerializer, RqStatusSerializer, + TaskSerializer, UserSerializer) from cvat.settings.base import CSS_3RDPARTY, JS_3RDPARTY from cvat.apps.engine.utils import av_scan_paths @@ -757,33 +757,6 @@ class UserViewSet(viewsets.GenericViewSet, mixins.ListModelMixin, serializer = serializer_class(request.user, context={ "request": request }) return Response(serializer.data) -class PluginViewSet(viewsets.ModelViewSet): - queryset = Plugin.objects.all() - serializer_class = PluginSerializer - - # @action(detail=True, methods=['GET', 'PATCH', 'PUT'], serializer_class=None) - # def config(self, request, name): - # pass - - # @action(detail=True, methods=['GET', 'POST'], serializer_class=None) - # def data(self, request, name): - # pass - - # @action(detail=True, methods=['GET', 'DELETE', 'PATCH', 'PUT'], - # serializer_class=None, url_path='data/(?P\d+)') - # def data_detail(self, request, name, id): - # pass - - - @action(detail=True, methods=['GET', 'POST'], serializer_class=RqStatusSerializer) - def requests(self, request, name): - pass - - @action(detail=True, methods=['GET', 'DELETE'], - serializer_class=RqStatusSerializer, url_path='requests/(?P\d+)') - def request_detail(self, request, name, rq_id): - pass - def rq_handler(job, exc_type, exc_value, tb): job.exc_info = "".join( traceback.format_exception_only(exc_type, exc_value)) diff --git a/cvat/apps/lambda_manager/__init__.py b/cvat/apps/lambda_manager/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cvat/apps/lambda_manager/apps.py b/cvat/apps/lambda_manager/apps.py new file mode 100644 index 00000000..eda3a971 --- /dev/null +++ b/cvat/apps/lambda_manager/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class LambdaManagerConfig(AppConfig): + name = 'lambda_manager' diff --git a/cvat/apps/lambda_manager/urls.py b/cvat/apps/lambda_manager/urls.py new file mode 100644 index 00000000..0225db53 --- /dev/null +++ b/cvat/apps/lambda_manager/urls.py @@ -0,0 +1,29 @@ +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +from django.urls import path +from rest_framework import routers +from django.urls import include +from . import views + +router = routers.DefaultRouter(trailing_slash=False) +# https://github.com/encode/django-rest-framework/issues/6645 +# I want to "call" my functions. To do that need to map my call method to +# POST (like get HTTP method is mapped to list(...)). One way is to implement +# own CustomRouter. But it is simpler just patch the router instance here. +router.routes[2].mapping.update({'post': 'call'}) +router.register('functions', views.FunctionViewSet, basename='function') +router.register('requests', views.RequestViewSet, basename='request') + +# GET /api/v1/lambda/functions - get list of functions +# GET /api/v1/lambda/functions/ - get information about the function +# POST /api/v1/labmda/requests - call a function +# { "function": "", "mode": "online|offline", "job": "", "frame": "", +# "points": [...], } +# GET /api/v1/lambda/requests - get list of requests +# GET /api/v1/lambda/requests/ - get status of the request +# DEL /api/v1/lambda/requests/ - cancel a request (don't delete) +urlpatterns = [ + path('api/v1/lambda/', include((router.urls, 'cvat'), namespace='v1')) +] \ No newline at end of file diff --git a/cvat/apps/lambda_manager/views.py b/cvat/apps/lambda_manager/views.py new file mode 100644 index 00000000..43ec2e18 --- /dev/null +++ b/cvat/apps/lambda_manager/views.py @@ -0,0 +1,598 @@ +import base64 +import json +from functools import wraps +from enum import Enum + +import django_rq +import requests +import rq +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist, ValidationError +from rest_framework import status, viewsets +from rest_framework.response import Response + +from cvat.apps.authentication import auth +import cvat.apps.dataset_manager as dm +from cvat.apps.engine.frame_provider import FrameProvider +from cvat.apps.engine.models import Task as TaskModel +from cvat.apps.engine.serializers import LabeledDataSerializer +from rest_framework.permissions import IsAuthenticated +from cvat.apps.engine.models import ShapeType, SourceType + +class LambdaType(Enum): + DETECTOR = "detector" + INTERACTOR = "interactor" + REID = "reid" + TRACKER = "tracker" + UNKNOWN = "unknown" + + def __str__(self): + return self.value + +class LambdaGateway: + NUCLIO_ROOT_URL = '/api/functions' + + def _http(self, method="get", scheme=None, host=None, port=None, + url=None, headers=None, data=None): + NUCLIO_GATEWAY = '{}://{}:{}'.format( + scheme or settings.NUCLIO['SCHEME'], + host or settings.NUCLIO['HOST'], + port or settings.NUCLIO['PORT']) + extra_headers = { + 'x-nuclio-project-name': 'cvat', + 'x-nuclio-function-namespace': 'nuclio', + } + if headers: + extra_headers.update(headers) + NUCLIO_TIMEOUT = settings.NUCLIO['DEFAULT_TIMEOUT'] + + if url: + url = "{}{}".format(NUCLIO_GATEWAY, url) + else: + url = NUCLIO_GATEWAY + + reply = getattr(requests, method)(url, headers=extra_headers, + timeout=NUCLIO_TIMEOUT, json=data) + reply.raise_for_status() + response = reply.json() + + return response + + def list(self): + data = self._http(url=self.NUCLIO_ROOT_URL) + response = [LambdaFunction(self, item) for item in data.values()] + return response + + def get(self, func_id): + data = self._http(url=self.NUCLIO_ROOT_URL + '/' + func_id) + response = LambdaFunction(self, data) + return response + + def invoke(self, func, payload): + # NOTE: it is overhead to invoke a function using nuclio + # dashboard REST API. Better to call host.docker.internal: + # Look at https://github.com/docker/for-linux/issues/264. + # host.docker.internal isn't supported by docker on Linux. + # There are many workarounds but let's try to use the + # simple solution. + return self._http(method="post", url='/api/function_invocations', + data=payload, headers={ + 'x-nuclio-function-name': func.id, + 'x-nuclio-path': '/' + }) + +class LambdaFunction: + def __init__(self, gateway, data): + # ID of the function (e.g. omz.public.yolo-v3) + self.id = data['metadata']['name'] + # type of the function (e.g. detector, interactor) + kind = data['metadata']['annotations'].get('type') + try: + self.kind = LambdaType(kind) + except ValueError: + self.kind = LambdaType.UNKNOWN + # dictionary of labels for the function (e.g. car, person) + spec = json.loads(data['metadata']['annotations'].get('spec') or '[]') + labels = [item['name'] for item in spec] + if len(labels) != len(set(labels)): + raise ValidationError( + "`{}` lambda function has non-unique labels".format(self.id), + code=status.HTTP_404_NOT_FOUND) + self.labels = labels + # state of the function + self.state = data['status']['state'] + # description of the function + self.description = data['spec']['description'] + # http port to access the serverless function + self.port = data["status"].get("httpPort") + # framework which is used for the function (e.g. tensorflow, openvino) + self.framework = data['metadata']['annotations'].get('framework') + # display name for the function + self.name = data['metadata']['annotations'].get('name', self.id) + self.gateway = gateway + + def to_dict(self): + response = { + 'id': self.id, + 'kind': str(self.kind), + 'labels': self.labels, + 'state': self.state, + 'description': self.description, + 'framework': self.framework, + 'name': self.name, + } + + return response + + def invoke(self, db_task, data): + try: + payload = {} + threshold = data.get("threshold") + if threshold: + payload.update({ + "threshold": threshold, + }) + quality = data.get("quality") + mapping = data.get("mapping") + if self.kind == LambdaType.DETECTOR: + payload.update({ + "image": self._get_image(db_task, data["frame"], quality) + }) + elif self.kind == LambdaType.INTERACTOR: + payload.update({ + "image": self._get_image(db_task, data["frame"], quality), + "points": data["points"], + }) + elif self.kind == LambdaType.REID: + payload.update({ + "image0": self._get_image(db_task, data["frame0"], quality), + "image1": self._get_image(db_task, data["frame1"], quality), + "boxes0": data["boxes0"], + "boxes1": data["boxes1"] + }) + max_distance = data.get("max_distance") + if max_distance: + payload.update({ + "max_distance": max_distance + }) + else: + raise ValidationError( + '`{}` lambda function has incorrect type: {}' + .format(self.id, self.kind), + code=status.HTTP_500_INTERNAL_SERVER_ERROR) + except KeyError as err: + raise ValidationError( + "`{}` lambda function was called without mandatory argument: {}" + .format(self.id, str(err)), + code=status.HTTP_400_BAD_REQUEST) + + response = self.gateway.invoke(self, payload) + if self.kind == LambdaType.DETECTOR: + if mapping: + for item in response: + item["label"] = mapping.get(item["label"]) + response = [item for item in response if item["label"]] + + return response + + def _get_image(self, db_task, frame, quality): + if quality is None or quality == "original": + quality = FrameProvider.Quality.ORIGINAL + elif quality == "compressed": + quality = FrameProvider.Quality.COMPRESSED + else: + raise ValidationError( + '`{}` lambda function was run '.format(self.id) + + 'with wrong arguments (quality={})'.format(quality), + code=status.HTTP_400_BAD_REQUEST) + + frame_provider = FrameProvider(db_task.data) + image = frame_provider.get_frame(frame, quality=quality) + + return base64.b64encode(image[0].getvalue()).decode('utf-8') + + +class LambdaQueue: + def _get_queue(self): + QUEUE_NAME = "low" + return django_rq.get_queue(QUEUE_NAME) + + def get_jobs(self): + queue = self._get_queue() + # Only failed jobs are not included in the list below. + job_ids = set(queue.get_job_ids() + + queue.started_job_registry.get_job_ids() + + queue.finished_job_registry.get_job_ids() + + queue.scheduled_job_registry.get_job_ids() + + queue.deferred_job_registry.get_job_ids()) + jobs = queue.job_class.fetch_many(job_ids, queue.connection) + + return [LambdaJob(job) for job in jobs if job.meta.get("lambda")] + + def enqueue(self, lambda_func, threshold, task, quality, mapping, cleanup): + jobs = self.get_jobs() + # It is still possible to run several concurrent jobs for the same task. + # But the race isn't critical. The filtration is just a light-weight + # protection. + if list(filter(lambda job: job.get_task() == task and not job.is_finished, jobs)): + raise ValidationError( + "Only one running request is allowed for the same task #{}".format(task), + code=status.HTTP_409_CONFLICT) + + queue = self._get_queue() + # LambdaJob(None) is a workaround for python-rq. It has multiple issues + # with invocation of non-trivial functions. For example, it cannot run + # staticmethod, it cannot run a callable class. Thus I provide an object + # which has __call__ function. + job = queue.create_job(LambdaJob(None), + meta = { "lambda": True }, + kwargs = { + "function": lambda_func, + "threshold": threshold, + "task": task, + "quality": quality, + "cleanup": cleanup, + "mapping": mapping + }) + + queue.enqueue_job(job) + + return LambdaJob(job) + + def fetch_job(self, pk): + queue = self._get_queue() + job = queue.fetch_job(pk) + if job == None or not job.meta.get("lambda"): + raise ValidationError("{} lambda job is not found".format(pk), + code=status.HTTP_404_NOT_FOUND) + + return LambdaJob(job) + + +class LambdaJob: + def __init__(self, job): + self.job = job + + def to_dict(self): + lambda_func = self.job.kwargs.get("function") + return { + "id": self.job.id, + "function": { + "id": lambda_func.id if lambda_func else None, + "threshold": self.job.kwargs.get("threshold"), + "task": self.job.kwargs.get("task") + }, + "status": self.job.get_status(), + "progress": self.job.meta.get('progress', 0), + "enqueued": self.job.enqueued_at, + "started": self.job.started_at, + "ended": self.job.ended_at, + "exc_info": self.job.exc_info + } + + def get_task(self): + return self.job.kwargs.get("task") + + def get_status(self): + return self.job.get_status() + + @property + def is_finished(self): + return self.get_status() == rq.job.JobStatus.FINISHED + + @property + def is_queued(self): + return self.get_status() == rq.job.JobStatus.QUEUED + + @property + def is_failed(self): + return self.get_status() == rq.job.JobStatus.FAILED + + @property + def is_started(self): + return self.get_status() == rq.job.JobStatus.STARTED + + @property + def is_deferred(self): + return self.get_status() == rq.job.JobStatus.DEFERRED + + @property + def is_scheduled(self): + return self.get_status() == rq.job.JobStatus.SCHEDULED + + def delete(self): + self.job.delete() + + @staticmethod + def _call_detector(function, db_task, labels, quality, threshold, mapping): + class Results: + def __init__(self, task_id): + self.task_id = task_id + self.reset() + + def append_shape(self, shape): + self.data["shapes"].append(shape) + + def submit(self): + if not self.is_empty(): + serializer = LabeledDataSerializer(data=self.data) + if serializer.is_valid(raise_exception=True): + dm.task.patch_task_data(self.task_id, serializer.data, "create") + self.reset() + + def is_empty(self): + return not (self.data["tags"] or self.data["shapes"] or self.data["tracks"]) + + def reset(self): + # TODO: need to make "tags" and "tracks" are optional + # FIXME: need to provide the correct version here + self.data = {"version": 0, "tags": [], "shapes": [], "tracks": []} + + results = Results(db_task.id) + + for frame in range(db_task.data.size): + annotations = function.invoke(db_task, data={ + "frame": frame, "quality": quality, "mapping": mapping, + "threshold": threshold}) + progress = (frame + 1) / db_task.data.size + if not LambdaJob._update_progress(progress): + break + + for anno in annotations: + label_id = labels.get(anno["label"]) + if label_id is not None: + results.append_shape({ + "frame": frame, + "label_id": label_id, + "type": anno["type"], + "occluded": False, + "points": anno["points"], + "z_order": 0, + "group": None, + "attributes": [], + "source": "auto" + }) + + # Accumulate data during 100 frames before sumbitting results. + # It is optimization to make fewer calls to our server. Also + # it isn't possible to keep all results in memory. + if frame % 100 == 0: + results.submit() + + results.submit() + + @staticmethod + # progress is in [0, 1] range + def _update_progress(progress): + job = rq.get_current_job() + # If the job has been deleted, get_status will return None. Thus it will + # exist the loop. + job.meta["progress"] = int(progress * 100) + job.save_meta() + + return job.get_status() + + + @staticmethod + def _call_reid(function, db_task, quality, threshold, max_distance): + data = dm.task.get_task_data(db_task.id) + boxes_by_frame = [[] for _ in range(db_task.data.size)] + shapes_without_boxes = [] + for shape in data["shapes"]: + if shape["type"] == str(ShapeType.RECTANGLE): + boxes_by_frame[shape["frame"]].append(shape) + else: + shapes_without_boxes.append(shape) + + paths = {} + for frame in range(db_task.data.size - 1): + boxes0 = boxes_by_frame[frame] + for box in boxes0: + if "path_id" not in box: + path_id = len(paths) + paths[path_id] = [box] + box["path_id"] = path_id + + boxes1 = boxes_by_frame[frame + 1] + if boxes0 and boxes1: + matching = function.invoke(db_task, data={ + "frame0": frame, "frame1": frame + 1, "quality": quality, + "boxes0": boxes0, "boxes1": boxes1, "threshold": threshold, + "max_distance": max_distance}) + + for idx0, idx1 in enumerate(matching): + if idx1 >= 0: + path_id = boxes0[idx0]["path_id"] + boxes1[idx1]["path_id"] = path_id + paths[path_id].append(boxes1[idx1]) + + progress = (frame + 2) / db_task.data.size + if not LambdaJob._update_progress(progress): + break + + + for box in boxes_by_frame[db_task.data.size - 1]: + if "path_id" not in box: + path_id = len(paths) + paths[path_id] = [box] + box["path_id"] = path_id + + tracks = [] + for path_id in paths: + box0 = paths[path_id][0] + tracks.append({ + "label_id": box0["label_id"], + "group": None, + "attributes": [], + "frame": box0["frame"], + "shapes": paths[path_id], + "source": str(SourceType.AUTO) + }) + + for box in tracks[-1]["shapes"]: + box.pop("id", None) + box.pop("path_id") + box.pop("group") + box.pop("label_id") + box.pop("source") + box["outside"] = False + box["attributes"] = [] + + for track in tracks: + if track["shapes"][-1]["frame"] != db_task.data.size - 1: + box = track["shapes"][-1].copy() + box["outside"] = True + box["frame"] += 1 + track["shapes"].append(box) + + if tracks: + data["shapes"] = shapes_without_boxes + data["tracks"].extend(tracks) + + serializer = LabeledDataSerializer(data=data) + if serializer.is_valid(raise_exception=True): + dm.task.put_task_data(db_task.id, serializer.data) + + @staticmethod + def __call__(function, task, quality, cleanup, **kwargs): + # TODO: need logging + db_task = TaskModel.objects.get(pk=task) + if cleanup: + dm.task.delete_task_data(db_task.id) + db_labels = db_task.label_set.prefetch_related("attributespec_set").all() + labels = {db_label.name:db_label.id for db_label in db_labels} + + if function.kind == LambdaType.DETECTOR: + LambdaJob._call_detector(function, db_task, labels, quality, + kwargs.get("threshold"), kwargs.get("mapping")) + elif function.kind == LambdaType.REID: + LambdaJob._call_reid(function, db_task, quality, + kwargs.get("threshold"), kwargs.get("max_distance")) + + +def return_response(success_code=status.HTTP_200_OK): + def wrap_response(func): + @wraps(func) + def func_wrapper(*args, **kwargs): + data = None + status_code = success_code + try: + data = func(*args, **kwargs) + except requests.ConnectionError as err: + status_code = status.HTTP_503_SERVICE_UNAVAILABLE + data = str(err) + except requests.HTTPError as err: + status_code = err.response.status_code + data = str(err) + except requests.Timeout as err: + status_code = status.HTTP_504_GATEWAY_TIMEOUT + data = str(err) + except requests.RequestException as err: + status_code = status.HTTP_500_INTERNAL_SERVER_ERROR + data = str(err) + except ValidationError as err: + status_code = err.code + data = err.message + + return Response(data=data, status=status_code) + + return func_wrapper + return wrap_response + +class FunctionViewSet(viewsets.ViewSet): + lookup_value_regex = '[a-zA-Z0-9_.-]+' + lookup_field = 'func_id' + + def get_permissions(self): + http_method = self.request.method + permissions = [IsAuthenticated] + + if http_method in ["POST"]: + permissions.append(auth.TaskAccessPermission) + + return [perm() for perm in permissions] + + @return_response() + def list(self, request): + gateway = LambdaGateway() + return [f.to_dict() for f in gateway.list()] + + @return_response() + def retrieve(self, request, func_id): + gateway = LambdaGateway() + return gateway.get(func_id).to_dict() + + @return_response() + def call(self, request, func_id): + try: + task_id = request.data['task'] + db_task = TaskModel.objects.get(pk=task_id) + # Check that the user has enough permissions to read + # data from the task. + self.check_object_permissions(self.request, db_task) + except (KeyError, ObjectDoesNotExist) as err: + raise ValidationError( + '`{}` lambda function was run '.format(func_id) + + 'with wrong arguments ({})'.format(str(err)), + code=status.HTTP_400_BAD_REQUEST) + + gateway = LambdaGateway() + lambda_func = gateway.get(func_id) + + return lambda_func.invoke(db_task, request.data) + +class RequestViewSet(viewsets.ViewSet): + def get_permissions(self): + http_method = self.request.method + permissions = [IsAuthenticated] + + if http_method in ["POST", "DELETE"]: + permissions.append(auth.TaskChangePermission) + + return [perm() for perm in permissions] + + @return_response() + def list(self, request): + queue = LambdaQueue() + return [job.to_dict() for job in queue.get_jobs()] + + @return_response() + def create(self, request): + try: + function = request.data['function'] + threshold = request.data.get('threshold') + task = request.data['task'] + quality = request.data.get("quality") + cleanup = request.data.get('cleanup', False) + mapping = request.data.get('mapping') + + db_task = TaskModel.objects.get(pk=task) + # Check that the user has enough permissions to modify + # the task. + self.check_object_permissions(self.request, db_task) + except (KeyError, ObjectDoesNotExist) as err: + raise ValidationError( + '`{}` lambda function was run '.format(function) + + 'with wrong arguments ({})'.format(str(err)), + code=status.HTTP_400_BAD_REQUEST) + + gateway = LambdaGateway() + queue = LambdaQueue() + lambda_func = gateway.get(function) + job = queue.enqueue(lambda_func, threshold, task, quality, + mapping, cleanup) + + return job.to_dict() + + @return_response() + def retrieve(self, request, pk): + queue = LambdaQueue() + job = queue.fetch_job(pk) + + return job.to_dict() + + @return_response(status.HTTP_204_NO_CONTENT) + def delete(self, request, pk): + queue = LambdaQueue() + job = queue.fetch_job(pk) + job.delete() diff --git a/cvat/apps/reid/README.md b/cvat/apps/reid/README.md deleted file mode 100644 index 8cf29c50..00000000 --- a/cvat/apps/reid/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Re-Identification Application - -## About the application - -The ReID application uses deep learning model to perform an automatic bbox merging between neighbor frames. -You can use "Merge" and "Split" functionality to edit automatically generated annotation. - -## Installation - -This application will be installed automatically with the [OpenVINO](https://github.com/opencv/cvat/blob/develop/components/openvino/README.md) component. - -## Running - -For starting the ReID merge process: - -- Open an annotation job -- Open the menu -- Click the "Run ReID Merge" button -- Click the "Submit" button. Also here you can experiment with values of model threshold or maximum distance. - - Model threshold is maximum cosine distance between objects embeddings. - - Maximum distance defines a maximum radius that an object can diverge between neightbor frames. -- The process will be run. You can cancel it in the menu. diff --git a/cvat/apps/reid/__init__.py b/cvat/apps/reid/__init__.py deleted file mode 100644 index 4a9759cc..00000000 --- a/cvat/apps/reid/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from cvat.settings.base import JS_3RDPARTY - -default_app_config = 'cvat.apps.reid.apps.ReidConfig' - -JS_3RDPARTY['engine'] = JS_3RDPARTY.get('engine', []) + ['reid/js/enginePlugin.js'] diff --git a/cvat/apps/reid/apps.py b/cvat/apps/reid/apps.py deleted file mode 100644 index f6aa66e1..00000000 --- a/cvat/apps/reid/apps.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.apps import AppConfig - -class ReidConfig(AppConfig): - name = 'cvat.apps.reid' diff --git a/cvat/apps/reid/reid.py b/cvat/apps/reid/reid.py deleted file mode 100644 index bf79bac9..00000000 --- a/cvat/apps/reid/reid.py +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -import os -import rq -import cv2 -import math -import numpy -import itertools - -from openvino.inference_engine import IENetwork, IEPlugin -from scipy.optimize import linear_sum_assignment -from scipy.spatial.distance import euclidean, cosine - -from cvat.apps.engine.models import Job -from cvat.apps.engine.frame_provider import FrameProvider - - -class ReID: - __threshold = None - __max_distance = None - __frame_urls = None - __frame_boxes = None - __stop_frame = None - __plugin = None - __executable_network = None - __input_blob_name = None - __output_blob_name = None - __input_height = None - __input_width = None - - - def __init__(self, jid, data): - self.__threshold = data["threshold"] - self.__max_distance = data["maxDistance"] - - self.__frame_boxes = {} - - db_job = Job.objects.select_related('segment__task').get(pk = jid) - db_segment = db_job.segment - db_task = db_segment.task - self.__frame_iter = itertools.islice( - FrameProvider(db_task.data).get_frames(FrameProvider.Quality.ORIGINAL), - db_segment.start_frame, - db_segment.stop_frame + 1, - ) - - self.__stop_frame = db_segment.stop_frame - for frame in range(db_segment.start_frame, db_segment.stop_frame + 1): - self.__frame_boxes[frame] = [box for box in data["boxes"] if box["frame"] == frame] - - IE_PLUGINS_PATH = os.getenv('IE_PLUGINS_PATH', None) - REID_MODEL_DIR = os.getenv('REID_MODEL_DIR', None) - - if not IE_PLUGINS_PATH: - raise Exception("Environment variable 'IE_PLUGINS_PATH' isn't defined") - if not REID_MODEL_DIR: - raise Exception("Environment variable 'REID_MODEL_DIR' isn't defined") - - REID_XML = os.path.join(REID_MODEL_DIR, "reid.xml") - REID_BIN = os.path.join(REID_MODEL_DIR, "reid.bin") - - self.__plugin = IEPlugin(device="CPU", plugin_dirs=[IE_PLUGINS_PATH]) - network = IENetwork.from_ir(model=REID_XML, weights=REID_BIN) - self.__input_blob_name = next(iter(network.inputs)) - self.__output_blob_name = next(iter(network.outputs)) - self.__input_height, self.__input_width = network.inputs[self.__input_blob_name].shape[-2:] - self.__executable_network = self.__plugin.load(network=network) - del network - - - def __del__(self): - if self.__executable_network: - del self.__executable_network - self.__executable_network = None - - if self.__plugin: - del self.__plugin - self.__plugin = None - - - def __boxes_are_compatible(self, cur_box, next_box): - cur_c_x = (cur_box["points"][0] + cur_box["points"][2]) / 2 - cur_c_y = (cur_box["points"][1] + cur_box["points"][3]) / 2 - next_c_x = (next_box["points"][0] + next_box["points"][2]) / 2 - next_c_y = (next_box["points"][1] + next_box["points"][3]) / 2 - compatible_distance = euclidean([cur_c_x, cur_c_y], [next_c_x, next_c_y]) <= self.__max_distance - compatible_label = cur_box["label_id"] == next_box["label_id"] - return compatible_distance and compatible_label and "path_id" not in next_box - - - def __compute_difference(self, image_1, image_2): - image_1 = cv2.resize(image_1, (self.__input_width, self.__input_height)).transpose((2,0,1)) - image_2 = cv2.resize(image_2, (self.__input_width, self.__input_height)).transpose((2,0,1)) - - input_1 = { - self.__input_blob_name: image_1[numpy.newaxis, ...] - } - - input_2 = { - self.__input_blob_name: image_2[numpy.newaxis, ...] - } - - embedding_1 = self.__executable_network.infer(inputs = input_1)[self.__output_blob_name] - embedding_2 = self.__executable_network.infer(inputs = input_2)[self.__output_blob_name] - - embedding_1 = embedding_1.reshape(embedding_1.size) - embedding_2 = embedding_2.reshape(embedding_2.size) - - return cosine(embedding_1, embedding_2) - - - def __compute_difference_matrix(self, cur_boxes, next_boxes, cur_image, next_image): - def _int(number, upper): - return math.floor(numpy.clip(number, 0, upper - 1)) - - default_mat_value = 1000.0 - - matrix = numpy.full([len(cur_boxes), len(next_boxes)], default_mat_value, dtype=float) - for row, cur_box in enumerate(cur_boxes): - cur_width = cur_image.shape[1] - cur_height = cur_image.shape[0] - cur_xtl, cur_xbr, cur_ytl, cur_ybr = ( - _int(cur_box["points"][0], cur_width), _int(cur_box["points"][2], cur_width), - _int(cur_box["points"][1], cur_height), _int(cur_box["points"][3], cur_height) - ) - - for col, next_box in enumerate(next_boxes): - next_box = next_boxes[col] - next_width = next_image.shape[1] - next_height = next_image.shape[0] - next_xtl, next_xbr, next_ytl, next_ybr = ( - _int(next_box["points"][0], next_width), _int(next_box["points"][2], next_width), - _int(next_box["points"][1], next_height), _int(next_box["points"][3], next_height) - ) - - if not self.__boxes_are_compatible(cur_box, next_box): - continue - - crop_1 = cur_image[cur_ytl:cur_ybr, cur_xtl:cur_xbr] - crop_2 = next_image[next_ytl:next_ybr, next_xtl:next_xbr] - matrix[row][col] = self.__compute_difference(crop_1, crop_2) - - return matrix - - - def __apply_matching(self): - frames = sorted(list(self.__frame_boxes.keys())) - job = rq.get_current_job() - box_tracks = {} - - next_image = cv2.imdecode(numpy.fromstring((next(self.__frame_iter)[0]).read(), numpy.uint8), cv2.IMREAD_COLOR) - for idx, (cur_frame, next_frame) in enumerate(list(zip(frames[:-1], frames[1:]))): - job.refresh() - if "cancel" in job.meta: - return None - - job.meta["progress"] = idx * 100.0 / len(frames) - job.save_meta() - - cur_boxes = self.__frame_boxes[cur_frame] - next_boxes = self.__frame_boxes[next_frame] - - for box in cur_boxes: - if "path_id" not in box: - path_id = len(box_tracks) - box_tracks[path_id] = [box] - box["path_id"] = path_id - - if not (len(cur_boxes) and len(next_boxes)): - continue - - cur_image = next_image - next_image = cv2.imdecode(numpy.fromstring((next(self.__frame_iter)[0]).read(), numpy.uint8), cv2.IMREAD_COLOR) - difference_matrix = self.__compute_difference_matrix(cur_boxes, next_boxes, cur_image, next_image) - cur_idxs, next_idxs = linear_sum_assignment(difference_matrix) - for idx, cur_idx in enumerate(cur_idxs): - if (difference_matrix[cur_idx][next_idxs[idx]]) <= self.__threshold: - cur_box = cur_boxes[cur_idx] - next_box = next_boxes[next_idxs[idx]] - next_box["path_id"] = cur_box["path_id"] - box_tracks[cur_box["path_id"]].append(next_box) - - for box in self.__frame_boxes[frames[-1]]: - if "path_id" not in box: - path_id = len(box_tracks) - box["path_id"] = path_id - box_tracks[path_id] = [box] - - return box_tracks - - - def run(self): - box_tracks = self.__apply_matching() - output = [] - - # ReID process has been canceled - if box_tracks is None: - return - - for path_id in box_tracks: - output.append({ - "label_id": box_tracks[path_id][0]["label_id"], - "group": None, - "attributes": [], - "frame": box_tracks[path_id][0]["frame"], - "shapes": box_tracks[path_id] - }) - - for box in output[-1]["shapes"]: - if "id" in box: - del box["id"] - del box["path_id"] - del box["group"] - del box["label_id"] - box["outside"] = False - box["attributes"] = [] - - for path in output: - if path["shapes"][-1]["frame"] != self.__stop_frame: - copy = path["shapes"][-1].copy() - copy["outside"] = True - copy["frame"] += 1 - path["shapes"].append(copy) - - return output diff --git a/cvat/apps/reid/static/reid/js/enginePlugin.js b/cvat/apps/reid/static/reid/js/enginePlugin.js deleted file mode 100644 index 28fabb82..00000000 --- a/cvat/apps/reid/static/reid/js/enginePlugin.js +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2018 Intel Corporation - * - * SPDX-License-Identifier: MIT - */ - -/* global showMessage userConfirm */ - - -document.addEventListener('DOMContentLoaded', () => { - async function run(overlay, cancelButton, thresholdInput, distanceInput) { - const collection = window.cvat.data.get(); - const data = { - threshold: +thresholdInput.prop('value'), - maxDistance: +distanceInput.prop('value'), - boxes: collection.shapes.filter(el => el.type === 'rectangle'), - }; - - overlay.removeClass('hidden'); - cancelButton.prop('disabled', true); - - async function checkCallback() { - let jobData = null; - try { - jobData = await $.get(`/reid/check/${window.cvat.job.id}`); - } catch (errorData) { - overlay.addClass('hidden'); - const message = `Can not check ReID merge. Code: ${errorData.status}. ` - + `Message: ${errorData.responseText || errorData.statusText}`; - showMessage(message); - } - - if (jobData.progress) { - cancelButton.text(`Cancel ReID Merge (${jobData.progress.toString().slice(0, 4)}%)`); - } - - if (['queued', 'started'].includes(jobData.status)) { - setTimeout(checkCallback, 1000); - } else { - overlay.addClass('hidden'); - - if (jobData.status === 'finished') { - if (jobData.result) { - const result = JSON.parse(jobData.result); - collection.shapes = collection.shapes - .filter(el => el.type !== 'rectangle'); - collection.tracks = collection.tracks - .concat(result); - - window.cvat.data.clear(); - window.cvat.data.set(collection); - - showMessage('ReID merge has done.'); - } else { - showMessage('ReID merge been canceled.'); - } - } else if (jobData.status === 'failed') { - const message = `ReID merge has fallen. Error: '${jobData.stderr}'`; - showMessage(message); - } else { - let message = `Check request returned "${jobData.status}" status.`; - if (jobData.stderr) { - message += ` Error: ${jobData.stderr}`; - } - showMessage(message); - } - } - } - - try { - await $.ajax({ - url: `/reid/start/job/${window.cvat.job.id}`, - type: 'POST', - data: JSON.stringify(data), - contentType: 'application/json', - }); - - setTimeout(checkCallback, 1000); - } catch (errorData) { - overlay.addClass('hidden'); - const message = `Can not start ReID merge. Code: ${errorData.status}. ` - + `Message: ${errorData.responseText || errorData.statusText}`; - showMessage(message); - } finally { - cancelButton.prop('disabled', false); - } - } - - async function cancel(overlay, cancelButton) { - cancelButton.prop('disabled', true); - try { - await $.get(`/reid/cancel/${window.cvat.job.id}`); - overlay.addClass('hidden'); - cancelButton.text('Cancel ReID Merge (0%)'); - } catch (errorData) { - const message = `Can not cancel ReID process. Code: ${errorData.status}. Message: ${errorData.responseText || errorData.statusText}`; - showMessage(message); - } finally { - cancelButton.prop('disabled', false); - } - } - - const buttonsUI = $('#engineMenuButtons'); - const reidWindowId = 'reidSubmitWindow'; - const reidThresholdValueId = 'reidThresholdValue'; - const reidDistanceValueId = 'reidDistanceValue'; - const reidCancelMergeId = 'reidCancelMerge'; - const reidSubmitMergeId = 'reidSubmitMerge'; - const reidCancelButtonId = 'reidCancelReID'; - const reidOverlay = 'reidOverlay'; - - $('').on('click', () => { - $('#annotationMenu').addClass('hidden'); - $(`#${reidWindowId}`).removeClass('hidden'); - }).addClass('menuButton semiBold h2').prependTo(buttonsUI); - - $(` - - `).appendTo('body'); - - $(` - - `).appendTo('body'); - - $(`#${reidCancelMergeId}`).on('click', () => { - $(`#${reidWindowId}`).addClass('hidden'); - }); - - $(`#${reidCancelButtonId}`).on('click', () => { - userConfirm('ReID process will be canceld. Are you sure?', () => { - cancel($(`#${reidOverlay}`), $(`#${reidCancelButtonId}`)); - }); - }); - - $(`#${reidSubmitMergeId}`).on('click', () => { - $(`#${reidWindowId}`).addClass('hidden'); - run($(`#${reidOverlay}`), $(`#${reidCancelButtonId}`), - $(`#${reidThresholdValueId}`), $(`#${reidDistanceValueId}`)) - .catch((error) => { - setTimeout(() => { - throw error; - }); - }); - }); -}); diff --git a/cvat/apps/reid/urls.py b/cvat/apps/reid/urls.py deleted file mode 100644 index 431b1119..00000000 --- a/cvat/apps/reid/urls.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (C) 2018-2020 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.urls import path -from . import views - -urlpatterns = [ - path('start/job/', views.start), - path('cancel/', views.cancel), - path('check/', views.check), - path('enabled', views.enabled), -] diff --git a/cvat/apps/reid/views.py b/cvat/apps/reid/views.py deleted file mode 100644 index 100151ee..00000000 --- a/cvat/apps/reid/views.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.http import HttpResponse, HttpResponseBadRequest, JsonResponse -from cvat.apps.authentication.decorators import login_required -from rules.contrib.views import permission_required, objectgetter - -from cvat.apps.engine.models import Job -from cvat.apps.reid.reid import ReID - -import django_rq -import json -import rq - - -def _create_thread(jid, data): - job = rq.get_current_job() - reid_obj = ReID(jid, data) - job.meta["result"] = json.dumps(reid_obj.run()) - job.save_meta() - - -@login_required -@permission_required(perm=["engine.job.change"], - fn=objectgetter(Job, 'jid'), raise_exception=True) -def start(request, jid): - try: - data = json.loads(request.body.decode('utf-8')) - queue = django_rq.get_queue("low") - job_id = "reid.create.{}".format(jid) - job = queue.fetch_job(job_id) - if job is not None and (job.is_started or job.is_queued): - raise Exception('ReID process has been already started') - queue.enqueue_call(func=_create_thread, args=(jid, data), job_id=job_id, timeout=7200) - job = queue.fetch_job(job_id) - job.meta = {} - job.save_meta() - except Exception as e: - return HttpResponseBadRequest(str(e)) - - return HttpResponse() - - -@login_required -@permission_required(perm=["engine.job.change"], - fn=objectgetter(Job, 'jid'), raise_exception=True) -def check(request, jid): - try: - queue = django_rq.get_queue("low") - rq_id = "reid.create.{}".format(jid) - job = queue.fetch_job(rq_id) - if job is not None and "cancel" in job.meta: - return JsonResponse({"status": "finished"}) - data = {} - if job is None: - data["status"] = "unknown" - elif job.is_queued: - data["status"] = "queued" - elif job.is_started: - data["status"] = "started" - if "progress" in job.meta: - data["progress"] = job.meta["progress"] - elif job.is_finished: - data["status"] = "finished" - data["result"] = job.meta["result"] - job.delete() - else: - data["status"] = "failed" - data["stderr"] = job.exc_info - job.delete() - - except Exception as ex: - data["stderr"] = str(ex) - data["status"] = "unknown" - - return JsonResponse(data) - - -@login_required -@permission_required(perm=["engine.job.change"], - fn=objectgetter(Job, 'jid'), raise_exception=True) -def cancel(request, jid): - try: - queue = django_rq.get_queue("low") - rq_id = "reid.create.{}".format(jid) - job = queue.fetch_job(rq_id) - if job is None or job.is_finished or job.is_failed: - raise Exception("Task is not being annotated currently") - elif "cancel" not in job.meta: - job.meta["cancel"] = True - job.save_meta() - except Exception as e: - return HttpResponseBadRequest(str(e)) - - return HttpResponse() - -def enabled(request): - return HttpResponse() diff --git a/cvat/apps/tf_annotation/__init__.py b/cvat/apps/tf_annotation/__init__.py deleted file mode 100644 index a0fca4cb..00000000 --- a/cvat/apps/tf_annotation/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ - -# Copyright (C) 2018-2019 Intel Corporation -# -# SPDX-License-Identifier: MIT diff --git a/cvat/apps/tf_annotation/admin.py b/cvat/apps/tf_annotation/admin.py deleted file mode 100644 index af8dfc47..00000000 --- a/cvat/apps/tf_annotation/admin.py +++ /dev/null @@ -1,9 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.contrib import admin - -# Register your models here. - diff --git a/cvat/apps/tf_annotation/apps.py b/cvat/apps/tf_annotation/apps.py deleted file mode 100644 index d07a37b1..00000000 --- a/cvat/apps/tf_annotation/apps.py +++ /dev/null @@ -1,11 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.apps import AppConfig - - -class TFAnnotationConfig(AppConfig): - name = 'tf_annotation' - diff --git a/cvat/apps/tf_annotation/migrations/__init__.py b/cvat/apps/tf_annotation/migrations/__init__.py deleted file mode 100644 index d8e62e54..00000000 --- a/cvat/apps/tf_annotation/migrations/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - diff --git a/cvat/apps/tf_annotation/models.py b/cvat/apps/tf_annotation/models.py deleted file mode 100644 index cdf3b082..00000000 --- a/cvat/apps/tf_annotation/models.py +++ /dev/null @@ -1,9 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.db import models - -# Create your models here. - diff --git a/cvat/apps/tf_annotation/tests.py b/cvat/apps/tf_annotation/tests.py deleted file mode 100644 index 53bc3b7a..00000000 --- a/cvat/apps/tf_annotation/tests.py +++ /dev/null @@ -1,9 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.test import TestCase - -# Create your tests here. - diff --git a/cvat/apps/tf_annotation/urls.py b/cvat/apps/tf_annotation/urls.py deleted file mode 100644 index f84019be..00000000 --- a/cvat/apps/tf_annotation/urls.py +++ /dev/null @@ -1,14 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.urls import path -from . import views - -urlpatterns = [ - path('create/task/', views.create), - path('check/task/', views.check), - path('cancel/task/', views.cancel), - path('meta/get', views.get_meta_info), -] diff --git a/cvat/apps/tf_annotation/views.py b/cvat/apps/tf_annotation/views.py deleted file mode 100644 index e112860e..00000000 --- a/cvat/apps/tf_annotation/views.py +++ /dev/null @@ -1,347 +0,0 @@ - -# Copyright (C) 2018-2020 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.http import HttpResponse, JsonResponse, HttpResponseBadRequest -from rest_framework.decorators import api_view -from rules.contrib.views import permission_required, objectgetter -from cvat.apps.authentication.decorators import login_required -from cvat.apps.dataset_manager.task import put_task_data -from cvat.apps.engine.models import Task as TaskModel -from cvat.apps.engine.serializers import LabeledDataSerializer -from cvat.apps.engine.frame_provider import FrameProvider - -import django_rq -import os -import rq - -import tensorflow as tf -import numpy as np - -from PIL import Image -from cvat.apps.engine.log import slogger - - -def load_image_into_numpy(image): - (im_width, im_height) = image.size - return np.array(image.getdata()).reshape((im_height, im_width, 3)).astype(np.uint8) - - -def run_inference_engine_annotation(image_list, labels_mapping, treshold): - from cvat.apps.auto_annotation.inference_engine import make_plugin_or_core, make_network - - def _normalize_box(box, w, h, dw, dh): - xmin = min(int(box[0] * dw * w), w) - ymin = min(int(box[1] * dh * h), h) - xmax = min(int(box[2] * dw * w), w) - ymax = min(int(box[3] * dh * h), h) - return xmin, ymin, xmax, ymax - - result = {} - MODEL_PATH = os.environ.get('TF_ANNOTATION_MODEL_PATH') - if MODEL_PATH is None: - raise OSError('Model path env not found in the system.') - - core_or_plugin = make_plugin_or_core() - network = make_network('{}.xml'.format(MODEL_PATH), '{}.bin'.format(MODEL_PATH)) - input_blob_name = next(iter(network.inputs)) - output_blob_name = next(iter(network.outputs)) - if getattr(core_or_plugin, 'load_network', False): - executable_network = core_or_plugin.load_network(network, 'CPU') - else: - executable_network = core_or_plugin.load(network=network) - job = rq.get_current_job() - - del network - - try: - for image_num, im_name in enumerate(image_list): - - job.refresh() - if 'cancel' in job.meta: - del job.meta['cancel'] - job.save() - return None - job.meta['progress'] = image_num * 100 / len(image_list) - job.save_meta() - - image = Image.open(im_name) - width, height = image.size - image.thumbnail((600, 600), Image.ANTIALIAS) - dwidth, dheight = 600 / image.size[0], 600 / image.size[1] - image = image.crop((0, 0, 600, 600)) - image_np = load_image_into_numpy(image) - image_np = np.transpose(image_np, (2, 0, 1)) - prediction = executable_network.infer(inputs={input_blob_name: image_np[np.newaxis, ...]})[output_blob_name][0][0] - for obj in prediction: - obj_class = int(obj[1]) - obj_value = obj[2] - if obj_class and obj_class in labels_mapping and obj_value >= treshold: - label = labels_mapping[obj_class] - if label not in result: - result[label] = [] - xmin, ymin, xmax, ymax = _normalize_box(obj[3:7], width, height, dwidth, dheight) - result[label].append([image_num, xmin, ymin, xmax, ymax]) - finally: - del executable_network - del plugin - - return result - - -def run_tensorflow_annotation(frame_provider, labels_mapping, treshold): - def _normalize_box(box, w, h): - xmin = int(box[1] * w) - ymin = int(box[0] * h) - xmax = int(box[3] * w) - ymax = int(box[2] * h) - return xmin, ymin, xmax, ymax - - result = {} - model_path = os.environ.get('TF_ANNOTATION_MODEL_PATH') - if model_path is None: - raise OSError('Model path env not found in the system.') - job = rq.get_current_job() - - detection_graph = tf.Graph() - with detection_graph.as_default(): - od_graph_def = tf.GraphDef() - with tf.gfile.GFile(model_path + '.pb', 'rb') as fid: - serialized_graph = fid.read() - od_graph_def.ParseFromString(serialized_graph) - tf.import_graph_def(od_graph_def, name='') - - try: - config = tf.ConfigProto() - config.gpu_options.allow_growth=True - sess = tf.Session(graph=detection_graph, config=config) - frames = frame_provider.get_frames(frame_provider.Quality.ORIGINAL) - for image_num, (image, _) in enumerate(frames): - - job.refresh() - if 'cancel' in job.meta: - del job.meta['cancel'] - job.save() - return None - job.meta['progress'] = image_num * 100 / len(frame_provider) - job.save_meta() - - image = Image.open(image) - width, height = image.size - if width > 1920 or height > 1080: - image = image.resize((width // 2, height // 2), Image.ANTIALIAS) - image_np = load_image_into_numpy(image) - image_np_expanded = np.expand_dims(image_np, axis=0) - - image_tensor = detection_graph.get_tensor_by_name('image_tensor:0') - boxes = detection_graph.get_tensor_by_name('detection_boxes:0') - scores = detection_graph.get_tensor_by_name('detection_scores:0') - classes = detection_graph.get_tensor_by_name('detection_classes:0') - num_detections = detection_graph.get_tensor_by_name('num_detections:0') - (boxes, scores, classes, num_detections) = sess.run([boxes, scores, classes, num_detections], feed_dict={image_tensor: image_np_expanded}) - - for i in range(len(classes[0])): - if classes[0][i] in labels_mapping.keys(): - if scores[0][i] >= treshold: - xmin, ymin, xmax, ymax = _normalize_box(boxes[0][i], width, height) - label = labels_mapping[classes[0][i]] - if label not in result: - result[label] = [] - result[label].append([image_num, xmin, ymin, xmax, ymax]) - finally: - sess.close() - del sess - return result - -def convert_to_cvat_format(data): - result = { - "tracks": [], - "shapes": [], - "tags": [], - "version": 0, - } - - for label in data: - boxes = data[label] - for box in boxes: - result['shapes'].append({ - "type": "rectangle", - "label_id": label, - "frame": box[0], - "points": [box[1], box[2], box[3], box[4]], - "z_order": 0, - "group": None, - "occluded": False, - "attributes": [], - "source": "auto", - }) - - return result - -def create_thread(tid, labels_mapping, user): - try: - TRESHOLD = 0.5 - # Init rq job - job = rq.get_current_job() - job.meta['progress'] = 0 - job.save_meta() - # Get job indexes and segment length - db_task = TaskModel.objects.get(pk=tid) - # Get image list - image_list = FrameProvider(db_task.data) - - # Run auto annotation by tf - result = None - slogger.glob.info("tf annotation with tensorflow framework for task {}".format(tid)) - result = run_tensorflow_annotation(image_list, labels_mapping, TRESHOLD) - - if result is None: - slogger.glob.info('tf annotation for task {} canceled by user'.format(tid)) - return - - # Modify data format and save - result = convert_to_cvat_format(result) - serializer = LabeledDataSerializer(data = result) - if serializer.is_valid(raise_exception=True): - put_task_data(tid, result) - slogger.glob.info('tf annotation for task {} done'.format(tid)) - except Exception as ex: - try: - slogger.task[tid].exception('exception was occured during tf annotation of the task', exc_info=True) - except: - slogger.glob.exception('exception was occured during tf annotation of the task {}'.format(tid), exc_info=True) - raise ex - -@api_view(['POST']) -@login_required -def get_meta_info(request): - try: - queue = django_rq.get_queue('low') - tids = request.data - result = {} - for tid in tids: - job = queue.fetch_job('tf_annotation.create/{}'.format(tid)) - if job is not None: - result[tid] = { - "active": job.is_queued or job.is_started, - "success": not job.is_failed - } - - return JsonResponse(result) - except Exception as ex: - slogger.glob.exception('exception was occured during tf meta request', exc_info=True) - return HttpResponseBadRequest(str(ex)) - - -@login_required -@permission_required(perm=['engine.task.change'], - fn=objectgetter(TaskModel, 'tid'), raise_exception=True) -def create(request, tid): - slogger.glob.info('tf annotation create request for task {}'.format(tid)) - try: - db_task = TaskModel.objects.get(pk=tid) - queue = django_rq.get_queue('low') - job = queue.fetch_job('tf_annotation.create/{}'.format(tid)) - if job is not None and (job.is_started or job.is_queued): - raise Exception("The process is already running") - - db_labels = db_task.label_set.prefetch_related('attributespec_set').all() - db_labels = {db_label.id:db_label.name for db_label in db_labels} - - tf_annotation_labels = { - "person": 1, "bicycle": 2, "car": 3, "motorcycle": 4, "airplane": 5, - "bus": 6, "train": 7, "truck": 8, "boat": 9, "traffic_light": 10, - "fire_hydrant": 11, "stop_sign": 13, "parking_meter": 14, "bench": 15, - "bird": 16, "cat": 17, "dog": 18, "horse": 19, "sheep": 20, "cow": 21, - "elephant": 22, "bear": 23, "zebra": 24, "giraffe": 25, "backpack": 27, - "umbrella": 28, "handbag": 31, "tie": 32, "suitcase": 33, "frisbee": 34, - "skis": 35, "snowboard": 36, "sports_ball": 37, "kite": 38, "baseball_bat": 39, - "baseball_glove": 40, "skateboard": 41, "surfboard": 42, "tennis_racket": 43, - "bottle": 44, "wine_glass": 46, "cup": 47, "fork": 48, "knife": 49, "spoon": 50, - "bowl": 51, "banana": 52, "apple": 53, "sandwich": 54, "orange": 55, "broccoli": 56, - "carrot": 57, "hot_dog": 58, "pizza": 59, "donut": 60, "cake": 61, "chair": 62, - "couch": 63, "potted_plant": 64, "bed": 65, "dining_table": 67, "toilet": 70, - "tv": 72, "laptop": 73, "mouse": 74, "remote": 75, "keyboard": 76, "cell_phone": 77, - "microwave": 78, "oven": 79, "toaster": 80, "sink": 81, "refrigerator": 83, - "book": 84, "clock": 85, "vase": 86, "scissors": 87, "teddy_bear": 88, "hair_drier": 89, - "toothbrush": 90 - } - - labels_mapping = {} - for key, labels in db_labels.items(): - if labels in tf_annotation_labels.keys(): - labels_mapping[tf_annotation_labels[labels]] = key - - if not len(labels_mapping.values()): - raise Exception('No labels found for tf annotation') - - # Run tf annotation job - queue.enqueue_call(func=create_thread, - args=(tid, labels_mapping, request.user), - job_id='tf_annotation.create/{}'.format(tid), - timeout=604800) # 7 days - - slogger.task[tid].info('tensorflow annotation job enqueued with labels {}'.format(labels_mapping)) - - except Exception as ex: - try: - slogger.task[tid].exception("exception was occured during tensorflow annotation request", exc_info=True) - except: - pass - return HttpResponseBadRequest(str(ex)) - - return HttpResponse() - -@login_required -@permission_required(perm=['engine.task.access'], - fn=objectgetter(TaskModel, 'tid'), raise_exception=True) -def check(request, tid): - try: - queue = django_rq.get_queue('low') - job = queue.fetch_job('tf_annotation.create/{}'.format(tid)) - if job is not None and 'cancel' in job.meta: - return JsonResponse({'status': 'finished'}) - data = {} - if job is None: - data['status'] = 'unknown' - elif job.is_queued: - data['status'] = 'queued' - elif job.is_started: - data['status'] = 'started' - data['progress'] = job.meta['progress'] - elif job.is_finished: - data['status'] = 'finished' - job.delete() - else: - data['status'] = 'failed' - data['stderr'] = job.exc_info - job.delete() - - except Exception: - data['status'] = 'unknown' - - return JsonResponse(data) - - -@login_required -@permission_required(perm=['engine.task.change'], - fn=objectgetter(TaskModel, 'tid'), raise_exception=True) -def cancel(request, tid): - try: - queue = django_rq.get_queue('low') - job = queue.fetch_job('tf_annotation.create/{}'.format(tid)) - if job is None or job.is_finished or job.is_failed: - raise Exception('Task is not being annotated currently') - elif 'cancel' not in job.meta: - job.meta['cancel'] = True - job.save() - - except Exception as ex: - try: - slogger.task[tid].exception("cannot cancel tensorflow annotation for task #{}".format(tid), exc_info=True) - except: - pass - return HttpResponseBadRequest(str(ex)) - - return HttpResponse() diff --git a/cvat/requirements/base.txt b/cvat/requirements/base.txt index b2847cbd..aa6afd90 100644 --- a/cvat/requirements/base.txt +++ b/cvat/requirements/base.txt @@ -4,7 +4,7 @@ django-appconf==1.0.4 django-auth-ldap==2.2.0 django-cacheops==5.0.1 django-compressor==2.4 -django-rq==2.0.0 +django-rq==2.3.2 EasyProcess==0.3 Pillow==7.2.0 numpy==1.18.5 @@ -15,7 +15,7 @@ rcssmin==1.0.6 redis==3.5.3 rjsmin==1.1.0 requests==2.24.0 -rq==1.0.0 +rq==1.4.2 rq-scheduler==0.10.0 scipy==1.4.1 sqlparse==0.3.1 diff --git a/cvat/settings/base.py b/cvat/settings/base.py index 9155f2b3..15fe3264 100644 --- a/cvat/settings/base.py +++ b/cvat/settings/base.py @@ -99,6 +99,7 @@ INSTALLED_APPS = [ 'cvat.apps.engine', 'cvat.apps.git', 'cvat.apps.restrictions', + 'cvat.apps.lambda_manager', 'django_rq', 'compressor', 'cacheops', @@ -160,25 +161,9 @@ REST_AUTH_REGISTER_SERIALIZERS = { 'REGISTER_SERIALIZER': 'cvat.apps.restrictions.serializers.RestrictedRegisterSerializer' } -if 'yes' == os.environ.get('TF_ANNOTATION', 'no'): - INSTALLED_APPS += ['cvat.apps.tf_annotation'] - -if 'yes' == os.environ.get('OPENVINO_TOOLKIT', 'no'): - INSTALLED_APPS += ['cvat.apps.auto_annotation'] - -if 'yes' == os.environ.get('OPENVINO_TOOLKIT', 'no') and os.environ.get('REID_MODEL_DIR', ''): - INSTALLED_APPS += ['cvat.apps.reid'] - -if 'yes' == os.environ.get('WITH_DEXTR', 'no'): - INSTALLED_APPS += ['cvat.apps.dextr_segmentation'] - if os.getenv('DJANGO_LOG_VIEWER_HOST'): INSTALLED_APPS += ['cvat.apps.log_viewer'] -# new feature by Mohammad -if 'yes' == os.environ.get('AUTO_SEGMENTATION', 'no'): - INSTALLED_APPS += ['cvat.apps.auto_segmentation'] - MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', @@ -254,6 +239,13 @@ RQ_QUEUES = { } } +NUCLIO = { + 'SCHEME': 'http', + 'HOST': 'localhost', + 'PORT': 8070, + 'DEFAULT_TIMEOUT': 120 +} + RQ_SHOW_ADMIN_LINK = True RQ_EXCEPTION_HANDLERS = ['cvat.apps.engine.views.rq_handler'] diff --git a/cvat/settings/production.py b/cvat/settings/production.py index ae059bee..d6cea898 100644 --- a/cvat/settings/production.py +++ b/cvat/settings/production.py @@ -10,6 +10,8 @@ INSTALLED_APPS += [ 'mod_wsgi.server', ] +NUCLIO['HOST'] = os.getenv('CVAT_NUCLIO_HOST', 'nuclio') + for key in RQ_QUEUES: RQ_QUEUES[key]['HOST'] = os.getenv('CVAT_REDIS_HOST', 'cvat_redis') diff --git a/cvat/urls.py b/cvat/urls.py index 6ae59f6b..0d652e9b 100644 --- a/cvat/urls.py +++ b/cvat/urls.py @@ -31,27 +31,14 @@ urlpatterns = [ path('documentation/', include('cvat.apps.documentation.urls')), ] -if apps.is_installed('cvat.apps.tf_annotation'): - urlpatterns.append(path('tensorflow/annotation/', include('cvat.apps.tf_annotation.urls'))) - if apps.is_installed('cvat.apps.git'): urlpatterns.append(path('git/repository/', include('cvat.apps.git.urls'))) -if apps.is_installed('cvat.apps.reid'): - urlpatterns.append(path('reid/', include('cvat.apps.reid.urls'))) - -if apps.is_installed('cvat.apps.auto_annotation'): - urlpatterns.append(path('auto_annotation/', include('cvat.apps.auto_annotation.urls'))) - -if apps.is_installed('cvat.apps.dextr_segmentation'): - urlpatterns.append(path('dextr/', include('cvat.apps.dextr_segmentation.urls'))) - if apps.is_installed('cvat.apps.log_viewer'): urlpatterns.append(path('analytics/', include('cvat.apps.log_viewer.urls'))) +if apps.is_installed('cvat.apps.lambda_manager'): + urlpatterns.append(path('', include('cvat.apps.lambda_manager.urls'))) + if apps.is_installed('silk'): urlpatterns.append(path('profiler/', include('silk.urls'))) - -# new feature by Mohammad -if apps.is_installed('cvat.apps.auto_segmentation'): - urlpatterns.append(path('tensorflow/segmentation/', include('cvat.apps.auto_segmentation.urls'))) diff --git a/cvat_proxy/conf.d/cvat.conf.template b/cvat_proxy/conf.d/cvat.conf.template index 084ce189..287f7284 100644 --- a/cvat_proxy/conf.d/cvat.conf.template +++ b/cvat_proxy/conf.d/cvat.conf.template @@ -12,7 +12,7 @@ server { proxy_set_header Host $http_host; proxy_pass_header Set-Cookie; - location ~* /api/.*|git/.*|tensorflow/.*|auto_annotation/.*|analytics/.*|static/.*|admin|admin/.*|documentation/.*|dextr/.*|reid/.* { + location ~* /api/.*|git/.*|analytics/.*|static/.*|admin|admin/.*|documentation/.* { proxy_pass http://cvat:8080; } diff --git a/datumaro/.gitignore b/datumaro/.gitignore new file mode 100644 index 00000000..17c3ea8b --- /dev/null +++ b/datumaro/.gitignore @@ -0,0 +1 @@ +/datumaro.egg-info diff --git a/docker-compose.yml b/docker-compose.yml index 0b8aebfb..60a5965b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,7 +32,7 @@ services: cvat: container_name: cvat - image: cvat + image: cvat/server restart: always depends_on: - cvat_redis @@ -44,12 +44,9 @@ services: https_proxy: no_proxy: socks_proxy: - TF_ANNOTATION: "no" - AUTO_SEGMENTATION: "no" USER: "django" DJANGO_CONFIGURATION: "production" TZ: "Etc/UTC" - OPENVINO_TOOLKIT: "no" CLAM_AV: "no" environment: DJANGO_MODWSGI_EXTRA_ARGS: "" @@ -64,6 +61,7 @@ services: cvat_ui: container_name: cvat_ui + image: cvat/ui restart: always build: context: . @@ -97,6 +95,22 @@ services: - ./cvat_proxy/conf.d/cvat.conf.template:/etc/nginx/conf.d/cvat.conf.template:ro command: /bin/sh -c "envsubst '$$CVAT_HOST' < /etc/nginx/conf.d/cvat.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" + serverless: + container_name: nuclio + image: quay.io/nuclio/dashboard:1.4.8-amd64 + restart: always + networks: + default: + aliases: + - nuclio + volumes: + - /tmp:/tmp + - /var/run/docker.sock:/var/run/docker.sock + environment: + NUCLIO_CHECK_FUNCTION_CONTAINERS_HEALTHINESS: "true" + ports: + - "8070:8070" + volumes: cvat_db: cvat_data: diff --git a/serverless/deploy.sh b/serverless/deploy.sh new file mode 100755 index 00000000..556f1d3e --- /dev/null +++ b/serverless/deploy.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +nuctl create project cvat +nuctl deploy --project-name cvat \ + --path $SCRIPT_DIR/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio \ + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + +nuctl deploy --project-name cvat \ + --path $SCRIPT_DIR/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio \ + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + +nuctl deploy --project-name cvat \ + --path $SCRIPT_DIR/openvino/omz/public/yolo-v3-tf/nuclio \ + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + +nuctl deploy --project-name cvat \ + --path $SCRIPT_DIR/openvino/omz/intel/text-detection-0004/nuclio \ + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + +nuctl deploy --project-name cvat \ + --path $SCRIPT_DIR/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio \ + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + +nuctl deploy --project-name cvat \ + --path $SCRIPT_DIR/openvino/omz/intel/person-reidentification-retail-300/nuclio \ + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + +nuctl deploy --project-name cvat \ + --path $SCRIPT_DIR/openvino/dextr/nuclio \ + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + +nuctl deploy --project-name cvat \ + --path $SCRIPT_DIR/tensorflow/matterport/mask_rcnn/nuclio + +nuctl deploy --project-name cvat \ + --path $SCRIPT_DIR/tensorflow/faster_rcnn_inception_v2_coco/nuclio + +nuctl get function diff --git a/serverless/openvino/common/model_loader.py b/serverless/openvino/common/model_loader.py new file mode 100644 index 00000000..ca3354d1 --- /dev/null +++ b/serverless/openvino/common/model_loader.py @@ -0,0 +1,72 @@ + +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +import cv2 +import numpy as np +from openvino.inference_engine import IECore + +class ModelLoader: + def __init__(self, model, weights): + ie_core = IECore() + network = ie_core.read_network(model, weights) + self._network = network + + # Check compatibility + supported_layers = ie_core.query_network(network, "CPU") + not_supported_layers = [l for l in network.layers.keys() if l not in supported_layers] + if len(not_supported_layers) != 0: + raise Exception( + "Following layers are not supported by the plugin for specified device {}:\n {}" + .format(ie_core.device, ", ".join(not_supported_layers))) + + # Initialize input blobs + self._input_info_name = None + for blob_name in network.inputs: + if len(network.inputs[blob_name].shape) == 4: + self._input_blob_name = blob_name + elif len(network.inputs[blob_name].shape) == 2: + self._input_info_name = blob_name + else: + raise RuntimeError( + "Unsupported {}D input layer '{}'. Only 2D and 4D input layers are supported" + .format(len(network.inputs[blob_name].shape), blob_name)) + + # Initialize output blob + self._output_blob_name = next(iter(network.outputs)) + + # Load network + self._net = ie_core.load_network(network, "CPU", num_requests=2) + input_type = network.inputs[self._input_blob_name] + self._input_layout = input_type if isinstance(input_type, list) else input_type.shape + + def infer(self, image, preprocessing=True): + image = np.array(image) + _, _, h, w = self._input_layout + if preprocessing: + image = image if image.shape[:-1] == (h, w) else cv2.resize(image, (w, h)) + if len(image.shape) < 3: # grayscale image + image = image[:, :, np.newaxis] + else: + if image.shape[2] == 4: # the image has alpha channel + image = image[:, :, :3] + + image = image.transpose((2, 0, 1)) # Change data layout from HWC to CHW + + inputs = {self._input_blob_name: image} + if self._input_info_name: + inputs[self._input_info_name] = [h, w, 1] + + results = self._net.infer(inputs) + if len(results) == 1: + return results[self._output_blob_name].copy() + else: + return results.copy() + + def input_size(self): + return self._input_layout[2:] + + @property + def layers(self): + return self._network.layers diff --git a/serverless/openvino/common/python3 b/serverless/openvino/common/python3 new file mode 100755 index 00000000..fca7518d --- /dev/null +++ b/serverless/openvino/common/python3 @@ -0,0 +1,7 @@ +#!/bin/bash + +args=$@ + +. /opt/intel/openvino/bin/setupvars.sh +PYTHONPATH=/opt/nuclio/common:$PYTHONPATH +/usr/bin/python3 $args diff --git a/serverless/openvino/dextr/nuclio/function.yaml b/serverless/openvino/dextr/nuclio/function.yaml new file mode 100644 index 00000000..08fbf14f --- /dev/null +++ b/serverless/openvino/dextr/nuclio/function.yaml @@ -0,0 +1,54 @@ +metadata: + name: openvino.dextr + namespace: cvat + annotations: + name: DEXTR + type: interactor + spec: + framework: openvino + +spec: + description: Deep Extreme Cut + runtime: "python:3.6" + handler: main:handler + eventTimeout: 30s + env: + - name: NUCLIO_PYTHON_EXE_PATH + value: /opt/nuclio/common/python3 + + build: + image: cvat/openvino.dextr + baseImage: openvino/ubuntu18_runtime:2020.2 + + directives: + preCopy: + - kind: USER + value: root + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: ln -s /usr/bin/pip3 /usr/bin/pip + + postCopy: + - kind: RUN + value: curl -O https://download.01.org/openvinotoolkit/models_contrib/cvat/dextr_model_v1.zip + - kind: RUN + value: unzip dextr_model_v1.zip + - kind: RUN + value: pip3 install Pillow + - kind: USER + value: openvino + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/openvino/dextr/nuclio/main.py b/serverless/openvino/dextr/nuclio/main.py new file mode 100644 index 00000000..73617002 --- /dev/null +++ b/serverless/openvino/dextr/nuclio/main.py @@ -0,0 +1,26 @@ +import json +import base64 +from PIL import Image +import io +from model_handler import ModelHandler + +def init_context(context): + context.logger.info("Init context... 0%") + + model = ModelHandler() + setattr(context.user_data, 'model', model) + + context.logger.info("Init context...100%") + +def handler(context, event): + context.logger.info("call handler") + data = event.body + points = data["points"] + buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) + image = Image.open(buf) + + polygon = context.user_data.model.handle(image, points) + return context.Response(body=json.dumps(polygon), + headers={}, + content_type='application/json', + status_code=200) diff --git a/serverless/openvino/dextr/nuclio/model_handler.py b/serverless/openvino/dextr/nuclio/model_handler.py new file mode 100644 index 00000000..9dc74116 --- /dev/null +++ b/serverless/openvino/dextr/nuclio/model_handler.py @@ -0,0 +1,84 @@ +# Copyright (C) 2018-2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +import cv2 +import numpy as np +import os +from model_loader import ModelLoader + +class ModelHandler: + def __init__(self): + base_dir = os.environ.get("MODEL_PATH", "/opt/nuclio") + model_xml = os.path.join(base_dir, "dextr.xml") + model_bin = os.path.join(base_dir, "dextr.bin") + self.model = ModelLoader(model_xml, model_bin) + + # Input: + # image: PIL image + # points: [[x1,y1], [x2,y2], [x3,y3], [x4,y4], ...] + # Output: + # polygon: [[x1,y1], [x2,y2], [x3,y3], [x4,y4], ...] + def handle(self, image, points): + DEXTR_PADDING = 50 + DEXTR_TRESHOLD = 0.9 + DEXTR_SIZE = 512 + + numpy_image = np.array(image) + points = np.asarray(points, dtype=int) + bounding_box = ( + max(min(points[:, 0]) - DEXTR_PADDING, 0), + max(min(points[:, 1]) - DEXTR_PADDING, 0), + min(max(points[:, 0]) + DEXTR_PADDING, numpy_image.shape[1] - 1), + min(max(points[:, 1]) + DEXTR_PADDING, numpy_image.shape[0] - 1) + ) + + # Prepare an image + numpy_cropped = np.array(image.crop(bounding_box)) + resized = cv2.resize(numpy_cropped, (DEXTR_SIZE, DEXTR_SIZE), + interpolation = cv2.INTER_CUBIC).astype(np.float32) + if len(resized.shape) == 2: # support grayscale images + resized = cv2.cvtColor(resized, cv2.COLOR_GRAY2RGB) + elif resized.shape[2] == 4: # remove alpha channel + resized = resized[:, :, :3] + + # Make a heatmap + points = points - [min(points[:, 0]), min(points[:, 1])] + [DEXTR_PADDING, DEXTR_PADDING] + points = (points * [DEXTR_SIZE / numpy_cropped.shape[1], DEXTR_SIZE / numpy_cropped.shape[0]]).astype(int) + heatmap = np.zeros(shape=resized.shape[:2], dtype=np.float64) + for point in points: + gaussian_x_axis = np.arange(0, DEXTR_SIZE, 1, float) - point[0] + gaussian_y_axis = np.arange(0, DEXTR_SIZE, 1, float)[:, np.newaxis] - point[1] + gaussian = np.exp(-4 * np.log(2) * ((gaussian_x_axis ** 2 + gaussian_y_axis ** 2) / 100)).astype(np.float64) + heatmap = np.maximum(heatmap, gaussian) + cv2.normalize(heatmap, heatmap, 0, 255, cv2.NORM_MINMAX) + + # Concat an image and a heatmap + input_dextr = np.concatenate((resized, heatmap[:, :, np.newaxis].astype(resized.dtype)), axis=2) + input_dextr = input_dextr.transpose((2,0,1)) + + pred = self.model.infer(input_dextr[np.newaxis, ...], False)[0, 0, :, :] + pred = cv2.resize(pred, tuple(reversed(numpy_cropped.shape[:2])), interpolation = cv2.INTER_CUBIC) + result = np.zeros(numpy_image.shape[:2]) + result[bounding_box[1]:bounding_box[1] + pred.shape[0], bounding_box[0]:bounding_box[0] + pred.shape[1]] = pred > DEXTR_TRESHOLD + + # Convert a mask to a polygon + result = np.array(result, dtype=np.uint8) + cv2.normalize(result,result,0,255,cv2.NORM_MINMAX) + contours = None + if int(cv2.__version__.split('.')[0]) > 3: + contours = cv2.findContours(result, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS)[0] + else: + contours = cv2.findContours(result, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS)[1] + + contours = max(contours, key=lambda arr: arr.size) + if contours.shape.count(1): + contours = np.squeeze(contours) + if contours.size < 3 * 2: + raise Exception('Less then three point have been detected. Can not build a polygon.') + + result = [] + for point in contours: + result.append([int(point[0]), int(point[1])]) + + return result diff --git a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml new file mode 100644 index 00000000..1057efb0 --- /dev/null +++ b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml @@ -0,0 +1,52 @@ +metadata: + name: openvino.omz.intel.person-reidentification-retail-0300 + namespace: cvat + annotations: + name: Person reidentification + type: reid + framework: openvino + spec: + +spec: + description: Person reidentification model for a general scenario + runtime: "python:3.6" + handler: main:handler + eventTimeout: 30s + env: + - name: NUCLIO_PYTHON_EXE_PATH + value: /opt/nuclio/common/python3 + + build: + image: cvat/openvino.omz.intel.person-reidentification-retail-0300 + baseImage: openvino/ubuntu18_dev:2020.2 + + directives: + preCopy: + - kind: USER + value: root + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: ln -s /usr/bin/pip3 /usr/bin/pip + - kind: RUN + value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/downloader.py --name person-reidentification-retail-0300 -o /opt/nuclio/open_model_zoo + - kind: RUN + value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/converter.py --name person-reidentification-retail-0300 --precisions FP32 -d /opt/nuclio/open_model_zoo -o /opt/nuclio/open_model_zoo + + postCopy: + - kind: USER + value: openvino + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/main.py b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/main.py new file mode 100644 index 00000000..9197632a --- /dev/null +++ b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/main.py @@ -0,0 +1,31 @@ +import json +import base64 +from PIL import Image +import io +from model_handler import ModelHandler + +def init_context(context): + context.logger.info("Init context... 0%") + + model = ModelHandler() + setattr(context.user_data, 'model', model) + + context.logger.info("Init context...100%") + +def handler(context, event): + context.logger.info("Run person-reidentification-retail-0300 model") + data = event.body + buf0 = io.BytesIO(base64.b64decode(data["image0"].encode('utf-8'))) + buf1 = io.BytesIO(base64.b64decode(data["image1"].encode('utf-8'))) + threshold = float(data.get("threshold", 0.5)) + max_distance = float(data.get("max_distance", 50)) + image0 = Image.open(buf0) + image1 = Image.open(buf1) + boxes0 = data["boxes0"] + boxes1 = data["boxes1"] + + results = context.user_data.model.infer(image0, boxes0, + image1, boxes1, threshold, max_distance) + + return context.Response(body=json.dumps(results), headers={}, + content_type='application/json', status_code=200) diff --git a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/model_handler.py b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/model_handler.py new file mode 100644 index 00000000..481fa4c4 --- /dev/null +++ b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/model_handler.py @@ -0,0 +1,81 @@ +# Copyright (C) 2018 Intel Corporation +# +# SPDX-License-Identifier: MIT + +import math +import numpy +import os +from scipy.optimize import linear_sum_assignment +from scipy.spatial.distance import euclidean, cosine + +from model_loader import ModelLoader + +class ModelHandler: + def __init__(self): + base_dir = os.environ.get("MODEL_PATH", + "/opt/nuclio/open_model_zoo/intel/person-reidentification-retail-0300/FP32") + model_xml = os.path.join(base_dir, "person-reidentification-retail-0300.xml") + model_bin = os.path.join(base_dir, "person-reidentification-retail-0300.bin") + + self.model = ModelLoader(model_xml, model_bin) + + def infer(self, image0, boxes0, image1, boxes1, threshold, distance): + similarity_matrix = self._compute_similarity_matrix(image0, + boxes0, image1, boxes1, distance) + row_idx, col_idx = linear_sum_assignment(similarity_matrix) + results = [-1] * len(boxes0) + for idx0, idx1 in zip(row_idx, col_idx): + if similarity_matrix[idx0, idx1] <= threshold: + results[idx0] = int(idx1) + + return results + + def _match_boxes(self, box0, box1, distance): + cx0 = (box0["points"][0] + box0["points"][2]) / 2 + cy0 = (box0["points"][1] + box0["points"][3]) / 2 + cx1 = (box1["points"][0] + box1["points"][2]) / 2 + cy1 = (box1["points"][1] + box1["points"][3]) / 2 + is_good_distance = euclidean([cx0, cy0], [cx1, cy1]) <= distance + is_same_label = box0["label_id"] == box1["label_id"] + + return is_good_distance and is_same_label + + def _match_crops(self, crop0, crop1): + embedding0 = self.model.infer(crop0) + embedding1 = self.model.infer(crop1) + + embedding0 = embedding0.reshape(embedding0.size) + embedding1 = embedding1.reshape(embedding1.size) + + return cosine(embedding0, embedding1) + + def _compute_similarity_matrix(self, image0, boxes0, image1, boxes1, + distance): + def _int(number, upper): + return math.floor(numpy.clip(number, 0, upper - 1)) + + DISTANCE_INF = 1000.0 + + matrix = numpy.full([len(boxes0), len(boxes1)], DISTANCE_INF, dtype=float) + for row, box0 in enumerate(boxes0): + w0, h0 = image0.size + xtl0, xbr0, ytl0, ybr0 = ( + _int(box0["points"][0], w0), _int(box0["points"][2], w0), + _int(box0["points"][1], h0), _int(box0["points"][3], h0) + ) + + for col, box1 in enumerate(boxes1): + w1, h1 = image1.size + xtl1, xbr1, ytl1, ybr1 = ( + _int(box1["points"][0], w1), _int(box1["points"][2], w1), + _int(box1["points"][1], h1), _int(box1["points"][3], h1) + ) + + if not self._match_boxes(box0, box1, distance): + continue + + crop0 = image0.crop((xtl0, ytl0, xbr0, ybr0)) + crop1 = image1.crop((xtl1, ytl1, xbr1, ybr1)) + matrix[row][col] = self._match_crops(crop0, crop1) + + return matrix diff --git a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml new file mode 100644 index 00000000..0f3f4454 --- /dev/null +++ b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml @@ -0,0 +1,78 @@ +metadata: + name: openvino.omz.semantic-segmentation-adas-0001 + namespace: cvat + annotations: + name: Semantic segmentation for ADAS + type: detector + framework: openvino + spec: | + [ + { "id": 0, "name": "road" }, + { "id": 1, "name": "sidewalk" }, + { "id": 2, "name": "building" }, + { "id": 3, "name": "wall" }, + { "id": 4, "name": "fence" }, + { "id": 5, "name": "pole" }, + { "id": 6, "name": "traffic light" }, + { "id": 7, "name": "traffic sign" }, + { "id": 8, "name": "vegetation" }, + { "id": 9, "name": "terrain" }, + { "id": 10, "name": "sky" }, + { "id": 11, "name": "person" }, + { "id": 12, "name": "rider" }, + { "id": 13, "name": "car" }, + { "id": 14, "name": "truck" }, + { "id": 15, "name": "bus" }, + { "id": 16, "name": "train" }, + { "id": 17, "name": "motorcycle" }, + { "id": 18, "name": "bicycle" }, + { "id": 19, "name": "ego-vehicle" }, + { "id": 20, "name": "background" } + ] + +spec: + description: Segmentation network to classify each pixel into typical 20 classes for ADAS + runtime: "python:3.6" + handler: main:handler + eventTimeout: 30s + env: + - name: NUCLIO_PYTHON_EXE_PATH + value: /opt/nuclio/common/python3 + + build: + image: cvat/openvino.omz.intel.semantic-segmentation-adas-0001 + baseImage: openvino/ubuntu18_dev:2020.2 + + directives: + preCopy: + - kind: USER + value: root + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: ln -s /usr/bin/pip3 /usr/bin/pip + - kind: RUN + value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/downloader.py --name semantic-segmentation-adas-0001 -o /opt/nuclio/open_model_zoo + + + postCopy: + - kind: RUN + value: apt update && DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends -y python3-skimage + - kind: RUN + value: pip3 install "numpy<1.16.0" # workaround for skimage + - kind: USER + value: openvino + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/main.py b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/main.py new file mode 100644 index 00000000..9942bc02 --- /dev/null +++ b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/main.py @@ -0,0 +1,32 @@ +import json +import base64 +from PIL import Image +import io +from model_handler import ModelHandler +import yaml + +def init_context(context): + context.logger.info("Init context... 0%") + + # Read labels + functionconfig = yaml.safe_load(open("/opt/nuclio/function.yaml")) + labels_spec = functionconfig['metadata']['annotations']['spec'] + labels = {item['id']: item['name'] for item in json.loads(labels_spec)} + + # Read the DL model + model = ModelHandler(labels) + setattr(context.user_data, 'model', model) + + context.logger.info("Init context...100%") + +def handler(context, event): + context.logger.info("Run semantic-segmentation-adas-0001 model") + data = event.body + buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) + threshold = float(data.get("threshold", 0.5)) + image = Image.open(buf) + + results = context.user_data.model.infer(image, threshold) + + return context.Response(body=json.dumps(results), headers={}, + content_type='application/json', status_code=200) diff --git a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/model_handler.py b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/model_handler.py new file mode 100644 index 00000000..5b4bb722 --- /dev/null +++ b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/model_handler.py @@ -0,0 +1,50 @@ +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +import os +import cv2 +import numpy as np +from skimage.measure import approximate_polygon, find_contours +from model_loader import ModelLoader + +class ModelHandler: + def __init__(self, labels): + base_dir = os.environ.get("MODEL_PATH", + "/opt/nuclio/open_model_zoo/intel/semantic-segmentation-adas-0001/FP32") + model_xml = os.path.join(base_dir, "semantic-segmentation-adas-0001.xml") + model_bin = os.path.join(base_dir, "semantic-segmentation-adas-0001.bin") + self.model = ModelLoader(model_xml, model_bin) + self.labels = labels + + def infer(self, image, threshold): + output_layer = self.model.infer(image) + + results = [] + mask = output_layer[0, 0, :, :] + width, height = mask.shape + + for i in range(len(self.labels)): + mask_by_label = np.zeros((width, height), dtype=np.uint8) + + mask_by_label = ((mask == float(i)) * 255).astype(np.float32) + mask_by_label = cv2.resize(mask_by_label, + dsize=(image.width, image.height), + interpolation=cv2.INTER_CUBIC) + + contours = find_contours(mask_by_label, 0.8) + + for contour in contours: + contour = np.flip(contour, axis=1) + contour = approximate_polygon(contour, tolerance=2.5) + if len(contour) < 3: + continue + + results.append({ + "confidence": None, + "label": self.labels.get(i, "unknown"), + "points": contour.ravel().tolist(), + "type": "polygon", + }) + + return results \ No newline at end of file diff --git a/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml new file mode 100644 index 00000000..864ed2d1 --- /dev/null +++ b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml @@ -0,0 +1,53 @@ +metadata: + name: openvino.omz.intel.text-detection-0004 + namespace: cvat + annotations: + name: Text detection v4 + type: detector + framework: openvino + spec: | + [ + { "id": 1, "name": "text" } + ] + +spec: + description: Text detector based on PixelLink architecture with MobileNetV2-like as a backbone for indoor/outdoor scenes. + runtime: "python:3.6" + handler: main:handler + eventTimeout: 30s + env: + - name: NUCLIO_PYTHON_EXE_PATH + value: /opt/nuclio/common/python3 + + build: + image: cvat/openvino.omz.intel.text-detection-0004 + baseImage: openvino/ubuntu18_dev:2020.2 + + directives: + preCopy: + - kind: USER + value: root + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: ln -s /usr/bin/pip3 /usr/bin/pip + - kind: RUN + value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/downloader.py --name text-detection-0004 -o /opt/nuclio/open_model_zoo + + postCopy: + - kind: USER + value: openvino + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/openvino/omz/intel/text-detection-0004/nuclio/main.py b/serverless/openvino/omz/intel/text-detection-0004/nuclio/main.py new file mode 100644 index 00000000..ab54e76c --- /dev/null +++ b/serverless/openvino/omz/intel/text-detection-0004/nuclio/main.py @@ -0,0 +1,34 @@ +import json +import base64 +from PIL import Image +import io +from model_handler import ModelHandler +import yaml + +def init_context(context): + context.logger.info("Init context... 0%") + + # Read labels + functionconfig = yaml.safe_load(open("/opt/nuclio/function.yaml")) + labels_spec = functionconfig['metadata']['annotations']['spec'] + labels = {item['id']: item['name'] for item in json.loads(labels_spec)} + + # Read the DL model + model = ModelHandler(labels) + setattr(context.user_data, 'model', model) + + context.logger.info("Init context...100%") + +def handler(context, event): + context.logger.info("Run text-detection-0004 model") + data = event.body + buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) + pixel_threshold = float(data.get("pixel_threshold", 0.8)) + link_threshold = float(data.get("link_threshold", 0.8)) + image = Image.open(buf) + + results = context.user_data.model.infer(image, + pixel_threshold, link_threshold) + + return context.Response(body=json.dumps(results), headers={}, + content_type='application/json', status_code=200) diff --git a/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0004/pixel_link_mobilenet_v2.py b/serverless/openvino/omz/intel/text-detection-0004/nuclio/model_handler.py similarity index 83% rename from utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0004/pixel_link_mobilenet_v2.py rename to serverless/openvino/omz/intel/text-detection-0004/nuclio/model_handler.py index b0f105ec..6ea78c1e 100644 --- a/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0004/pixel_link_mobilenet_v2.py +++ b/serverless/openvino/omz/intel/text-detection-0004/nuclio/model_handler.py @@ -1,18 +1,21 @@ -# SPDX-License-Identifier: MIT` +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT +import os import cv2 import numpy as np - +from model_loader import ModelLoader class PixelLinkDecoder(): - def __init__(self): + def __init__(self, pixel_threshold, link_threshold): four_neighbours = False if four_neighbours: self._get_neighbours = self._get_neighbours_4 else: self._get_neighbours = self._get_neighbours_8 - self.pixel_conf_threshold = 0.8 - self.link_conf_threshold = 0.8 + self.pixel_conf_threshold = pixel_threshold + self.link_conf_threshold = link_threshold def decode(self, height, width, detections: dict): self.image_height = height @@ -186,12 +189,29 @@ class PixelLinkDecoder(): self._get_all() self._mask_to_bboxes() - -label = 1 -pcd = PixelLinkDecoder() -for detection in detections: - frame = detection['frame_id'] - pcd.decode(detection['frame_height'], detection['frame_width'], detection['detections']) - for box in pcd.bboxes: - box = [[int(b[0]), int(b[1])] for b in box] - results.add_polygon(box, label, frame) +class ModelHandler: + def __init__(self, labels): + base_dir = os.environ.get("MODEL_PATH", + "/opt/nuclio/open_model_zoo/intel/text-detection-0004/FP32") + model_xml = os.path.join(base_dir, "text-detection-0004.xml") + model_bin = os.path.join(base_dir, "text-detection-0004.bin") + self.model = ModelLoader(model_xml, model_bin) + self.labels = labels + + def infer(self, image, pixel_threshold, link_threshold): + output_layer = self.model.infer(image) + + results = [] + obj_class = 1 + pcd = PixelLinkDecoder(pixel_threshold, link_threshold) + + pcd.decode(image.height, image.width, output_layer) + for box in pcd.bboxes: + results.append({ + "confidence": None, + "label": self.labels.get(obj_class, "unknown"), + "points": box.ravel().tolist(), + "type": "polygon", + }) + + return results \ No newline at end of file diff --git a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml new file mode 100644 index 00000000..b8ea9f53 --- /dev/null +++ b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml @@ -0,0 +1,134 @@ +metadata: + name: openvino.omz.public.faster_rcnn_inception_v2_coco + namespace: cvat + annotations: + name: Faster RCNN + type: detector + framework: openvino + spec: | + [ + { "id": 1, "name": "person" }, + { "id": 2, "name": "bicycle" }, + { "id": 3, "name": "car" }, + { "id": 4, "name": "motorcycle" }, + { "id": 5, "name": "airplane" }, + { "id": 6, "name": "bus" }, + { "id": 7, "name": "train" }, + { "id": 8, "name": "truck" }, + { "id": 9, "name": "boat" }, + { "id":10, "name": "traffic_light" }, + { "id":11, "name": "fire_hydrant" }, + { "id":13, "name": "stop_sign" }, + { "id":14, "name": "parking_meter" }, + { "id":15, "name": "bench" }, + { "id":16, "name": "bird" }, + { "id":17, "name": "cat" }, + { "id":18, "name": "dog" }, + { "id":19, "name": "horse" }, + { "id":20, "name": "sheep" }, + { "id":21, "name": "cow" }, + { "id":22, "name": "elephant" }, + { "id":23, "name": "bear" }, + { "id":24, "name": "zebra" }, + { "id":25, "name": "giraffe" }, + { "id":27, "name": "backpack" }, + { "id":28, "name": "umbrella" }, + { "id":31, "name": "handbag" }, + { "id":32, "name": "tie" }, + { "id":33, "name": "suitcase" }, + { "id":34, "name": "frisbee" }, + { "id":35, "name": "skis" }, + { "id":36, "name": "snowboard" }, + { "id":37, "name": "sports_ball" }, + { "id":38, "name": "kite" }, + { "id":39, "name": "baseball_bat" }, + { "id":40, "name": "baseball_glove" }, + { "id":41, "name": "skateboard" }, + { "id":42, "name": "surfboard" }, + { "id":43, "name": "tennis_racket" }, + { "id":44, "name": "bottle" }, + { "id":46, "name": "wine_glass" }, + { "id":47, "name": "cup" }, + { "id":48, "name": "fork" }, + { "id":49, "name": "knife" }, + { "id":50, "name": "spoon" }, + { "id":51, "name": "bowl" }, + { "id":52, "name": "banana" }, + { "id":53, "name": "apple" }, + { "id":54, "name": "sandwich" }, + { "id":55, "name": "orange" }, + { "id":56, "name": "broccoli" }, + { "id":57, "name": "carrot" }, + { "id":58, "name": "hot_dog" }, + { "id":59, "name": "pizza" }, + { "id":60, "name": "donut" }, + { "id":61, "name": "cake" }, + { "id":62, "name": "chair" }, + { "id":63, "name": "couch" }, + { "id":64, "name": "potted_plant" }, + { "id":65, "name": "bed" }, + { "id":67, "name": "dining_table" }, + { "id":70, "name": "toilet" }, + { "id":72, "name": "tv" }, + { "id":73, "name": "laptop" }, + { "id":74, "name": "mouse" }, + { "id":75, "name": "remote" }, + { "id":76, "name": "keyboard" }, + { "id":77, "name": "cell_phone" }, + { "id":78, "name": "microwave" }, + { "id":79, "name": "oven" }, + { "id":80, "name": "toaster" }, + { "id":81, "name": "sink" }, + { "id":83, "name": "refrigerator" }, + { "id":84, "name": "book" }, + { "id":85, "name": "clock" }, + { "id":86, "name": "vase" }, + { "id":87, "name": "scissors" }, + { "id":88, "name": "teddy_bear" }, + { "id":89, "name": "hair_drier" }, + { "id":90, "name": "toothbrush" } + ] + +spec: + description: Faster RCNN inception v2 COCO via Intel OpenVINO toolkit + runtime: "python:3.6" + handler: main:handler + eventTimeout: 30s + env: + - name: NUCLIO_PYTHON_EXE_PATH + value: /opt/nuclio/common/python3 + + build: + image: cvat/openvino.omz.public.faster_rcnn_inception_v2_coco + baseImage: openvino/ubuntu18_dev:2020.2 + + directives: + preCopy: + - kind: USER + value: root + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: ln -s /usr/bin/pip3 /usr/bin/pip + - kind: RUN + value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/downloader.py --name faster_rcnn_inception_v2_coco -o /opt/nuclio/open_model_zoo + - kind: RUN + value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/converter.py --name faster_rcnn_inception_v2_coco --precisions FP32 -d /opt/nuclio/open_model_zoo -o /opt/nuclio/open_model_zoo + + postCopy: + - kind: USER + value: openvino + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/main.py b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/main.py new file mode 100644 index 00000000..6ae5c801 --- /dev/null +++ b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/main.py @@ -0,0 +1,32 @@ +import json +import base64 +from PIL import Image +import io +from model_handler import ModelHandler +import yaml + +def init_context(context): + context.logger.info("Init context... 0%") + + # Read labels + functionconfig = yaml.safe_load(open("/opt/nuclio/function.yaml")) + labels_spec = functionconfig['metadata']['annotations']['spec'] + labels = {item['id']: item['name'] for item in json.loads(labels_spec)} + + # Read the DL model + model = ModelHandler(labels) + setattr(context.user_data, 'model', model) + + context.logger.info("Init context...100%") + +def handler(context, event): + context.logger.info("Run faster_rcnn_inception_v2_coco model") + data = event.body + buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) + threshold = float(data.get("threshold", 0.5)) + image = Image.open(buf) + + results = context.user_data.model.infer(image, threshold) + + return context.Response(body=json.dumps(results), headers={}, + content_type='application/json', status_code=200) diff --git a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/model_handler.py b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/model_handler.py new file mode 100644 index 00000000..60838779 --- /dev/null +++ b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/model_handler.py @@ -0,0 +1,39 @@ +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +import os +from model_loader import ModelLoader + +class ModelHandler: + def __init__(self, labels): + base_dir = os.environ.get("MODEL_PATH", + "/opt/nuclio/open_model_zoo/public/faster_rcnn_inception_v2_coco/FP32") + model_xml = os.path.join(base_dir, "faster_rcnn_inception_v2_coco.xml") + model_bin = os.path.join(base_dir, "faster_rcnn_inception_v2_coco.bin") + self.model = ModelLoader(model_xml, model_bin) + self.labels = labels + + def infer(self, image, threshold): + output_layer = self.model.infer(image) + + results = [] + prediction = output_layer[0][0] + for obj in prediction: + obj_class = int(obj[1]) + obj_value = obj[2] + obj_label = self.labels.get(obj_class, "unknown") + if obj_value >= threshold: + xtl = obj[3] * image.width + ytl = obj[4] * image.height + xbr = obj[5] * image.width + ybr = obj[6] * image.height + + results.append({ + "confidence": str(obj_value), + "label": obj_label, + "points": [xtl, ytl, xbr, ybr], + "type": "rectangle", + }) + + return results \ No newline at end of file diff --git a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml new file mode 100644 index 00000000..5b94d954 --- /dev/null +++ b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml @@ -0,0 +1,141 @@ +# To build the function you need to adjust docker settings. Be sure that you +# have enough memory (more than 4GB). Look here how to do that +# https://stackoverflow.com/questions/44417159/docker-process-killed-with-cryptic-killed-message +metadata: + name: openvino.omz.public.mask_rcnn_inception_resnet_v2_atrous_coco + namespace: cvat + annotations: + name: Mask RCNN + type: detector + framework: openvino + spec: | + [ + { "id": 1, "name": "person" }, + { "id": 2, "name": "bicycle" }, + { "id": 3, "name": "car" }, + { "id": 4, "name": "motorcycle" }, + { "id": 5, "name": "airplane" }, + { "id": 6, "name": "bus" }, + { "id": 7, "name": "train" }, + { "id": 8, "name": "truck" }, + { "id": 9, "name": "boat" }, + { "id":10, "name": "traffic_light" }, + { "id":11, "name": "fire_hydrant" }, + { "id":13, "name": "stop_sign" }, + { "id":14, "name": "parking_meter" }, + { "id":15, "name": "bench" }, + { "id":16, "name": "bird" }, + { "id":17, "name": "cat" }, + { "id":18, "name": "dog" }, + { "id":19, "name": "horse" }, + { "id":20, "name": "sheep" }, + { "id":21, "name": "cow" }, + { "id":22, "name": "elephant" }, + { "id":23, "name": "bear" }, + { "id":24, "name": "zebra" }, + { "id":25, "name": "giraffe" }, + { "id":27, "name": "backpack" }, + { "id":28, "name": "umbrella" }, + { "id":31, "name": "handbag" }, + { "id":32, "name": "tie" }, + { "id":33, "name": "suitcase" }, + { "id":34, "name": "frisbee" }, + { "id":35, "name": "skis" }, + { "id":36, "name": "snowboard" }, + { "id":37, "name": "sports_ball" }, + { "id":38, "name": "kite" }, + { "id":39, "name": "baseball_bat" }, + { "id":40, "name": "baseball_glove" }, + { "id":41, "name": "skateboard" }, + { "id":42, "name": "surfboard" }, + { "id":43, "name": "tennis_racket" }, + { "id":44, "name": "bottle" }, + { "id":46, "name": "wine_glass" }, + { "id":47, "name": "cup" }, + { "id":48, "name": "fork" }, + { "id":49, "name": "knife" }, + { "id":50, "name": "spoon" }, + { "id":51, "name": "bowl" }, + { "id":52, "name": "banana" }, + { "id":53, "name": "apple" }, + { "id":54, "name": "sandwich" }, + { "id":55, "name": "orange" }, + { "id":56, "name": "broccoli" }, + { "id":57, "name": "carrot" }, + { "id":58, "name": "hot_dog" }, + { "id":59, "name": "pizza" }, + { "id":60, "name": "donut" }, + { "id":61, "name": "cake" }, + { "id":62, "name": "chair" }, + { "id":63, "name": "couch" }, + { "id":64, "name": "potted_plant" }, + { "id":65, "name": "bed" }, + { "id":67, "name": "dining_table" }, + { "id":70, "name": "toilet" }, + { "id":72, "name": "tv" }, + { "id":73, "name": "laptop" }, + { "id":74, "name": "mouse" }, + { "id":75, "name": "remote" }, + { "id":76, "name": "keyboard" }, + { "id":77, "name": "cell_phone" }, + { "id":78, "name": "microwave" }, + { "id":79, "name": "oven" }, + { "id":80, "name": "toaster" }, + { "id":81, "name": "sink" }, + { "id":83, "name": "refrigerator" }, + { "id":84, "name": "book" }, + { "id":85, "name": "clock" }, + { "id":86, "name": "vase" }, + { "id":87, "name": "scissors" }, + { "id":88, "name": "teddy_bear" }, + { "id":89, "name": "hair_drier" }, + { "id":90, "name": "toothbrush" } + ] + +spec: + description: Mask RCNN inception resnet v2 COCO via Intel OpenVINO + runtime: "python:3.6" + handler: main:handler + eventTimeout: 60s + env: + - name: NUCLIO_PYTHON_EXE_PATH + value: /opt/nuclio/common/python3 + + build: + image: cvat/openvino.omz.public.mask_rcnn_inception_resnet_v2_atrous_coco + baseImage: openvino/ubuntu18_dev:2020.2 + + directives: + preCopy: + - kind: USER + value: root + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: ln -s /usr/bin/pip3 /usr/bin/pip + - kind: RUN + value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/downloader.py --name mask_rcnn_inception_resnet_v2_atrous_coco -o /opt/nuclio/open_model_zoo + - kind: RUN + value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/converter.py --name mask_rcnn_inception_resnet_v2_atrous_coco --precisions FP32 -d /opt/nuclio/open_model_zoo -o /opt/nuclio/open_model_zoo + + postCopy: + - kind: RUN + value: apt update && DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends -y python3-skimage + - kind: RUN + value: pip3 install "numpy<1.16.0" # workaround for skimage + - kind: USER + value: openvino + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/main.py b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/main.py new file mode 100644 index 00000000..8fc7d285 --- /dev/null +++ b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/main.py @@ -0,0 +1,32 @@ +import json +import base64 +from PIL import Image +import io +from model_handler import ModelHandler +import yaml + +def init_context(context): + context.logger.info("Init context... 0%") + + # Read labels + functionconfig = yaml.safe_load(open("/opt/nuclio/function.yaml")) + labels_spec = functionconfig['metadata']['annotations']['spec'] + labels = {item['id']: item['name'] for item in json.loads(labels_spec)} + + # Read the DL model + model = ModelHandler(labels) + setattr(context.user_data, 'model', model) + + context.logger.info("Init context...100%") + +def handler(context, event): + context.logger.info("Run mask_rcnn_inception_resnet_v2_atrous_coco model") + data = event.body + buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) + threshold = float(data.get("threshold", 0.2)) + image = Image.open(buf) + + results = context.user_data.model.infer(image, threshold) + + return context.Response(body=json.dumps(results), headers={}, + content_type='application/json', status_code=200) diff --git a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/model_handler.py b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/model_handler.py new file mode 100644 index 00000000..a508aaa4 --- /dev/null +++ b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/model_handler.py @@ -0,0 +1,77 @@ +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +import os +import cv2 +import numpy as np +from model_loader import ModelLoader +from skimage.measure import approximate_polygon, find_contours + + +MASK_THRESHOLD = 0.5 + +# Ref: https://software.intel.com/en-us/forums/computer-vision/topic/804895 +def segm_postprocess(box: list, raw_cls_mask, im_h, im_w): + ymin, xmin, ymax, xmax = box + + width = int(abs(xmax - xmin)) + height = int(abs(ymax - ymin)) + + result = np.zeros((im_h, im_w), dtype=np.uint8) + resized_mask = cv2.resize(raw_cls_mask, dsize=(height, width), interpolation=cv2.INTER_CUBIC) + + # extract the ROI of the image + ymin = int(round(ymin)) + xmin = int(round(xmin)) + ymax = ymin + height + xmax = xmin + width + result[xmin:xmax, ymin:ymax] = (resized_mask>MASK_THRESHOLD).astype(np.uint8) * 255 + + return result + +class ModelHandler: + def __init__(self, labels): + base_dir = os.environ.get("MODEL_PATH", + "/opt/nuclio/open_model_zoo/public/mask_rcnn_inception_resnet_v2_atrous_coco/FP32") + model_xml = os.path.join(base_dir, "mask_rcnn_inception_resnet_v2_atrous_coco.xml") + model_bin = os.path.join(base_dir, "mask_rcnn_inception_resnet_v2_atrous_coco.bin") + self.model = ModelLoader(model_xml, model_bin) + self.labels = labels + + def infer(self, image, threshold): + output_layer = self.model.infer(image) + + results = [] + masks = output_layer['masks'] + boxes = output_layer['reshape_do_2d'] + + for index, box in enumerate(boxes): + obj_class = int(box[1]) + obj_value = box[2] + obj_label = self.labels.get(obj_class, "unknown") + if obj_value >= threshold: + xtl = box[3] * image.width + ytl = box[4] * image.height + xbr = box[5] * image.width + ybr = box[6] * image.height + mask = masks[index][obj_class - 1] + + mask = segm_postprocess((xtl, ytl, xbr, ybr), + mask, image.height, image.width) + + contours = find_contours(mask, MASK_THRESHOLD) + contour = contours[0] + contour = np.flip(contour, axis=1) + contour = approximate_polygon(contour, tolerance=2.5) + if len(contour) < 3: + continue + + results.append({ + "confidence": str(obj_value), + "label": obj_label, + "points": contour.ravel().tolist(), + "type": "polygon", + }) + + return results \ No newline at end of file diff --git a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml new file mode 100644 index 00000000..3ec733b7 --- /dev/null +++ b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml @@ -0,0 +1,134 @@ +metadata: + name: openvino.omz.public.yolo-v3-tf + namespace: cvat + annotations: + name: YOLO v3 + type: detector + framework: openvino + spec: | + [ + { "id": 0, "name": "person" }, + { "id": 1, "name": "bicycle" }, + { "id": 2, "name": "car" }, + { "id": 3, "name": "motorbike" }, + { "id": 4, "name": "aeroplane" }, + { "id": 5, "name": "bus" }, + { "id": 6, "name": "train" }, + { "id": 7, "name": "truck" }, + { "id": 8, "name": "boat" }, + { "id": 9, "name": "traffic light" }, + { "id": 10, "name": "fire hydrant" }, + { "id": 11, "name": "stop sign" }, + { "id": 12, "name": "parking meter" }, + { "id": 13, "name": "bench" }, + { "id": 14, "name": "bird" }, + { "id": 15, "name": "cat" }, + { "id": 16, "name": "dog" }, + { "id": 17, "name": "horse" }, + { "id": 18, "name": "sheep" }, + { "id": 19, "name": "cow" }, + { "id": 20, "name": "elephant" }, + { "id": 21, "name": "bear" }, + { "id": 22, "name": "zebra" }, + { "id": 23, "name": "giraffe" }, + { "id": 24, "name": "backpack" }, + { "id": 25, "name": "umbrella" }, + { "id": 26, "name": "handbag" }, + { "id": 27, "name": "tie" }, + { "id": 28, "name": "suitcase" }, + { "id": 29, "name": "frisbee" }, + { "id": 30, "name": "skis" }, + { "id": 31, "name": "snowboard" }, + { "id": 32, "name": "sports ball" }, + { "id": 33, "name": "kite" }, + { "id": 34, "name": "baseball bat" }, + { "id": 35, "name": "baseball glove" }, + { "id": 36, "name": "skateboard" }, + { "id": 37, "name": "surfboard" }, + { "id": 38, "name": "tennis racket" }, + { "id": 39, "name": "bottle" }, + { "id": 40, "name": "wine glass" }, + { "id": 41, "name": "cup" }, + { "id": 42, "name": "fork" }, + { "id": 43, "name": "knife" }, + { "id": 44, "name": "spoon" }, + { "id": 45, "name": "bowl" }, + { "id": 46, "name": "banana" }, + { "id": 47, "name": "apple" }, + { "id": 48, "name": "sandwich" }, + { "id": 49, "name": "orange" }, + { "id": 50, "name": "broccoli" }, + { "id": 51, "name": "carrot" }, + { "id": 52, "name": "hot dog" }, + { "id": 53, "name": "pizza" }, + { "id": 54, "name": "donut" }, + { "id": 55, "name": "cake" }, + { "id": 56, "name": "chair" }, + { "id": 57, "name": "sofa" }, + { "id": 58, "name": "pottedplant" }, + { "id": 59, "name": "bed" }, + { "id": 60, "name": "diningtable" }, + { "id": 61, "name": "toilet" }, + { "id": 62, "name": "tvmonitor" }, + { "id": 63, "name": "laptop" }, + { "id": 64, "name": "mouse" }, + { "id": 65, "name": "remote" }, + { "id": 66, "name": "keyboard" }, + { "id": 67, "name": "cell phone" }, + { "id": 68, "name": "microwave" }, + { "id": 69, "name": "oven" }, + { "id": 70, "name": "toaster" }, + { "id": 71, "name": "sink" }, + { "id": 72, "name": "refrigerator" }, + { "id": 73, "name": "book" }, + { "id": 74, "name": "clock" }, + { "id": 75, "name": "vase" }, + { "id": 76, "name": "scissors" }, + { "id": 77, "name": "teddy bear" }, + { "id": 78, "name": "hair drier" }, + { "id": 79, "name": "toothbrush" } + ] + +spec: + description: YOLO v3 via Intel OpenVINO + runtime: "python:3.6" + handler: main:handler + eventTimeout: 30s + env: + - name: NUCLIO_PYTHON_EXE_PATH + value: /opt/nuclio/common/python3 + + build: + image: cvat/openvino.omz.public.yolo-v3-tf + baseImage: openvino/ubuntu18_dev:2020.2 + + directives: + preCopy: + - kind: USER + value: root + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: ln -s /usr/bin/pip3 /usr/bin/pip + - kind: RUN + value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/downloader.py --name yolo-v3-tf -o /opt/nuclio/open_model_zoo + - kind: RUN + value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/converter.py --name yolo-v3-tf --precisions FP32 -d /opt/nuclio/open_model_zoo -o /opt/nuclio/open_model_zoo + + postCopy: + - kind: USER + value: openvino + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/main.py b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/main.py new file mode 100644 index 00000000..806ab654 --- /dev/null +++ b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/main.py @@ -0,0 +1,32 @@ +import json +import base64 +from PIL import Image +import io +from model_handler import ModelHandler +import yaml + +def init_context(context): + context.logger.info("Init context... 0%") + + # Read labels + functionconfig = yaml.safe_load(open("/opt/nuclio/function.yaml")) + labels_spec = functionconfig['metadata']['annotations']['spec'] + labels = {item['id']: item['name'] for item in json.loads(labels_spec)} + + # Read the DL model + model = ModelHandler(labels) + setattr(context.user_data, 'model', model) + + context.logger.info("Init context...100%") + +def handler(context, event): + context.logger.info("Run yolo-v3-tf model") + data = event.body + buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) + threshold = float(data.get("threshold", 0.5)) + image = Image.open(buf) + + results = context.user_data.model.infer(image, threshold) + + return context.Response(body=json.dumps(results), headers={}, + content_type='application/json', status_code=200) diff --git a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/model_handler.py b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/model_handler.py new file mode 100644 index 00000000..47fa5842 --- /dev/null +++ b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/model_handler.py @@ -0,0 +1,160 @@ +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +import os +from math import exp +from model_loader import ModelLoader + +class YoloParams: + # ------------------------------------------- Extracting layer parameters ------------------------------------------ + # Magic numbers are copied from yolo samples + def __init__(self, param, side): + self.num = 3 if 'num' not in param else int(param['num']) + self.coords = 4 if 'coords' not in param else int(param['coords']) + self.classes = 80 if 'classes' not in param else int(param['classes']) + self.side = side + self.anchors = [10.0, 13.0, 16.0, 30.0, 33.0, 23.0, 30.0, 61.0, 62.0, 45.0, 59.0, 119.0, 116.0, 90.0, 156.0, + 198.0, + 373.0, 326.0] if 'anchors' not in param else [float(a) for a in param['anchors'].split(',')] + + self.isYoloV3 = False + + if param.get('mask'): + mask = [int(idx) for idx in param['mask'].split(',')] + self.num = len(mask) + + maskedAnchors = [] + for idx in mask: + maskedAnchors += [self.anchors[idx * 2], self.anchors[idx * 2 + 1]] + self.anchors = maskedAnchors + + self.isYoloV3 = True # Weak way to determine but the only one. + + +def entry_index(side, coord, classes, location, entry): + side_power_2 = side ** 2 + n = location // side_power_2 + loc = location % side_power_2 + return int(side_power_2 * (n * (coord + classes + 1) + entry) + loc) + + +def scale_bbox(x, y, h, w, class_id, confidence, h_scale, w_scale): + xmin = int((x - w / 2) * w_scale) + ymin = int((y - h / 2) * h_scale) + xmax = int(xmin + w * w_scale) + ymax = int(ymin + h * h_scale) + return dict(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, class_id=class_id, confidence=confidence) + + +def parse_yolo_region(blob, resized_image_shape, original_im_shape, params, threshold): + # ------------------------------------------ Validating output parameters ------------------------------------------ + _, _, out_blob_h, out_blob_w = blob.shape + assert out_blob_w == out_blob_h, "Invalid size of output blob. It sould be in NCHW layout and height should " \ + "be equal to width. Current height = {}, current width = {}" \ + "".format(out_blob_h, out_blob_w) + + # ------------------------------------------ Extracting layer parameters ------------------------------------------- + orig_im_h, orig_im_w = original_im_shape + resized_image_h, resized_image_w = resized_image_shape + objects = list() + predictions = blob.flatten() + side_square = params.side * params.side + + # ------------------------------------------- Parsing YOLO Region output ------------------------------------------- + for i in range(side_square): + row = i // params.side + col = i % params.side + for n in range(params.num): + obj_index = entry_index(params.side, params.coords, params.classes, n * side_square + i, params.coords) + scale = predictions[obj_index] + if scale < threshold: + continue + box_index = entry_index(params.side, params.coords, params.classes, n * side_square + i, 0) + # Network produces location predictions in absolute coordinates of feature maps. + # Scale it to relative coordinates. + x = (col + predictions[box_index + 0 * side_square]) / params.side + y = (row + predictions[box_index + 1 * side_square]) / params.side + # Value for exp is very big number in some cases so following construction is using here + try: + w_exp = exp(predictions[box_index + 2 * side_square]) + h_exp = exp(predictions[box_index + 3 * side_square]) + except OverflowError: + continue + # Depends on topology we need to normalize sizes by feature maps (up to YOLOv3) or by input shape (YOLOv3) + w = w_exp * params.anchors[2 * n] / (resized_image_w if params.isYoloV3 else params.side) + h = h_exp * params.anchors[2 * n + 1] / (resized_image_h if params.isYoloV3 else params.side) + for j in range(params.classes): + class_index = entry_index(params.side, params.coords, params.classes, n * side_square + i, + params.coords + 1 + j) + confidence = scale * predictions[class_index] + if confidence < threshold: + continue + objects.append(scale_bbox(x=x, y=y, h=h, w=w, class_id=j, confidence=confidence, + h_scale=orig_im_h, w_scale=orig_im_w)) + return objects + + +def intersection_over_union(box_1, box_2): + width_of_overlap_area = min(box_1['xmax'], box_2['xmax']) - max(box_1['xmin'], box_2['xmin']) + height_of_overlap_area = min(box_1['ymax'], box_2['ymax']) - max(box_1['ymin'], box_2['ymin']) + if width_of_overlap_area < 0 or height_of_overlap_area < 0: + area_of_overlap = 0 + else: + area_of_overlap = width_of_overlap_area * height_of_overlap_area + box_1_area = (box_1['ymax'] - box_1['ymin']) * (box_1['xmax'] - box_1['xmin']) + box_2_area = (box_2['ymax'] - box_2['ymin']) * (box_2['xmax'] - box_2['xmin']) + area_of_union = box_1_area + box_2_area - area_of_overlap + if area_of_union == 0: + return 0 + return area_of_overlap / area_of_union + + +class ModelHandler: + def __init__(self, labels): + base_dir = os.environ.get("MODEL_PATH", + "/opt/nuclio/open_model_zoo/public/yolo-v3-tf/FP32") + model_xml = os.path.join(base_dir, "yolo-v3-tf.xml") + model_bin = os.path.join(base_dir, "yolo-v3-tf.bin") + self.model = ModelLoader(model_xml, model_bin) + self.labels = labels + + def infer(self, image, threshold): + output_layer = self.model.infer(image) + + # Collecting object detection results + objects = [] + origin_im_size = (image.height, image.width) + for layer_name, out_blob in output_layer.items(): + out_blob = out_blob.reshape(self.model.layers[self.model.layers[layer_name].parents[0]].shape) + layer_params = YoloParams(self.model.layers[layer_name].params, out_blob.shape[2]) + objects += parse_yolo_region(out_blob, self.model.input_size(), + origin_im_size, layer_params, threshold) + + # Filtering overlapping boxes (non-maximum supression) + IOU_THRESHOLD = 0.4 + objects = sorted(objects, key=lambda obj : obj['confidence'], reverse=True) + for i, obj in enumerate(objects): + if obj['confidence'] == 0: + continue + for j in range(i + 1, len(objects)): + if intersection_over_union(obj, objects[j]) > IOU_THRESHOLD: + objects[j]['confidence'] = 0 + + results = [] + for obj in objects: + if obj['confidence'] >= threshold: + xtl = max(obj['xmin'], 0) + ytl = max(obj['ymin'], 0) + xbr = min(obj['xmax'], image.width) + ybr = min(obj['ymax'], image.height) + obj_class = int(obj['class_id']) + + results.append({ + "confidence": str(obj['confidence']), + "label": self.labels.get(obj_class, "unknown"), + "points": [xtl, ytl, xbr, ybr], + "type": "rectangle", + }) + + return results \ No newline at end of file diff --git a/serverless/pytorch/foolwood/siammask/nuclio/function.yaml b/serverless/pytorch/foolwood/siammask/nuclio/function.yaml new file mode 100644 index 00000000..efdb0ca8 --- /dev/null +++ b/serverless/pytorch/foolwood/siammask/nuclio/function.yaml @@ -0,0 +1,57 @@ +metadata: + name: pth.foolwood.siammask + namespace: cvat + annotations: + name: SiamMask + type: tracker + spec: + framework: pytorch + +spec: + description: Fast Online Object Tracking and Segmentation + runtime: "python:3.6" + handler: main:handler + eventTimeout: 30s + env: + - name: PYTHONPATH + value: /opt/nuclio/SiamMask:/opt/nuclio/SiamMask/experiments/siammask_sharp + + build: + image: cvat/pth.foolwood.siammask + baseImage: continuumio/miniconda3 + + directives: + preCopy: + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: conda create -y -n siammask python=3.6 + - kind: RUN + value: source activate siammask + - kind: RUN + value: git clone https://github.com/foolwood/SiamMask.git + - kind: RUN + value: pip install -r SiamMask/requirements.txt + - kind: RUN + value: conda install -y gcc_linux-64 + - kind: RUN + value: cd SiamMask && bash make.sh && cd - + - kind: RUN + value: wget -P SiamMask/experiments/siammask_sharp http://www.robots.ox.ac.uk/~qwang/SiamMask_DAVIS.pth + + - kind: WORKDIR + value: /opt/nuclio/pysot + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/pytorch/foolwood/siammask/nuclio/main.py b/serverless/pytorch/foolwood/siammask/nuclio/main.py new file mode 100644 index 00000000..51c3669a --- /dev/null +++ b/serverless/pytorch/foolwood/siammask/nuclio/main.py @@ -0,0 +1,27 @@ +import json +import base64 +from PIL import Image +import io +from model_handler import ModelHandler + +def init_context(context): + context.logger.info("Init context... 0%") + + # Read the DL model + model = ModelHandler() + setattr(context.user_data, 'model', model) + + context.logger.info("Init context...100%") + +def handler(context, event): + context.logger.info("Run SiamMask model") + data = event.body + buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) + shape = data.get("shape") + state = data.get("state") + image = Image.open(buf) + + results = context.user_data.model.infer(image, shape, state) + + return context.Response(body=json.dumps(results), headers={}, + content_type='application/json', status_code=200) diff --git a/serverless/pytorch/foolwood/siammask/nuclio/model_handler.py b/serverless/pytorch/foolwood/siammask/nuclio/model_handler.py new file mode 100644 index 00000000..de79c16d --- /dev/null +++ b/serverless/pytorch/foolwood/siammask/nuclio/model_handler.py @@ -0,0 +1,38 @@ +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +from tools.test import * +import os + +class ModelHandler: + def __init__(self): + # Setup device + self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + torch.backends.cudnn.benchmark = True + + base_dir = "/opt/nuclio/SiamMask/experiments/siammask_sharp" + class configPath: + config = os.path.join(base_dir, "config_davis.json") + + self.config = load_config(configPath) + from custom import Custom + siammask = Custom(anchors=self.config['anchors']) + self.siammask = load_pretrain(siammask, os.path.join(base_dir, "SiamMask_DAVIS.pth")) + self.siammask.eval().to(self.device) + + + def infer(self, image, shape, state): + if state is None: # init tracking + x, y, w, h = shape + target_pos = np.array([x + w / 2, y + h / 2]) + target_sz = np.array([w, h]) + state = siamese_init(image, target_pos, target_sz, self.siammask, + self.config['hp'], device=self.device) + else: # track + state = siamese_track(state, image, mask_enable=True, refine_enable=True, + device=self.device) + shape = state['ploygon'].flatten() + + return {"shape": shape, "state": state} + diff --git a/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml new file mode 100644 index 00000000..c58617ce --- /dev/null +++ b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml @@ -0,0 +1,132 @@ +metadata: + name: tf.faster_rcnn_inception_v2_coco + namespace: cvat + annotations: + name: Faster RCNN via Tensorflow + type: detector + framework: tensorflow + spec: | + [ + { "id": 1, "name": "person" }, + { "id": 2, "name": "bicycle" }, + { "id": 3, "name": "car" }, + { "id": 4, "name": "motorcycle" }, + { "id": 5, "name": "airplane" }, + { "id": 6, "name": "bus" }, + { "id": 7, "name": "train" }, + { "id": 8, "name": "truck" }, + { "id": 9, "name": "boat" }, + { "id":10, "name": "traffic_light" }, + { "id":11, "name": "fire_hydrant" }, + { "id":13, "name": "stop_sign" }, + { "id":14, "name": "parking_meter" }, + { "id":15, "name": "bench" }, + { "id":16, "name": "bird" }, + { "id":17, "name": "cat" }, + { "id":18, "name": "dog" }, + { "id":19, "name": "horse" }, + { "id":20, "name": "sheep" }, + { "id":21, "name": "cow" }, + { "id":22, "name": "elephant" }, + { "id":23, "name": "bear" }, + { "id":24, "name": "zebra" }, + { "id":25, "name": "giraffe" }, + { "id":27, "name": "backpack" }, + { "id":28, "name": "umbrella" }, + { "id":31, "name": "handbag" }, + { "id":32, "name": "tie" }, + { "id":33, "name": "suitcase" }, + { "id":34, "name": "frisbee" }, + { "id":35, "name": "skis" }, + { "id":36, "name": "snowboard" }, + { "id":37, "name": "sports_ball" }, + { "id":38, "name": "kite" }, + { "id":39, "name": "baseball_bat" }, + { "id":40, "name": "baseball_glove" }, + { "id":41, "name": "skateboard" }, + { "id":42, "name": "surfboard" }, + { "id":43, "name": "tennis_racket" }, + { "id":44, "name": "bottle" }, + { "id":46, "name": "wine_glass" }, + { "id":47, "name": "cup" }, + { "id":48, "name": "fork" }, + { "id":49, "name": "knife" }, + { "id":50, "name": "spoon" }, + { "id":51, "name": "bowl" }, + { "id":52, "name": "banana" }, + { "id":53, "name": "apple" }, + { "id":54, "name": "sandwich" }, + { "id":55, "name": "orange" }, + { "id":56, "name": "broccoli" }, + { "id":57, "name": "carrot" }, + { "id":58, "name": "hot_dog" }, + { "id":59, "name": "pizza" }, + { "id":60, "name": "donut" }, + { "id":61, "name": "cake" }, + { "id":62, "name": "chair" }, + { "id":63, "name": "couch" }, + { "id":64, "name": "potted_plant" }, + { "id":65, "name": "bed" }, + { "id":67, "name": "dining_table" }, + { "id":70, "name": "toilet" }, + { "id":72, "name": "tv" }, + { "id":73, "name": "laptop" }, + { "id":74, "name": "mouse" }, + { "id":75, "name": "remote" }, + { "id":76, "name": "keyboard" }, + { "id":77, "name": "cell_phone" }, + { "id":78, "name": "microwave" }, + { "id":79, "name": "oven" }, + { "id":80, "name": "toaster" }, + { "id":81, "name": "sink" }, + { "id":83, "name": "refrigerator" }, + { "id":84, "name": "book" }, + { "id":85, "name": "clock" }, + { "id":86, "name": "vase" }, + { "id":87, "name": "scissors" }, + { "id":88, "name": "teddy_bear" }, + { "id":89, "name": "hair_drier" }, + { "id":90, "name": "toothbrush" } + ] + +spec: + description: Faster RCNN from Tensorflow Object Detection API + runtime: "python:3.6" + handler: main:handler + eventTimeout: 30s + + build: + image: cvat/tf.faster_rcnn_inception_v2_coco + baseImage: tensorflow/tensorflow:2.1.1 + + directives: + preCopy: + - kind: RUN + value: apt install curl + - kind: WORKDIR + value: /opt/nuclio + + postCopy: + - kind: RUN + value: curl -O http://download.tensorflow.org/models/object_detection/faster_rcnn_inception_v2_coco_2018_01_28.tar.gz + - kind: RUN + value: tar -xzf faster_rcnn_inception_v2_coco_2018_01_28.tar.gz && rm faster_rcnn_inception_v2_coco_2018_01_28.tar.gz + - kind: RUN + value: ln -s faster_rcnn_inception_v2_coco_2018_01_28 faster_rcnn + - kind: RUN + value: pip install pillow pyyaml + + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/main.py b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/main.py new file mode 100644 index 00000000..8bcad27c --- /dev/null +++ b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/main.py @@ -0,0 +1,48 @@ +import json +import base64 +import io +from PIL import Image +import yaml +from model_loader import ModelLoader + + +def init_context(context): + context.logger.info("Init context... 0%") + model_path = "/opt/nuclio/faster_rcnn/frozen_inference_graph.pb" + model_handler = ModelLoader(model_path) + setattr(context.user_data, 'model_handler', model_handler) + functionconfig = yaml.safe_load(open("/opt/nuclio/function.yaml")) + labels_spec = functionconfig['metadata']['annotations']['spec'] + labels = {item['id']: item['name'] for item in json.loads(labels_spec)} + setattr(context.user_data, "labels", labels) + context.logger.info("Init context...100%") + +def handler(context, event): + context.logger.info("Run faster_rcnn_inception_v2_coco model") + data = event.body + buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) + threshold = float(data.get("threshold", 0.5)) + image = Image.open(buf) + + (boxes, scores, classes, num_detections) = context.user_data.model_handler.infer(image) + + results = [] + for i in range(int(num_detections[0])): + obj_class = int(classes[0][i]) + obj_score = scores[0][i] + obj_label = context.user_data.labels.get(obj_class, "unknown") + if obj_score >= threshold: + xtl = boxes[0][i][1] * image.width + ytl = boxes[0][i][0] * image.height + xbr = boxes[0][i][3] * image.width + ybr = boxes[0][i][2] * image.height + + results.append({ + "confidence": str(obj_score), + "label": obj_label, + "points": [xtl, ytl, xbr, ybr], + "type": "rectangle", + }) + + return context.Response(body=json.dumps(results), headers={}, + content_type='application/json', status_code=200) diff --git a/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/model_loader.py b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/model_loader.py new file mode 100644 index 00000000..8158eee3 --- /dev/null +++ b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/model_loader.py @@ -0,0 +1,43 @@ + +import numpy as np +from PIL import Image +import tensorflow.compat.v1 as tf +tf.disable_v2_behavior() + +class ModelLoader: + def __init__(self, model_path): + self.session = None + + detection_graph = tf.Graph() + with detection_graph.as_default(): + od_graph_def = tf.GraphDef() + with tf.gfile.GFile(model_path, 'rb') as fid: + serialized_graph = fid.read() + od_graph_def.ParseFromString(serialized_graph) + tf.import_graph_def(od_graph_def, name='') + + config = tf.ConfigProto() + config.gpu_options.allow_growth = True + self.session = tf.Session(graph=detection_graph, config=config) + + self.image_tensor = detection_graph.get_tensor_by_name('image_tensor:0') + self.boxes = detection_graph.get_tensor_by_name('detection_boxes:0') + self.scores = detection_graph.get_tensor_by_name('detection_scores:0') + self.classes = detection_graph.get_tensor_by_name('detection_classes:0') + self.num_detections = detection_graph.get_tensor_by_name('num_detections:0') + + def __del__(self): + if self.session: + self.session.close() + del self.session + + def infer(self, image): + width, height = image.size + if width > 1920 or height > 1080: + image = image.resize((width // 2, height // 2), Image.ANTIALIAS) + image_np = np.array(image.getdata()).reshape((image.height, image.width, 3)).astype(np.uint8) + image_np = np.expand_dims(image_np, axis=0) + + return self.session.run( + [self.boxes, self.scores, self.classes, self.num_detections], + feed_dict={self.image_tensor: image_np}) diff --git a/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml b/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml new file mode 100644 index 00000000..b50868a6 --- /dev/null +++ b/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml @@ -0,0 +1,133 @@ +metadata: + name: tf.matterport.mask_rcnn + namespace: cvat + annotations: + name: Mask RCNN via Tensorflow + type: detector + framework: tensorflow + spec: | + [ + { "id": 0, "name": "BG" }, + { "id": 1, "name": "person" }, + { "id": 2, "name": "bicycle" }, + { "id": 3, "name": "car" }, + { "id": 4, "name": "motorcycle" }, + { "id": 5, "name": "airplane" }, + { "id": 6, "name": "bus" }, + { "id": 7, "name": "train" }, + { "id": 8, "name": "truck" }, + { "id": 9, "name": "boat" }, + { "id": 10, "name": "traffic_light" }, + { "id": 11, "name": "fire_hydrant" }, + { "id": 12, "name": "stop_sign" }, + { "id": 13, "name": "parking_meter" }, + { "id": 14, "name": "bench" }, + { "id": 15, "name": "bird" }, + { "id": 16, "name": "cat" }, + { "id": 17, "name": "dog" }, + { "id": 18, "name": "horse" }, + { "id": 19, "name": "sheep" }, + { "id": 20, "name": "cow" }, + { "id": 21, "name": "elephant" }, + { "id": 22, "name": "bear" }, + { "id": 23, "name": "zebra" }, + { "id": 24, "name": "giraffe" }, + { "id": 25, "name": "backpack" }, + { "id": 26, "name": "umbrella" }, + { "id": 27, "name": "handbag" }, + { "id": 28, "name": "tie" }, + { "id": 29, "name": "suitcase" }, + { "id": 30, "name": "frisbee" }, + { "id": 31, "name": "skis" }, + { "id": 32, "name": "snowboard" }, + { "id": 33, "name": "sports_ball" }, + { "id": 34, "name": "kite" }, + { "id": 35, "name": "baseball_bat" }, + { "id": 36, "name": "baseball_glove" }, + { "id": 37, "name": "skateboard" }, + { "id": 38, "name": "surfboard" }, + { "id": 39, "name": "tennis_racket" }, + { "id": 40, "name": "bottle" }, + { "id": 41, "name": "wine_glass" }, + { "id": 42, "name": "cup" }, + { "id": 43, "name": "fork" }, + { "id": 44, "name": "knife" }, + { "id": 45, "name": "spoon" }, + { "id": 46, "name": "bowl" }, + { "id": 47, "name": "banana" }, + { "id": 48, "name": "apple" }, + { "id": 49, "name": "sandwich" }, + { "id": 50, "name": "orange" }, + { "id": 51, "name": "broccoli" }, + { "id": 52, "name": "carrot" }, + { "id": 53, "name": "hot_dog" }, + { "id": 54, "name": "pizza" }, + { "id": 55, "name": "donut" }, + { "id": 56, "name": "cake" }, + { "id": 57, "name": "chair" }, + { "id": 58, "name": "couch" }, + { "id": 59, "name": "potted_plant" }, + { "id": 60, "name": "bed" }, + { "id": 61, "name": "dining_table" }, + { "id": 62, "name": "toilet" }, + { "id": 63, "name": "tv" }, + { "id": 64, "name": "laptop" }, + { "id": 65, "name": "mouse" }, + { "id": 66, "name": "remote" }, + { "id": 67, "name": "keyboard" }, + { "id": 68, "name": "cell_phone" }, + { "id": 69, "name": "microwave" }, + { "id": 70, "name": "oven" }, + { "id": 71, "name": "toaster" }, + { "id": 72, "name": "sink" }, + { "id": 73, "name": "refrigerator" }, + { "id": 74, "name": "book" }, + { "id": 75, "name": "clock" }, + { "id": 76, "name": "vase" }, + { "id": 77, "name": "scissors" }, + { "id": 78, "name": "teddy_bear" }, + { "id": 79, "name": "hair_drier" }, + { "id": 80, "name": "toothbrush" } + ] + +spec: + description: | + An implementation of Mask RCNN on Python 3, Keras, and TensorFlow. + + runtime: "python:3.6" + handler: main:handler + eventTimeout: 30s + env: + - name: MASK_RCNN_DIR + value: /opt/nuclio/Mask_RCNN + build: + image: cvat/tf.matterport.mask_rcnn + baseImage: tensorflow/tensorflow:2.1.0-py3 + directives: + postCopy: + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: apt update && apt install --no-install-recommends -y git curl libsm6 libxext6 libxrender-dev + - kind: RUN + value: git clone https://github.com/matterport/Mask_RCNN.git + - kind: RUN + value: curl -L https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5 -o Mask_RCNN/mask_rcnn_coco.h5 + - kind: RUN + value: pip3 install -r Mask_RCNN/requirements.txt + - kind: RUN + value: pip3 install pycocotools tensorflow==1.13.1 keras==2.1.0 pillow pyyaml + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/tensorflow/matterport/mask_rcnn/nuclio/main.py b/serverless/tensorflow/matterport/mask_rcnn/nuclio/main.py new file mode 100644 index 00000000..95816dd4 --- /dev/null +++ b/serverless/tensorflow/matterport/mask_rcnn/nuclio/main.py @@ -0,0 +1,32 @@ +import json +import base64 +from PIL import Image +import io +from model_loader import ModelLoader +import numpy as np +import yaml + + +def init_context(context): + context.logger.info("Init context... 0%") + + functionconfig = yaml.safe_load(open("/opt/nuclio/function.yaml")) + labels_spec = functionconfig['metadata']['annotations']['spec'] + labels = {item['id']: item['name'] for item in json.loads(labels_spec)} + + model_handler = ModelLoader(labels) + setattr(context.user_data, 'model_handler', model_handler) + + context.logger.info("Init context...100%") + +def handler(context, event): + context.logger.info("Run tf.matterport.mask_rcnn model") + data = event.body + buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) + threshold = float(data.get("threshold", 0.2)) + image = Image.open(buf) + + results = context.user_data.model_handler.infer(np.array(image), threshold) + + return context.Response(body=json.dumps(results), headers={}, + content_type='application/json', status_code=200) \ No newline at end of file diff --git a/serverless/tensorflow/matterport/mask_rcnn/nuclio/model_loader.py b/serverless/tensorflow/matterport/mask_rcnn/nuclio/model_loader.py new file mode 100644 index 00000000..b210338a --- /dev/null +++ b/serverless/tensorflow/matterport/mask_rcnn/nuclio/model_loader.py @@ -0,0 +1,79 @@ +# Copyright (C) 2018-2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +import os +import numpy as np +import sys +from skimage.measure import find_contours, approximate_polygon + +# workaround for tf.placeholder() is not compatible with eager execution +# https://github.com/tensorflow/tensorflow/issues/18165 +import tensorflow as tf +tf.compat.v1.disable_eager_execution() +#import tensorflow.compat.v1 as tf +# tf.disable_v2_behavior() + +# The directory should contain a clone of +# https://github.com/matterport/Mask_RCNN repository and +# downloaded mask_rcnn_coco.h5 model. +MASK_RCNN_DIR = os.environ.get('MASK_RCNN_DIR') +if MASK_RCNN_DIR: + sys.path.append(MASK_RCNN_DIR) # To find local version of the library + sys.path.append(os.path.join(MASK_RCNN_DIR, 'samples/coco')) + +from mrcnn import model as modellib +import coco + +class ModelLoader: + def __init__(self, labels): + COCO_MODEL_PATH = os.path.join(MASK_RCNN_DIR, "mask_rcnn_coco.h5") + if COCO_MODEL_PATH is None: + raise OSError('Model path env not found in the system.') + + class InferenceConfig(coco.CocoConfig): + # Set batch size to 1 since we'll be running inference on + # one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU + GPU_COUNT = 1 + IMAGES_PER_GPU = 1 + + # Print config details + self.config = InferenceConfig() + self.config.display() + + self.model = modellib.MaskRCNN(mode="inference", + config=self.config, model_dir=MASK_RCNN_DIR) + self.model.load_weights(COCO_MODEL_PATH, by_name=True) + self.labels = labels + + def infer(self, image, threshold): + output = self.model.detect([image], verbose=1)[0] + + results = [] + MASK_THRESHOLD = 0.5 + for i in range(len(output["rois"])): + score = output["scores"][i] + class_id = output["class_ids"][i] + mask = output["masks"][:,:,i] + if score >= threshold: + mask = mask.astype(np.uint8) + contours = find_contours(mask, MASK_THRESHOLD) + # only one contour exist in our case + contour = contours[0] + contour = np.flip(contour, axis=1) + # Approximate the contour and reduce the number of points + contour = approximate_polygon(contour, tolerance=2.5) + if len(contour) < 3: + continue + label = self.labels[class_id] + + results.append({ + "confidence": str(score), + "label": label, + "points": contour.ravel().tolist(), + "type": "polygon", + }) + + return results + + diff --git a/utils/README.md b/utils/README.md index a768eedf..48b87c96 100644 --- a/utils/README.md +++ b/utils/README.md @@ -3,6 +3,6 @@ ## Description -This folder contains some useful utilities for Computer Vision Annotation Tool (CVAT). To read about a certain utility please choose a link: - [Auto Annotation Runner](auto_annotation/README.md) +This folder contains some useful utilities for Computer Vision Annotation Tool (CVAT). +To read about a certain utility please choose a link: - [Command line interface for working with CVAT tasks](cli/README.md) diff --git a/utils/auto_annotation/README.md b/utils/auto_annotation/README.md deleted file mode 100644 index 4bc64654..00000000 --- a/utils/auto_annotation/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# Auto Annotation Runner - -A small command line program to test and run AutoAnnotation Scripts. - -## Instructions - -There are two modes to run this script in. If you already have a model uploaded into the server, and you're having -issues with running it in production, you can pass in the model name and a task id that you want to test against. - -```shell -# Note that this module can be found in cvat/utils/auto_annotation/run_model.py -$ python /path/to/run_model.py --model-name mymodel --task-id 4 -``` - -If you're running in docker, this can be useful way to debug your model. - -``` shell -$ docker exec -it cvat bash -ic 'python3 ~/cvat/apps/auto_annotation/run_model.py --model-name my-model --task-id 4 -``` - -If you are developing an auto annotation model or you can't get something uploaded into the server, -then you'll need to specify the individual inputs. - -```shell -# Note that this module can be found in cvat/utils/auto_annotation/run_model.py -$ python path/to/run_model.py --py /path/to/python/interp.py \ - --xml /path/to/xml/file.xml \ - --bin /path/to/bin/file.bin \ - --json /path/to/json/mapping/mapping.json -``` - -Some programs need to run unrestricted or as an administer. Use the `--unrestriced` flag to simulate. - -You can pass image files in to fully simulate your findings. Images are passed in as a list - -```shell -$ python /path/to/run_model.py --py /path/to/python/interp.py \ - --xml /path/to/xml/file.xml \ - --bin /path/to/bin/file.bin \ - --json /path/to/json/mapping/mapping.json \ - --image-files /path/to/img.jpg /path2/to/img2.png /path/to/img3.jpg -``` - -Additionally, it's sometimes useful to visualize your images. -Use the `--show-images` flag to have each image with the annotations pop up. - -```shell -$ python /path/to/run_model.py --py /path/to/python/interp.py \ - --xml /path/to/xml/file.xml \ - --bin /path/to/bin/file.bin \ - --json /path/to/json/mapping/mapping.json \ - --image-files /path/to/img.jpg /path2/to/img2.png /path/to/img3.jpg \ - --show-images -``` - -If you'd like to see the labels printed on the image, use the `--show-labels` flag - -```shell -$ python /path/to/run_model.py --py /path/to/python/interp.py \ - --xml /path/to/xml/file.xml \ - --bin /path/to/bin/file.bin \ - --json /path/to/json/mapping/mapping.json \ - --image-files /path/to/img.jpg /path2/to/img2.png /path/to/img3.jpg \ - --show-images \ - --show-labels -``` - -There's a command that let's you scan quickly by setting the length of time (in milliseconds) to display each image. -Use the `--show-image-delay` flag and set the appropriate time. -In this example, 2000 milliseconds is 2 seconds for each image. - -```shell -# Display each image in a window for 2 seconds -$ python /path/to/run_model.py --py /path/to/python/interp.py \ - --xml /path/to/xml/file.xml \ - --bin /path/to/bin/file.bin \ - --json /path/to/json/mapping/mapping.json \ - --image-files /path/to/img.jpg /path2/to/img2.png /path/to/img3.jpg \ - --show-images \ - --show-image-delay 2000 -``` - -Visualization isn't always enough. -The CVAT has a serialization step that can throw errors on model upload even after successful visualization. -You must install the necessary packages installed, but then you can add the `--serialize` command to ensure that your -results will serialize correctly. - -```shell -$ python /path/to/run_model.py --py /path/to/python/interp.py \ - --xml /path/to/xml/file.xml \ - --bin /path/to/bin/file.bin \ - --json /path/to/json/mapping/mapping.json \ - --image-files /path/to/img.jpg /path2/to/img2.png /path/to/img3.jpg \ - --serialize -``` diff --git a/utils/auto_annotation/run_model.py b/utils/auto_annotation/run_model.py deleted file mode 100644 index 9df63528..00000000 --- a/utils/auto_annotation/run_model.py +++ /dev/null @@ -1,263 +0,0 @@ -import os -import sys -import json -import argparse -import random -import logging -import fnmatch -from operator import xor - -import numpy as np -import cv2 - -work_dir = os.path.dirname(os.path.abspath(__file__)) -cvat_dir = os.path.join(work_dir, '..', '..') - -sys.path.insert(0, cvat_dir) - -from cvat.apps.auto_annotation.inference import run_inference_engine_annotation - - -def _get_kwargs(): - parser = argparse.ArgumentParser() - parser.add_argument('--py', help='Path to the python interpt file') - parser.add_argument('--xml', help='Path to the xml file') - parser.add_argument('--bin', help='Path to the bin file') - parser.add_argument('--json', help='Path to the JSON mapping file') - - parser.add_argument('--model-name', help='Name of the model in the Model Manager') - parser.add_argument('--task-id', type=int, help='ID task used to test the model') - - parser.add_argument('--restricted', dest='restricted', action='store_true') - parser.add_argument('--unrestricted', dest='restricted', action='store_false') - parser.add_argument('--image-files', nargs='*', help='Paths to image files you want to test') - - parser.add_argument('--show-images', action='store_true', help='Show the results of the annotation in a window') - parser.add_argument('--show-image-delay', default=0, type=int, help='Displays the images for a set duration in milliseconds, default is until a key is pressed') - parser.add_argument('--serialize', default=False, action='store_true', help='Try to serialize the result') - parser.add_argument('--show-labels', action='store_true', help='Show the labels on the window') - - return vars(parser.parse_args()) - -def _init_django(settings): - import django - os.environ['DJANGO_SETTINGS_MODULE'] = settings - django.setup() - -def random_color(): - rgbl=[255,0,0] - random.shuffle(rgbl) - return tuple(rgbl) - - -def pairwise(iterable): - result = [] - for i in range(0, len(iterable) - 1, 2): - result.append((iterable[i], iterable[i+1])) - return np.array(result, dtype=np.int32) - -def find_min_y(array): - min_ = sys.maxsize - index = None - for i, pair in enumerate(array): - if pair[1] < min_: - min_ = pair[1] - index = i - - return array[index] - -def _get_docker_files(model_name: str, task_id: int): - _init_django('cvat.settings.development') - - from cvat.apps.auto_annotation.models import AnnotationModel - from cvat.apps.engine.models import Task as TaskModel - - task = TaskModel(pk=task_id) - model = AnnotationModel.objects.get(name=model_name) - - images_dir = task.data.get_data_dirname() - - py_file = model.interpretation_file.name - mapping_file = model.labelmap_file.name - xml_file = model.model_file.name - bin_file = model.weights_file.name - - image_files = [] - images_dir = os.path.abspath(images_dir) - for root, _, filenames in os.walk(images_dir): - for filename in fnmatch.filter(filenames, '*.jpg'): - image_files.append(os.path.join(root, filename)) - - return py_file, mapping_file, bin_file, xml_file, image_files - - -def main(): - kwargs = _get_kwargs() - - py_file = kwargs.get('py') - bin_file = kwargs.get('bin') - mapping_file = os.path.abspath(kwargs.get('json')) - xml_file = kwargs.get('xml') - - model_name = kwargs.get('model_name') - task_id = kwargs.get('task_id') - - is_docker = model_name and task_id - - # xor is `exclusive or`. English is: if one or the other but not both - if xor(bool(model_name), bool(task_id)): - logging.critical('Must provide both `--model-name` and `--task-id` together!') - return - - if is_docker: - files = _get_docker_files(model_name, task_id) - py_file = files[0] - mapping_file = files[1] - bin_file = files[2] - xml_file = files[3] - image_files = files[4] - else: - return_ = False - if not py_file: - logging.critical('Must provide --py file!') - return_ = True - if not bin_file: - logging.critical('Must provide --bin file!') - return_ = True - if not xml_file: - logging.critical('Must provide --xml file!') - return_ = True - if not mapping_file: - logging.critical('Must provide --json file!') - return_ = True - - if return_: - return - - if not os.path.isfile(py_file): - logging.critical('Py file not found! Check the path') - return - - if not os.path.isfile(bin_file): - logging.critical('Bin file is not found! Check path!') - return - - if not os.path.isfile(xml_file): - logging.critical('XML File not found! Check path!') - return - - if not os.path.isfile(mapping_file): - logging.critical('JSON file is not found! Check path!') - return - - with open(mapping_file) as json_file: - try: - mapping = json.load(json_file) - except json.decoder.JSONDecodeError: - logging.critical('JSON file not able to be parsed! Check file') - return - - try: - mapping = mapping['label_map'] - except KeyError: - logging.critical("JSON Mapping file must contain key `label_map`!") - logging.critical("Exiting") - return - - mapping = {int(k): v for k, v in mapping.items()} - - restricted = kwargs['restricted'] - - if not is_docker: - image_files = kwargs.get('image_files') - - if image_files: - image_data = [cv2.imread(f) for f in image_files] - else: - test_image = np.ones((1024, 1980, 3), np.uint8) * 255 - image_data = [test_image,] - attribute_spec = {} - - results = run_inference_engine_annotation(image_data, - xml_file, - bin_file, - mapping, - attribute_spec, - py_file, - restricted=restricted) - - - logging.warning('Inference didn\'t have any errors.') - show_images = kwargs.get('show_images', False) - - if show_images: - if image_files is None: - logging.critical("Warning, no images provided!") - logging.critical('Exiting without presenting results') - return - - if not results['shapes']: - logging.warning(str(results)) - logging.critical("No objects detected!") - return - - show_image_delay = kwargs['show_image_delay'] - show_labels = kwargs.get('show_labels') - - for index, data in enumerate(image_data): - for detection in results['shapes']: - if not detection['frame'] == index: - continue - points = detection['points'] - label_str = detection['label_id'] - - # Cv2 doesn't like floats for drawing - points = [int(p) for p in points] - color = random_color() - - if detection['type'] == 'rectangle': - cv2.rectangle(data, (points[0], points[1]), (points[2], points[3]), color, 3) - - if show_labels: - cv2.putText(data, label_str, (points[0], points[1] - 7), cv2.FONT_HERSHEY_COMPLEX, 0.6, color, 1) - - elif detection['type'] in ('polygon', 'polyline'): - # polylines is picky about datatypes - points = pairwise(points) - cv2.polylines(data, [points], 1, color) - - if show_labels: - min_point = find_min_y(points) - cv2.putText(data, label_str, (min_point[0], min_point[1] - 7), cv2.FONT_HERSHEY_COMPLEX, 0.6, color, 1) - - cv2.imshow(str(index), data) - cv2.waitKey(show_image_delay) - cv2.destroyWindow(str(index)) - - if kwargs['serialize']: - _init_django('cvat.settings.production') - - from cvat.apps.engine.serializers import LabeledDataSerializer - - # NOTE: We're actually using `run_inference_engine_annotation` - # incorrectly here. The `mapping` dict is supposed to be a mapping - # of integers -> integers and represents the transition from model - # integers to the labels in the database. We're using a mapping of - # integers -> strings. For testing purposes, this shortcut is fine. - # We just want to make sure everything works. Until, that is.... - # we want to test using the label serializer. Then we have to transition - # back to integers, otherwise the serializer complains about have a string - # where an integer is expected. We'll just brute force that. - - for shape in results['shapes']: - # Change the english label to an integer for serialization validation - shape['label_id'] = 1 - - serializer = LabeledDataSerializer(data=results) - - if not serializer.is_valid(): - logging.critical('Data unable to be serialized correctly!') - serializer.is_valid(raise_exception=True) - -if __name__ == '__main__': - main() diff --git a/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0001/mappings.json b/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0001/mappings.json deleted file mode 100644 index f6a0aa87..00000000 --- a/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0001/mappings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "label_map": { - "1": "text" - } -} diff --git a/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0001/pixel_link_mobilenet_v2.py b/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0001/pixel_link_mobilenet_v2.py deleted file mode 100644 index 77297cab..00000000 --- a/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0001/pixel_link_mobilenet_v2.py +++ /dev/null @@ -1,192 +0,0 @@ -import cv2 -import numpy as np - - -class PixelLinkDecoder(): - def __init__(self): - four_neighbours = False - if four_neighbours: - self._get_neighbours = self._get_neighbours_4 - else: - self._get_neighbours = self._get_neighbours_8 - self.pixel_conf_threshold = 0.8 - self.link_conf_threshold = 0.8 - - def decode(self, height, width, detections: dict): - self.image_height = height - self.image_width = width - self.pixel_scores = self._set_pixel_scores(detections['pixel_cls/add_2']) - self.link_scores = self._set_link_scores(detections['pixel_link/add_2']) - - self.pixel_mask = self.pixel_scores >= self.pixel_conf_threshold - self.link_mask = self.link_scores >= self.link_conf_threshold - self.points = list(zip(*np.where(self.pixel_mask))) - self.h, self.w = np.shape(self.pixel_mask) - self.group_mask = dict.fromkeys(self.points, -1) - self.bboxes = None - self.root_map = None - self.mask = None - - self._decode() - - def _softmax(self, x, axis=None): - return np.exp(x - self._logsumexp(x, axis=axis, keepdims=True)) - - def _logsumexp(self, a, axis=None, b=None, keepdims=False, return_sign=False): - if b is not None: - a, b = np.broadcast_arrays(a, b) - if np.any(b == 0): - a = a + 0. # promote to at least float - a[b == 0] = -np.inf - - a_max = np.amax(a, axis=axis, keepdims=True) - - if a_max.ndim > 0: - a_max[~np.isfinite(a_max)] = 0 - elif not np.isfinite(a_max): - a_max = 0 - - if b is not None: - b = np.asarray(b) - tmp = b * np.exp(a - a_max) - else: - tmp = np.exp(a - a_max) - - # suppress warnings about log of zero - with np.errstate(divide='ignore'): - s = np.sum(tmp, axis=axis, keepdims=keepdims) - if return_sign: - sgn = np.sign(s) - s *= sgn # /= makes more sense but we need zero -> zero - out = np.log(s) - - if not keepdims: - a_max = np.squeeze(a_max, axis=axis) - out += a_max - - if return_sign: - return out, sgn - else: - return out - - def _set_pixel_scores(self, pixel_scores): - "get softmaxed properly shaped pixel scores" - tmp = np.transpose(pixel_scores, (0, 2, 3, 1)) - return self._softmax(tmp, axis=-1)[0, :, :, 1] - - def _set_link_scores(self, link_scores): - "get softmaxed properly shaped links scores" - tmp = np.transpose(link_scores, (0, 2, 3, 1)) - tmp_reshaped = tmp.reshape(tmp.shape[:-1] + (8, 2)) - return self._softmax(tmp_reshaped, axis=-1)[0, :, :, :, 1] - - def _find_root(self, point): - root = point - update_parent = False - tmp = self.group_mask[root] - while tmp is not -1: - root = tmp - tmp = self.group_mask[root] - update_parent = True - if update_parent: - self.group_mask[point] = root - return root - - def _join(self, p1, p2): - root1 = self._find_root(p1) - root2 = self._find_root(p2) - if root1 != root2: - self.group_mask[root2] = root1 - - def _get_index(self, root): - if root not in self.root_map: - self.root_map[root] = len(self.root_map) + 1 - return self.root_map[root] - - def _get_all(self): - self.root_map = {} - self.mask = np.zeros_like(self.pixel_mask, dtype=np.int32) - - for point in self.points: - point_root = self._find_root(point) - bbox_idx = self._get_index(point_root) - self.mask[point] = bbox_idx - - def _get_neighbours_8(self, x, y): - w, h = self.w, self.h - tmp = [(0, x - 1, y - 1), (1, x, y - 1), - (2, x + 1, y - 1), (3, x - 1, y), - (4, x + 1, y), (5, x - 1, y + 1), - (6, x, y + 1), (7, x + 1, y + 1)] - - return [i for i in tmp if i[1] >= 0 and i[1] < w and i[2] >= 0 and i[2] < h] - - def _get_neighbours_4(self, x, y): - w, h = self.w, self.h - tmp = [(1, x, y - 1), - (3, x - 1, y), - (4, x + 1, y), - (6, x, y + 1)] - - return [i for i in tmp if i[1] >= 0 and i[1] < w and i[2] >= 0 and i[2] < h] - - def _mask_to_bboxes(self, min_area=300, min_height=10): - self.bboxes = [] - max_bbox_idx = self.mask.max() - mask_tmp = cv2.resize(self.mask, (self.image_width, self.image_height), interpolation=cv2.INTER_NEAREST) - - for bbox_idx in range(1, max_bbox_idx + 1): - bbox_mask = mask_tmp == bbox_idx - cnts, _ = cv2.findContours(bbox_mask.astype(np.uint8), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) - if len(cnts) == 0: - continue - cnt = cnts[0] - rect, w, h = self._min_area_rect(cnt) - if min(w, h) < min_height: - continue - if w * h < min_area: - continue - self.bboxes.append(self._order_points(rect)) - - def _min_area_rect(self, cnt): - rect = cv2.minAreaRect(cnt) - w, h = rect[1] - box = cv2.boxPoints(rect) - box = np.int0(box) - return box, w, h - - def _order_points(self, rect): - """ (x, y) - Order: TL, TR, BR, BL - """ - tmp = np.zeros_like(rect) - sums = rect.sum(axis=1) - tmp[0] = rect[np.argmin(sums)] - tmp[2] = rect[np.argmax(sums)] - diff = np.diff(rect, axis=1) - tmp[1] = rect[np.argmin(diff)] - tmp[3] = rect[np.argmax(diff)] - return tmp - - def _decode(self): - for point in self.points: - y, x = point - neighbours = self._get_neighbours(x, y) - for n_idx, nx, ny in neighbours: - link_value = self.link_mask[y, x, n_idx] - pixel_cls = self.pixel_mask[ny, nx] - if link_value and pixel_cls: - self._join(point, (ny, nx)) - - self._get_all() - self._mask_to_bboxes() - - -label = 1 -pcd = PixelLinkDecoder() -for detection in detections: - frame = detection['frame_id'] - pcd.decode(detection['frame_height'], detection['frame_width'], detection['detections']) - for box in pcd.bboxes: - box = [[int(b[0]), int(b[1])] for b in box] - results.add_polygon(box, label, frame) diff --git a/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0004/mappings.json b/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0004/mappings.json deleted file mode 100644 index f6a0aa87..00000000 --- a/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/0004/mappings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "label_map": { - "1": "text" - } -} diff --git a/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/README.md b/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/README.md deleted file mode 100644 index c7bac387..00000000 --- a/utils/open_model_zoo/Retail/object_detection/text/pixel_link_mobilenet_v2/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Pixel Link - -* Model for the Detecting Scene Text vai Instance Segmentation -* Download using the `intel_model_zoo` using `$./downloader.py text-detection-0002` -* See [this Arxiv](https://arxiv.org/abs/1801.01315) link for the technical details diff --git a/utils/open_model_zoo/Transportation/semantic-segmentation-adas/interp.py b/utils/open_model_zoo/Transportation/semantic-segmentation-adas/interp.py deleted file mode 100644 index 58a87fa3..00000000 --- a/utils/open_model_zoo/Transportation/semantic-segmentation-adas/interp.py +++ /dev/null @@ -1,31 +0,0 @@ -import numpy as np -from skimage.measure import approximate_polygon, find_contours - -import cv2 - - -for frame_results in detections: - frame_height = frame_results['frame_height'] - frame_width = frame_results['frame_width'] - frame_number = frame_results['frame_id'] - detection = frame_results['detections'] - detection = detection[0, 0, :, :] - width, height = detection.shape - - for i in range(21): - zero = np.zeros((width,height),dtype=np.uint8) - - f = float(i) - zero = ((detection == f) * 255).astype(np.float32) - zero = cv2.resize(zero, dsize=(frame_width, frame_height), interpolation=cv2.INTER_CUBIC) - - contours = find_contours(zero, 0.8) - - for contour in contours: - contour = np.flip(contour, axis=1) - contour = approximate_polygon(contour, tolerance=2.5) - segmentation = contour.tolist() - if len(segmentation) < 3: - continue - - results.add_polygon(segmentation, i, frame_number) diff --git a/utils/open_model_zoo/Transportation/semantic-segmentation-adas/mapping.json b/utils/open_model_zoo/Transportation/semantic-segmentation-adas/mapping.json deleted file mode 100644 index cbda289d..00000000 --- a/utils/open_model_zoo/Transportation/semantic-segmentation-adas/mapping.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "label_map": { - "0": "road", - "1": "sidewalk", - "2": "building", - "3": "wall", - "4": "fence", - "5": "pole", - "6": "traffic light", - "7": "traffic sign", - "8": "vegetation", - "9": "terrain", - "10": "sky", - "11": "person", - "12": "rider", - "13": "car", - "14": "truck", - "15": "bus", - "16": "train", - "17": "motorcycle", - "18": "bicycle", - "19": "ego-vehicle", - "20": "background" - } -} diff --git a/utils/open_model_zoo/faster_rcnn_inception_v2_coco/README.md b/utils/open_model_zoo/faster_rcnn_inception_v2_coco/README.md deleted file mode 100644 index a6ede445..00000000 --- a/utils/open_model_zoo/faster_rcnn_inception_v2_coco/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Faster R-CNN with Inception v2 (https://arxiv.org/pdf/1801.04381.pdf) pre-trained on the COCO dataset - -### What is it? -* This application allows you automatically to annotate many various objects on images. -* It uses [Faster RCNN Inception Resnet v2 Atrous Coco Model](http://download.tensorflow.org/models/object_detection/faster_rcnn_inception_resnet_v2_atrous_coco_2018_01_28.tar.gz) from [tensorflow detection model zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md) -* It can work on CPU (with Tensorflow or OpenVINO) or GPU (with Tensorflow GPU). diff --git a/utils/open_model_zoo/faster_rcnn_inception_v2_coco/interp.py b/utils/open_model_zoo/faster_rcnn_inception_v2_coco/interp.py deleted file mode 100644 index f8a8a602..00000000 --- a/utils/open_model_zoo/faster_rcnn_inception_v2_coco/interp.py +++ /dev/null @@ -1,19 +0,0 @@ -threshold = .5 - -for detection in detections: - frame_number = detection['frame_id'] - height = detection['frame_height'] - width = detection['frame_width'] - detection = detection['detections'] - - prediction = detection[0][0] - for obj in prediction: - obj_class = int(obj[1]) - obj_value = obj[2] - if obj_value >= threshold: - x = obj[3] * width - y = obj[4] * height - right = obj[5] * width - bottom = obj[6] * height - - results.add_box(x, y, right, bottom, obj_class, frame_number) diff --git a/utils/open_model_zoo/faster_rcnn_inception_v2_coco/mapping.json b/utils/open_model_zoo/faster_rcnn_inception_v2_coco/mapping.json deleted file mode 100644 index 3efdb307..00000000 --- a/utils/open_model_zoo/faster_rcnn_inception_v2_coco/mapping.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "label_map": { - "1": "person", - "2": "bicycle", - "3": "car", - "4": "motorcycle", - "5": "airplane", - "6": "bus", - "7": "train", - "8": "truck", - "9": "boat", - "10": "traffic_light", - "11": "fire_hydrant", - "13": "stop_sign", - "14": "parking_meter", - "15": "bench", - "16": "bird", - "17": "cat", - "18": "dog", - "19": "horse", - "20": "sheep", - "21": "cow", - "22": "elephant", - "23": "bear", - "24": "zebra", - "25": "giraffe", - "27": "backpack", - "28": "umbrella", - "31": "handbag", - "32": "tie", - "33": "suitcase", - "34": "frisbee", - "35": "skis", - "36": "snowboard", - "37": "sports_ball", - "38": "kite", - "39": "baseball_bat", - "40": "baseball_glove", - "41": "skateboard", - "42": "surfboard", - "43": "tennis_racket", - "44": "bottle", - "46": "wine_glass", - "47": "cup", - "48": "fork", - "49": "knife", - "50": "spoon", - "51": "bowl", - "52": "banana", - "53": "apple", - "54": "sandwich", - "55": "orange", - "56": "broccoli", - "57": "carrot", - "58": "hot_dog", - "59": "pizza", - "60": "donut", - "61": "cake", - "62": "chair", - "63": "couch", - "64": "potted_plant", - "65": "bed", - "67": "dining_table", - "70": "toilet", - "72": "tv", - "73": "laptop", - "74": "mouse", - "75": "remote", - "76": "keyboard", - "77": "cell_phone", - "78": "microwave", - "79": "oven", - "80": "toaster", - "81": "sink", - "83": "refrigerator", - "84": "book", - "85": "clock", - "86": "vase", - "87": "scissors", - "88": "teddy_bear", - "89": "hair_drier", - "90": "toothbrush" - } -} diff --git a/utils/open_model_zoo/mask_rcnn_inception_resnet_v2_atrous_coco/README.md b/utils/open_model_zoo/mask_rcnn_inception_resnet_v2_atrous_coco/README.md deleted file mode 100644 index be7a8212..00000000 --- a/utils/open_model_zoo/mask_rcnn_inception_resnet_v2_atrous_coco/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# mask_rcnn_inception_resnet_v2_atrous_coco - -## Use Case and High-Level Description - -Mask R-CNN Inception Resnet V2 Atrous is trained on COCO dataset and used for object instance segmentation. -For details, see a [paper](https://arxiv.org/pdf/1703.06870.pdf). - -## Specification - -| Metric | Value | -|---------------------------------|-------------------------------------------| -| Type | Instance segmentation | -| GFlops | 675.314 | -| MParams | 92.368 | -| Source framework | TensorFlow\* | - -## Legal Information - -[https://raw.githubusercontent.com/tensorflow/models/master/LICENSE]() - -## OpenVINO Conversion Notes - -In order to convert the code into the openvino format, please see the [following link](https://docs.openvinotoolkit.org/latest/_docs_MO_DG_prepare_model_convert_model_tf_specific_Convert_Object_Detection_API_Models.html#mask_r_cnn_topologies). - -The conversion command from the command line prompt will look something like the following. - -```shell -$ python /opt/intel/openvino/deployment_tools/model_optimizer/mo_tf.py \ - --input_model /path/to/frozen_inference_graph.pb \ - --tensorflow_use_custom_operations_config /opt/intel/openvino/deployment_tools/model_optimizer/extensions/front/tf/mask_rcnn_support.json \ - --tensorflow_object_detection_api_pipeline_config /path/to/pipeline.config -``` diff --git a/utils/open_model_zoo/mask_rcnn_inception_resnet_v2_atrous_coco/interp.py b/utils/open_model_zoo/mask_rcnn_inception_resnet_v2_atrous_coco/interp.py deleted file mode 100644 index 6625a834..00000000 --- a/utils/open_model_zoo/mask_rcnn_inception_resnet_v2_atrous_coco/interp.py +++ /dev/null @@ -1,64 +0,0 @@ -import numpy as np -import cv2 -from skimage.measure import approximate_polygon, find_contours - - -MASK_THRESHOLD = .5 -PROBABILITY_THRESHOLD = 0.2 - - -# Ref: https://software.intel.com/en-us/forums/computer-vision/topic/804895 -def segm_postprocess(box: list, raw_cls_mask, im_h, im_w, threshold): - ymin, xmin, ymax, xmax = box - - width = int(abs(xmax - xmin)) - height = int(abs(ymax - ymin)) - - result = np.zeros((im_h, im_w), dtype=np.uint8) - resized_mask = cv2.resize(raw_cls_mask, dsize=(height, width), interpolation=cv2.INTER_CUBIC) - - # extract the ROI of the image - ymin = int(round(ymin)) - xmin = int(round(xmin)) - ymax = ymin + height - xmax = xmin + width - result[xmin:xmax, ymin:ymax] = (resized_mask>threshold).astype(np.uint8) * 255 - - return result - - -for detection in detections: - frame_number = detection['frame_id'] - height = detection['frame_height'] - width = detection['frame_width'] - detection = detection['detections'] - - masks = detection['masks'] - boxes = detection['reshape_do_2d'] - - for index, box in enumerate(boxes): - label = int(box[1]) - obj_value = box[2] - if obj_value >= PROBABILITY_THRESHOLD: - x = box[3] * width - y = box[4] * height - right = box[5] * width - bottom = box[6] * height - mask = masks[index][label - 1] - - mask = segm_postprocess((x, y, right, bottom), - mask, - height, - width, - MASK_THRESHOLD) - - contours = find_contours(mask, MASK_THRESHOLD) - contour = contours[0] - contour = np.flip(contour, axis=1) - contour = approximate_polygon(contour, tolerance=2.5) - segmentation = contour.tolist() - - - # NOTE: if you want to see the boxes, uncomment next line - # results.add_box(x, y, right, bottom, label, frame_number) - results.add_polygon(segmentation, label, frame_number) diff --git a/utils/open_model_zoo/mask_rcnn_inception_resnet_v2_atrous_coco/mapping.json b/utils/open_model_zoo/mask_rcnn_inception_resnet_v2_atrous_coco/mapping.json deleted file mode 100644 index 3efdb307..00000000 --- a/utils/open_model_zoo/mask_rcnn_inception_resnet_v2_atrous_coco/mapping.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "label_map": { - "1": "person", - "2": "bicycle", - "3": "car", - "4": "motorcycle", - "5": "airplane", - "6": "bus", - "7": "train", - "8": "truck", - "9": "boat", - "10": "traffic_light", - "11": "fire_hydrant", - "13": "stop_sign", - "14": "parking_meter", - "15": "bench", - "16": "bird", - "17": "cat", - "18": "dog", - "19": "horse", - "20": "sheep", - "21": "cow", - "22": "elephant", - "23": "bear", - "24": "zebra", - "25": "giraffe", - "27": "backpack", - "28": "umbrella", - "31": "handbag", - "32": "tie", - "33": "suitcase", - "34": "frisbee", - "35": "skis", - "36": "snowboard", - "37": "sports_ball", - "38": "kite", - "39": "baseball_bat", - "40": "baseball_glove", - "41": "skateboard", - "42": "surfboard", - "43": "tennis_racket", - "44": "bottle", - "46": "wine_glass", - "47": "cup", - "48": "fork", - "49": "knife", - "50": "spoon", - "51": "bowl", - "52": "banana", - "53": "apple", - "54": "sandwich", - "55": "orange", - "56": "broccoli", - "57": "carrot", - "58": "hot_dog", - "59": "pizza", - "60": "donut", - "61": "cake", - "62": "chair", - "63": "couch", - "64": "potted_plant", - "65": "bed", - "67": "dining_table", - "70": "toilet", - "72": "tv", - "73": "laptop", - "74": "mouse", - "75": "remote", - "76": "keyboard", - "77": "cell_phone", - "78": "microwave", - "79": "oven", - "80": "toaster", - "81": "sink", - "83": "refrigerator", - "84": "book", - "85": "clock", - "86": "vase", - "87": "scissors", - "88": "teddy_bear", - "89": "hair_drier", - "90": "toothbrush" - } -} diff --git a/utils/open_model_zoo/yolov3/README.md b/utils/open_model_zoo/yolov3/README.md deleted file mode 100644 index 2e47953c..00000000 --- a/utils/open_model_zoo/yolov3/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Object Detection YOLO V3 Python Demo, Async API Performance Showcase - -See [these instructions][1] for converting the yolo weights to the OpenVino format. - -As of OpenVINO 2019 R3, only tensorflow 1.13 and NetworkX 2.3. -These can be explicitly installed using the following command. - -```bash -python3 -m pip install tensorflow==1.13 networkx==2.3 -``` - - -Additionally, at the time of writing, the model optimizer required an input shape. - -``` bash -python3 mo_tf.py \ - --input_model /path/to/yolo_v3.pb \ - --tensorflow_use_custom_operations_config $MO_ROOT/extensions/front/tf/yolo_v3.json \ - --input_shape [1,416,416,3] -``` - -[1]: https://docs.openvinotoolkit.org/latest/_docs_MO_DG_prepare_model_convert_model_tf_specific_Convert_YOLO_From_Tensorflow.html diff --git a/utils/open_model_zoo/yolov3/interp.py b/utils/open_model_zoo/yolov3/interp.py deleted file mode 100644 index 4c76c854..00000000 --- a/utils/open_model_zoo/yolov3/interp.py +++ /dev/null @@ -1,160 +0,0 @@ -from math import exp - - -class Parser: - IOU_THRESHOLD = 0.4 - PROB_THRESHOLD = 0.5 - - def __init__(self): - self.objects = [] - - def scale_bbox(self, x, y, h, w, class_id, confidence, h_scale, w_scale): - xmin = int((x - w / 2) * w_scale) - ymin = int((y - h / 2) * h_scale) - xmax = int(xmin + w * w_scale) - ymax = int(ymin + h * h_scale) - - return dict(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, class_id=class_id, confidence=confidence) - - def entry_index(self, side, coord, classes, location, entry): - side_power_2 = side ** 2 - n = location // side_power_2 - loc = location % side_power_2 - return int(side_power_2 * (n * (coord + classes + 1) + entry) + loc) - - def intersection_over_union(self, box_1, box_2): - width_of_overlap_area = min(box_1['xmax'], box_2['xmax']) - max(box_1['xmin'], box_2['xmin']) - height_of_overlap_area = min(box_1['ymax'], box_2['ymax']) - max(box_1['ymin'], box_2['ymin']) - if width_of_overlap_area < 0 or height_of_overlap_area < 0: - area_of_overlap = 0 - else: - area_of_overlap = width_of_overlap_area * height_of_overlap_area - box_1_area = (box_1['ymax'] - box_1['ymin']) * (box_1['xmax'] - box_1['xmin']) - box_2_area = (box_2['ymax'] - box_2['ymin']) * (box_2['xmax'] - box_2['xmin']) - area_of_union = box_1_area + box_2_area - area_of_overlap - if area_of_union == 0: - return 0 - return area_of_overlap / area_of_union - - - def sort_objects(self): - self.objects = sorted(self.objects, key=lambda obj : obj['confidence'], reverse=True) - - for i in range(len(self.objects)): - if self.objects[i]['confidence'] == 0: - continue - for j in range(i + 1, len(self.objects)): - if self.intersection_over_union(self.objects[i], self.objects[j]) > self.IOU_THRESHOLD: - self.objects[j]['confidence'] = 0 - - def parse_yolo_region(self, blob: 'np.ndarray', original_shape: list, params: dict) -> list: - - # YOLO magic numbers - # See: https://github.com/opencv/open_model_zoo/blob/acf297c73db8cb3f68791ae1fad4a7cc4a6039e5/demos/python_demos/object_detection_demo_yolov3_async/object_detection_demo_yolov3_async.py#L61 - num = 3 - coords = 4 - classes = 80 - # ----------------- - - _, _, out_blob_h, out_blob_w = blob.shape - assert out_blob_w == out_blob_h, "Invalid size of output blob. It sould be in NCHW layout and height should " \ - "be equal to width. Current height = {}, current width = {}" \ - "".format(out_blob_h, out_blob_w) - - # ------ Extracting layer parameters -- - orig_im_h, orig_im_w = original_shape - predictions = blob.flatten() - side_square = params['side'] * params['side'] - - # ------ Parsing YOLO Region output -- - for i in range(side_square): - row = i // params['side'] - col = i % params['side'] - for n in range(num): - # -----entry index calcs------ - obj_index = self.entry_index(params['side'], coords, classes, n * side_square + i, coords) - scale = predictions[obj_index] - if scale < self.PROB_THRESHOLD: - continue - box_index = self.entry_index(params['side'], coords, classes, n * side_square + i, 0) - - # Network produces location predictions in absolute coordinates of feature maps. - # Scale it to relative coordinates. - x = (col + predictions[box_index + 0 * side_square]) / params['side'] * 416 - y = (row + predictions[box_index + 1 * side_square]) / params['side'] * 416 - # Value for exp is very big number in some cases so following construction is using here - try: - h_exp = exp(predictions[box_index + 3 * side_square]) - w_exp = exp(predictions[box_index + 2 * side_square]) - except OverflowError: - continue - - w = w_exp * params['anchors'][2 * n] - h = h_exp * params['anchors'][2 * n + 1] - - for j in range(classes): - class_index = self.entry_index(params['side'], coords, classes, n * side_square + i, - coords + 1 + j) - confidence = scale * predictions[class_index] - if confidence < self.PROB_THRESHOLD: - continue - - self.objects.append(self.scale_bbox(x=x, - y=y, - h=h, - w=w, - class_id=j, - confidence=confidence, - h_scale=(orig_im_h/416), - w_scale=(orig_im_w/416))) - - -for detection in detections: - frame_number = detection['frame_id'] - height = detection['frame_height'] - width = detection['frame_width'] - detection = detection['detections'] - - original_shape = (height, width) - - # https://github.com/opencv/open_model_zoo/blob/master/demos/python_demos/object_detection_demo_yolov3_async/object_detection_demo_yolov3_async.py#L72 - anchors = [10,13,16,30,33,23,30,61,62,45,59,119,116,90,156,198,373,326] - conv_6 = {'side': 13, 'mask': [6,7,8]} - conv_14 = {'side': 26, 'mask': [3,4,5]} - conv_22 = {'side': 52, 'mask': [0,1,2]} - - yolo_params = {'detector/yolo-v3/Conv_6/BiasAdd/YoloRegion': conv_6, - 'detector/yolo-v3/Conv_14/BiasAdd/YoloRegion': conv_14, - 'detector/yolo-v3/Conv_22/BiasAdd/YoloRegion': conv_22} - - for conv_net in yolo_params.values(): - mask = conv_net['mask'] - masked_anchors = [] - for idx in mask: - masked_anchors += [anchors[idx * 2], anchors[idx * 2 + 1]] - - conv_net['anchors'] = masked_anchors - - parser = Parser() - - for name, blob in detection.items(): - parser.parse_yolo_region(blob, original_shape, yolo_params[name]) - - parser.sort_objects() - - objects = [] - for obj in parser.objects: - if obj['confidence'] >= parser.PROB_THRESHOLD: - label = obj['class_id'] - xmin = obj['xmin'] - xmax = obj['xmax'] - ymin = obj['ymin'] - ymax = obj['ymax'] - - # Enforcing extra checks for bounding box coordinates - xmin = max(0,xmin) - ymin = max(0,ymin) - xmax = min(xmax,width) - ymax = min(ymax,height) - - results.add_box(xmin, ymin, xmax, ymax, label, frame_number) diff --git a/utils/open_model_zoo/yolov3/mapping.json b/utils/open_model_zoo/yolov3/mapping.json deleted file mode 100644 index bfb65a24..00000000 --- a/utils/open_model_zoo/yolov3/mapping.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "label_map": { - "0": "person", - "1": "bicycle", - "2": "car", - "3": "motorbike", - "4": "aeroplane", - "5": "bus", - "6": "train", - "7": "truck", - "8": "boat", - "9": "traffic light", - "10": "fire hydrant", - "11": "stop sign", - "12": "parking meter", - "13": "bench", - "14": "bird", - "15": "cat", - "16": "dog", - "17": "horse", - "18": "sheep", - "19": "cow", - "20": "elephant", - "21": "bear", - "22": "zebra", - "23": "giraffe", - "24": "backpack", - "25": "umbrella", - "26": "handbag", - "27": "tie", - "28": "suitcase", - "29": "frisbee", - "30": "skis", - "31": "snowboard", - "32": "sports ball", - "33": "kite", - "34": "baseball bat", - "35": "baseball glove", - "36": "skateboard", - "37": "surfboard", - "38": "tennis racket", - "39": "bottle", - "40": "wine glass", - "41": "cup", - "42": "fork", - "43": "knife", - "44": "spoon", - "45": "bowl", - "46": "banana", - "47": "apple", - "48": "sandwich", - "49": "orange", - "50": "broccoli", - "51": "carrot", - "52": "hot dog", - "53": "pizza", - "54": "donut", - "55": "cake", - "56": "chair", - "57": "sofa", - "58": "pottedplant", - "59": "bed", - "60": "diningtable", - "61": "toilet", - "62": "tvmonitor", - "63": "laptop", - "64": "mouse", - "65": "remote", - "66": "keyboard", - "67": "cell phone", - "68": "microwave", - "69": "oven", - "70": "toaster", - "71": "sink", - "72": "refrigerator", - "73": "book", - "74": "clock", - "75": "vase", - "76": "scissors", - "77": "teddy bear", - "78": "hair drier", - "79": "toothbrush" - } -} From 0062ecdec34a9ffcad33e1664a7cac663bec4ecf Mon Sep 17 00:00:00 2001 From: zhiltsov-max Date: Wed, 29 Jul 2020 21:54:49 +0300 Subject: [PATCH 08/53] [Datumaro] Fixes (#1953) * Add absolute image path in rest api extractor * Add default split for random split * Fix image path in datumaro format * Preserve bboxes in coco format * update changelog Co-authored-by: Nikita Manovich <40690625+nmanovic@users.noreply.github.com> --- CHANGELOG.md | 1 + .../plugins/cvat_rest_api_task_images.py | 2 +- .../datumaro/plugins/coco_format/converter.py | 4 +- .../plugins/datumaro_format/converter.py | 3 +- datumaro/datumaro/plugins/transforms.py | 1 + datumaro/tests/test_coco_format.py | 32 +++--- datumaro/tests/test_datumaro_format.py | 102 +++++++++--------- 7 files changed, 74 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f11ac22..7c1fd2a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Smaller object details () +- `COCO` format does not convert bboxes to polygons on export () - It is impossible to submit a DL model in OpenVINO format using UI. Now you can deploy new models on the server using serverless functions () - Files and folders under share path are now alphabetically sorted diff --git a/cvat/apps/dataset_manager/formats/datumaro/export_templates/plugins/cvat_rest_api_task_images.py b/cvat/apps/dataset_manager/formats/datumaro/export_templates/plugins/cvat_rest_api_task_images.py index b54cce3f..2af31fcc 100644 --- a/cvat/apps/dataset_manager/formats/datumaro/export_templates/plugins/cvat_rest_api_task_images.py +++ b/cvat/apps/dataset_manager/formats/datumaro/export_templates/plugins/cvat_rest_api_task_images.py @@ -100,7 +100,7 @@ class cvat_rest_api_task_images(SourceExtractor): if entry.get('height') and entry.get('width'): size = (entry['height'], entry['width']) image = Image(data=self._make_image_loader(item_id), - path=item_filename, size=size) + path=self._image_local_path(item_id), size=size) item = DatasetItem(id=item_id, image=image) items.append((item.id, item)) diff --git a/datumaro/datumaro/plugins/coco_format/converter.py b/datumaro/datumaro/plugins/coco_format/converter.py index 7c30636b..478e6599 100644 --- a/datumaro/datumaro/plugins/coco_format/converter.py +++ b/datumaro/datumaro/plugins/coco_format/converter.py @@ -298,8 +298,8 @@ class _InstancesConverter(_TaskConverter): rles = mask_utils.merge(rles) area = mask_utils.area(rles) else: - x, y, w, h = bbox - segmentation = [[x, y, x + w, y, x + w, y + h, x, y + h]] + _, _, w, h = bbox + segmentation = [] area = w * h elem = { diff --git a/datumaro/datumaro/plugins/datumaro_format/converter.py b/datumaro/datumaro/plugins/datumaro_format/converter.py index 6e948a25..81c2cd55 100644 --- a/datumaro/datumaro/plugins/datumaro_format/converter.py +++ b/datumaro/datumaro/plugins/datumaro_format/converter.py @@ -54,7 +54,8 @@ class _SubsetWriter: if item.has_image: path = item.image.path if self._context._save_images: - path = self._context._save_image(item) + path = self._context._make_image_filename(item) + self._context._save_image(item, path) item_desc['image'] = { 'size': item.image.size, diff --git a/datumaro/datumaro/plugins/transforms.py b/datumaro/datumaro/plugins/transforms.py index 520d6afd..79f0d3ae 100644 --- a/datumaro/datumaro/plugins/transforms.py +++ b/datumaro/datumaro/plugins/transforms.py @@ -322,6 +322,7 @@ class RandomSplit(Transform, CliPlugin): parser = super().build_cmdline_parser(**kwargs) parser.add_argument('-s', '--subset', action='append', type=cls._split_arg, dest='splits', + default=[('train', 0.67), ('test', 0.33)], help="Subsets in the form of: ':' (repeatable)") parser.add_argument('--seed', type=int, help="Random seed") return parser diff --git a/datumaro/tests/test_coco_format.py b/datumaro/tests/test_coco_format.py index 3c50996e..131284be 100644 --- a/datumaro/tests/test_coco_format.py +++ b/datumaro/tests/test_coco_format.py @@ -4,8 +4,8 @@ import os.path as osp from unittest import TestCase -from datumaro.components.project import (Project, Dataset) -from datumaro.components.extractor import (Extractor, DatasetItem, +from datumaro.components.project import Project, Dataset +from datumaro.components.extractor import (DatasetItem, AnnotationType, Label, Mask, Points, Polygon, Bbox, Caption, LabelCategories, PointsCategories ) @@ -26,7 +26,6 @@ DUMMY_DATASET_DIR = osp.join(osp.dirname(__file__), 'assets', 'coco_dataset') class CocoImporterTest(TestCase): def test_can_import(self): - expected_dataset = Dataset.from_iterable([ DatasetItem(id='000000000001', image=np.ones((10, 5, 3)), subset='val', attributes={'id': 1}, @@ -349,7 +348,6 @@ class CocoConverterTest(TestCase): CocoLabelsConverter.convert, test_dir) def test_can_save_and_load_keypoints(self): - source_dataset = Dataset.from_iterable([ DatasetItem(id=1, subset='train', image=np.zeros((5, 5, 3)), annotations=[ @@ -373,11 +371,11 @@ class CocoConverterTest(TestCase): Points([0, 0, 1, 2, 3, 4], [0, 1, 2], id=5), ]), ], categories={ - AnnotationType.label: LabelCategories.from_iterable( - str(i) for i in range(10)), - AnnotationType.points: PointsCategories.from_iterable( - (i, None, [[0, 1], [1, 2]]) for i in range(10) - ), + AnnotationType.label: LabelCategories.from_iterable( + str(i) for i in range(10)), + AnnotationType.points: PointsCategories.from_iterable( + (i, None, [[0, 1], [1, 2]]) for i in range(10) + ), }) target_dataset = Dataset.from_iterable([ @@ -393,30 +391,30 @@ class CocoConverterTest(TestCase): Points([1, 2, 3, 4, 2, 3], group=2, id=2, attributes={'is_crowd': False}), - Polygon([1, 2, 3, 2, 3, 4, 1, 4], + Bbox(1, 2, 2, 2, group=2, id=2, attributes={'is_crowd': False}), Points([1, 2, 0, 2, 4, 1], label=5, group=3, id=3, attributes={'is_crowd': False}), - Polygon([0, 1, 4, 1, 4, 2, 0, 2], + Bbox(0, 1, 4, 1, label=5, group=3, id=3, attributes={'is_crowd': False}), Points([0, 0, 1, 2, 3, 4], [0, 1, 2], group=5, id=5, attributes={'is_crowd': False}), - Polygon([1, 2, 3, 2, 3, 4, 1, 4], + Bbox(1, 2, 2, 2, group=5, id=5, attributes={'is_crowd': False}), ], attributes={'id': 1}), ], categories={ - AnnotationType.label: LabelCategories.from_iterable( - str(i) for i in range(10)), - AnnotationType.points: PointsCategories.from_iterable( - (i, None, [[0, 1], [1, 2]]) for i in range(10) - ), + AnnotationType.label: LabelCategories.from_iterable( + str(i) for i in range(10)), + AnnotationType.points: PointsCategories.from_iterable( + (i, None, [[0, 1], [1, 2]]) for i in range(10) + ), }) with TestDir() as test_dir: diff --git a/datumaro/tests/test_datumaro_format.py b/datumaro/tests/test_datumaro_format.py index e67a1b90..421627a8 100644 --- a/datumaro/tests/test_datumaro_format.py +++ b/datumaro/tests/test_datumaro_format.py @@ -32,56 +32,58 @@ class DatumaroConverterTest(TestCase): compare_datasets_strict(self, expected=target_dataset, actual=parsed_dataset) - label_categories = LabelCategories() - for i in range(5): - label_categories.add('cat' + str(i)) - - mask_categories = MaskCategories( - generate_colormap(len(label_categories.items))) - - points_categories = PointsCategories() - for index, _ in enumerate(label_categories.items): - points_categories.add(index, ['cat1', 'cat2'], joints=[[0, 1]]) - - test_dataset = Dataset.from_iterable([ - DatasetItem(id=100, subset='train', image=np.ones((10, 6, 3)), - annotations=[ - Caption('hello', id=1), - Caption('world', id=2, group=5), - Label(2, id=3, attributes={ - 'x': 1, - 'y': '2', - }), - Bbox(1, 2, 3, 4, label=4, id=4, z_order=1, attributes={ - 'score': 1.0, - }), - Bbox(5, 6, 7, 8, id=5, group=5), - Points([1, 2, 2, 0, 1, 1], label=0, id=5, z_order=4), - Mask(label=3, id=5, z_order=2, image=np.ones((2, 3))), - ]), - DatasetItem(id=21, subset='train', - annotations=[ - Caption('test'), - Label(2), - Bbox(1, 2, 3, 4, 5, id=42, group=42) - ]), - - DatasetItem(id=2, subset='val', - annotations=[ - PolyLine([1, 2, 3, 4, 5, 6, 7, 8], id=11, z_order=1), - Polygon([1, 2, 3, 4, 5, 6, 7, 8], id=12, z_order=4), - ]), - - DatasetItem(id=42, subset='test', - attributes={'a1': 5, 'a2': '42'}), - - DatasetItem(id=42), - DatasetItem(id=43, image=Image(path='1/b/c.qq', size=(2, 4))), - ], categories={ - AnnotationType.label: label_categories, - AnnotationType.mask: mask_categories, - AnnotationType.points: points_categories, - }) + @property + def test_dataset(self): + label_categories = LabelCategories() + for i in range(5): + label_categories.add('cat' + str(i)) + + mask_categories = MaskCategories( + generate_colormap(len(label_categories.items))) + + points_categories = PointsCategories() + for index, _ in enumerate(label_categories.items): + points_categories.add(index, ['cat1', 'cat2'], joints=[[0, 1]]) + + return Dataset.from_iterable([ + DatasetItem(id=100, subset='train', image=np.ones((10, 6, 3)), + annotations=[ + Caption('hello', id=1), + Caption('world', id=2, group=5), + Label(2, id=3, attributes={ + 'x': 1, + 'y': '2', + }), + Bbox(1, 2, 3, 4, label=4, id=4, z_order=1, attributes={ + 'score': 1.0, + }), + Bbox(5, 6, 7, 8, id=5, group=5), + Points([1, 2, 2, 0, 1, 1], label=0, id=5, z_order=4), + Mask(label=3, id=5, z_order=2, image=np.ones((2, 3))), + ]), + DatasetItem(id=21, subset='train', + annotations=[ + Caption('test'), + Label(2), + Bbox(1, 2, 3, 4, 5, id=42, group=42) + ]), + + DatasetItem(id=2, subset='val', + annotations=[ + PolyLine([1, 2, 3, 4, 5, 6, 7, 8], id=11, z_order=1), + Polygon([1, 2, 3, 4, 5, 6, 7, 8], id=12, z_order=4), + ]), + + DatasetItem(id=42, subset='test', + attributes={'a1': 5, 'a2': '42'}), + + DatasetItem(id=42), + DatasetItem(id=43, image=Image(path='1/b/c.qq', size=(2, 4))), + ], categories={ + AnnotationType.label: label_categories, + AnnotationType.mask: mask_categories, + AnnotationType.points: points_categories, + }) def test_can_save_and_load(self): with TestDir() as test_dir: From f6c396557f15a192b38b8defd87270cac42e94b4 Mon Sep 17 00:00:00 2001 From: Boris Sekachev <40690378+bsekachev@users.noreply.github.com> Date: Thu, 30 Jul 2020 16:14:19 +0300 Subject: [PATCH 09/53] [React UI] A couple of fixes (#1966) --- CHANGELOG.md | 2 ++ cvat-core/package.json | 2 +- cvat-core/src/frames.js | 8 ++++++++ cvat-core/src/session.js | 8 +++++++- cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- cvat-ui/src/actions/plugins-actions.ts | 20 ++++++++++++++----- cvat-ui/src/reducers/interfaces.ts | 7 +++---- cvat-ui/src/reducers/notifications-reducer.ts | 20 +++++++++++++++++++ 9 files changed, 58 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c1fd2a7..e230af8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Intelligent polygon editing () - Support creating multiple jobs for each task through python cli (https://github.com/opencv/cvat/pull/1950) - python cli over https () +- Error message when plugins weren't able to initialize instead of infinite loading () ### Changed - Smaller object details () @@ -42,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Interpolated shapes exported as `keyframe = True` () - Stylelint filetype scans () - Fixed toolip closing issue () +- Clearing frame cache when close a task () ### Security - diff --git a/cvat-core/package.json b/cvat-core/package.json index 5f7d2fcd..a34f53d0 100644 --- a/cvat-core/package.json +++ b/cvat-core/package.json @@ -1,6 +1,6 @@ { "name": "cvat-core", - "version": "3.3.0", + "version": "3.3.1", "description": "Part of Computer Vision Tool which presents an interface for client-side integration", "main": "babel.config.js", "scripts": { diff --git a/cvat-core/src/frames.js b/cvat-core/src/frames.js index 66145a06..0e95d42d 100644 --- a/cvat-core/src/frames.js +++ b/cvat-core/src/frames.js @@ -605,10 +605,18 @@ }; } + function clear(taskID) { + if (taskID in frameDataCache) { + frameDataCache[taskID].frameBuffer.clear(); + delete frameDataCache[taskID]; + } + } + module.exports = { FrameData, getFrame, getRanges, getPreview, + clear, }; })(); diff --git a/cvat-core/src/session.js b/cvat-core/src/session.js index 5d5bd7b2..6a994e0a 100644 --- a/cvat-core/src/session.js +++ b/cvat-core/src/session.js @@ -11,7 +11,12 @@ const PluginRegistry = require('./plugins'); const loggerStorage = require('./logger-storage'); const serverProxy = require('./server-proxy'); - const { getFrame, getRanges, getPreview } = require('./frames'); + const { + getFrame, + getRanges, + getPreview, + clear: clearFrames, + } = require('./frames'); const { ArgumentError } = require('./exceptions'); const { TaskStatus } = require('./enums'); const { Label } = require('./labels'); @@ -1593,6 +1598,7 @@ }; Task.prototype.close.implementation = function closeTask() { + clearFrames(this.id); for (const job of this.jobs) { closeSession(job); } diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 0ca9624a..0d7de93f 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.6.6", + "version": "1.6.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 49a2bd37..b97d19fe 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.6.6", + "version": "1.6.7", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { diff --git a/cvat-ui/src/actions/plugins-actions.ts b/cvat-ui/src/actions/plugins-actions.ts index 21b3fed5..5d58a11f 100644 --- a/cvat-ui/src/actions/plugins-actions.ts +++ b/cvat-ui/src/actions/plugins-actions.ts @@ -8,7 +8,8 @@ import PluginChecker from 'utils/plugin-checker'; export enum PluginsActionTypes { CHECK_PLUGINS = 'CHECK_PLUGINS', - CHECKED_ALL_PLUGINS = 'CHECKED_ALL_PLUGINS' + CHECKED_ALL_PLUGINS = 'CHECKED_ALL_PLUGINS', + RAISE_PLUGIN_CHECK_ERROR = 'RAISE_PLUGIN_CHECK_ERROR' } type PluginObjects = Record; @@ -20,6 +21,11 @@ const pluginActions = { list, }) ), + raisePluginCheckError: (error: Error) => ( + createAction(PluginsActionTypes.RAISE_PLUGIN_CHECK_ERROR, { + error, + }) + ), }; export type PluginActions = ActionUnion; @@ -39,9 +45,13 @@ export function checkPluginsAsync(): ThunkAction { PluginChecker.check(SupportedPlugins.DEXTR_SEGMENTATION), ]; - const values = await Promise.all(promises); - [plugins.ANALYTICS, plugins.GIT_INTEGRATION, - plugins.DEXTR_SEGMENTATION] = values; - dispatch(pluginActions.checkedAllPlugins(plugins)); + try { + const values = await Promise.all(promises); + [plugins.ANALYTICS, plugins.GIT_INTEGRATION, + plugins.DEXTR_SEGMENTATION] = values; + dispatch(pluginActions.checkedAllPlugins(plugins)); + } catch (error) { + dispatch(pluginActions.raisePluginCheckError(error)); + } }; } diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts index 065b0dd8..5e7961c7 100644 --- a/cvat-ui/src/reducers/interfaces.ts +++ b/cvat-ui/src/reducers/interfaces.ts @@ -235,8 +235,9 @@ export interface NotificationsState { userAgreements: { fetching: null | ErrorState; }; - - [index: string]: any; + plugins: { + initializationError: null | ErrorState; + }; }; messages: { tasks: { @@ -245,8 +246,6 @@ export interface NotificationsState { models: { inferenceDone: string; }; - - [index: string]: any; }; } diff --git a/cvat-ui/src/reducers/notifications-reducer.ts b/cvat-ui/src/reducers/notifications-reducer.ts index 68a65ca5..ee08de33 100644 --- a/cvat-ui/src/reducers/notifications-reducer.ts +++ b/cvat-ui/src/reducers/notifications-reducer.ts @@ -15,9 +15,11 @@ import { AnnotationActionTypes } from 'actions/annotation-actions'; import { NotificationsActionType } from 'actions/notification-actions'; import { BoundariesActionTypes } from 'actions/boundaries-actions'; import { UserAgreementsActionTypes } from 'actions/useragreements-actions'; +import { PluginsActionTypes } from 'actions/plugins-actions'; import { NotificationsState } from './interfaces'; + const defaultState: NotificationsState = { errors: { auth: { @@ -84,6 +86,9 @@ const defaultState: NotificationsState = { userAgreements: { fetching: null, }, + plugins: { + initializationError: null, + }, }, messages: { tasks: { @@ -805,6 +810,21 @@ export default function (state = defaultState, action: AnyAction): Notifications }, }; } + case PluginsActionTypes.RAISE_PLUGIN_CHECK_ERROR: { + return { + ...state, + errors: { + ...state.errors, + plugins: { + ...state.errors.plugins, + initializationError: { + message: 'Could not initialize plugins state', + reason: action.payload.error.toString(), + }, + }, + }, + }; + } case NotificationsActionType.RESET_ERRORS: { return { ...state, From e8c915876740a96b70e66c093dc0f7731350d12a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Jul 2020 16:17:22 +0300 Subject: [PATCH 10/53] Bump elliptic from 6.5.0 to 6.5.3 in /cvat-canvas (#1968) Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.0 to 6.5.3. - [Release notes](https://github.com/indutny/elliptic/releases) - [Commits](https://github.com/indutny/elliptic/compare/v6.5.0...v6.5.3) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cvat-canvas/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cvat-canvas/package-lock.json b/cvat-canvas/package-lock.json index 6ea8a30f..b50b6223 100644 --- a/cvat-canvas/package-lock.json +++ b/cvat-canvas/package-lock.json @@ -3223,9 +3223,9 @@ "dev": true }, "elliptic": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", - "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", "dev": true, "requires": { "bn.js": "^4.4.0", From 820f2c5724a50650f7325508152c3ee166ffe245 Mon Sep 17 00:00:00 2001 From: Andrey Zhavoronkov <41117609+azhavoro@users.noreply.github.com> Date: Thu, 30 Jul 2020 21:42:28 +0300 Subject: [PATCH 11/53] Az/update faq (#1967) * added a couple of questions to the FAQ page * Update faq.md * Update faq.md --- cvat/apps/documentation/faq.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cvat/apps/documentation/faq.md b/cvat/apps/documentation/faq.md index d846a093..396c9ab4 100644 --- a/cvat/apps/documentation/faq.md +++ b/cvat/apps/documentation/faq.md @@ -8,6 +8,8 @@ - [Where are annotations stored](#where-are-annotations-stored) - [How to mark job/task as completed](#how-to-mark-jobtask-as-completed) - [How to install CVAT on Windows 10 Home](#how-to-install-cvat-on-windows-10-home) +- [I do not have the Analytics tab on the header section. How can I add analytics](#i-do-not-have-the-analytics-tab-on-the-header-section-how-can-i-add-analytics) +- [How to upload annotations to an entire task from UI when there are multiple jobs in the task](#how-to-upload-annotations-to-an-entire-task-from-ui-when-there-are-multiple-jobs-in-the-task) ## How to update CVAT Before upgrading, please follow the official docker @@ -98,4 +100,11 @@ There are three types of status: annotation, validation or completed. The status of the job changes the progress bar of the task. ## How to install CVAT on Windows 10 Home -Follow this [guide](installation.md#windows-10). \ No newline at end of file +Follow this [guide](installation.md#windows-10). + +## I do not have the Analytics tab on the header section. How can I add analytics +You should build CVAT images with ['Analytics' component](../../../components/analytics). + +## How to upload annotations to an entire task from UI when there are multiple jobs in the task +You can upload annotation for a multi-job task from the Dasboard view or the Task view. +Uploading of annotation from the Annotation view only affects the current job. From d71e44174a1721e9ab8787c71f3a20d746069560 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Aug 2020 07:14:17 +0300 Subject: [PATCH 12/53] Bump elliptic from 6.5.2 to 6.5.3 in /cvat-ui (#1975) Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.3. - [Release notes](https://github.com/indutny/elliptic/releases) - [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.3) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cvat-ui/package-lock.json | 42 +++++---------------------------------- 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 0d7de93f..0f2ece18 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -5139,7 +5139,6 @@ "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", "inherits": "^2.0.1", "parse-asn1": "^5.0.0" } @@ -5682,8 +5681,7 @@ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" + "bn.js": "^4.1.0" } }, "create-error-class": { @@ -6172,20 +6170,6 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.199.tgz", "integrity": "sha512-gachlDdHSK47s0N2e58GH9HMC6Z4ip0SfmYUa5iEbE50AKaOUXysaJnXMfKj0xB245jWbYcyFSH+th3rqsF8hA==" }, - "elliptic": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", - "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -14089,7 +14073,6 @@ "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", "inherits": "^2.0.1", "parse-asn1": "^5.0.0" } @@ -14503,8 +14486,7 @@ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" + "bn.js": "^4.1.0" } }, "create-hash": { @@ -14969,20 +14951,6 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.377.tgz", "integrity": "sha512-cm2WzMKf/3dW5+hNANKm8GAW6SwIWOqLTJ6GPCD0Bbw1qJ9Wzm9nmx9M+byzSsgw8CdCv5fb/wzLFqVS5h6QrA==" }, - "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", - "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -21482,9 +21450,9 @@ "dev": true }, "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", - "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", "dev": true, "requires": { "bn.js": "^4.4.0", From 0d0749f4ec0190e21e7f26123289fa9eb130fc58 Mon Sep 17 00:00:00 2001 From: Andrey Zhavoronkov <41117609+azhavoro@users.noreply.github.com> Date: Mon, 3 Aug 2020 12:29:10 +0300 Subject: [PATCH 13/53] fixed swagger API documentation for POST /tasks/{id}/data endpoint (#1963) --- cvat/apps/engine/views.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cvat/apps/engine/views.py b/cvat/apps/engine/views.py index c9d6e5d0..13a9fdbe 100644 --- a/cvat/apps/engine/views.py +++ b/cvat/apps/engine/views.py @@ -389,7 +389,9 @@ class TaskViewSet(auth.TaskGetQuerySetMixin, viewsets.ModelViewSet): return Response(serializer.data) - @swagger_auto_schema(method='post', operation_summary='Method permanently attaches images or video to a task') + @swagger_auto_schema(method='post', operation_summary='Method permanently attaches images or video to a task', + request_body=DataSerializer, + ) @swagger_auto_schema(method='get', operation_summary='Method returns data for a specific task', manual_parameters=[ openapi.Parameter('type', in_=openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING, @@ -879,4 +881,4 @@ def _export_annotations(db_task, rq_id, request, format_name, action, callback, args=(db_task.id, format_name, server_address), job_id=rq_id, meta={ 'request_time': timezone.localtime() }, result_ttl=ttl, failure_ttl=ttl) - return Response(status=status.HTTP_202_ACCEPTED) \ No newline at end of file + return Response(status=status.HTTP_202_ACCEPTED) From 634ca1795875b9bf602e85fce710b383bce9a3a9 Mon Sep 17 00:00:00 2001 From: Nikita Manovich <40690625+nmanovic@users.noreply.github.com> Date: Mon, 3 Aug 2020 16:19:17 +0300 Subject: [PATCH 14/53] Remove old UI (#1964) * Removed outdated code * Revert changes in .gitignore * Fix docker build * Remove karma + some dummy code * Fix a type in Dockerfile.ci * Fix swagger and remove dispatch_request. * Update CHANGELOG.md --- CHANGELOG.md | 1 + Dockerfile | 3 - Dockerfile.ci | 12 +- cvat-ui/src/components/task-page/job-list.tsx | 9 - cvat/apps/authentication/api_urls.py | 28 - cvat/apps/authentication/forms.py | 60 - .../authentication/migrations/__init__.py | 5 - cvat/apps/authentication/models.py | 9 - cvat/apps/authentication/templates/403.html | 17 - .../authentication/templates/auth_base.html | 99 - cvat/apps/authentication/templates/login.html | 29 - .../authentication/templates/register.html | 32 - .../templates/user_profile.html | 21 - cvat/apps/authentication/tests.py | 9 - cvat/apps/authentication/urls.py | 25 +- cvat/apps/authentication/views.py | 18 - cvat/apps/documentation/admin.py | 9 - .../apps/documentation/migrations/__init__.py | 5 - cvat/apps/documentation/models.py | 9 - cvat/apps/documentation/tests.py | 9 - cvat/apps/engine/static/engine/base.css | 181 - .../engine/fonts/BarlowSemiCondensed-Bold.ttf | Bin 91412 -> 0 bytes .../fonts/BarlowSemiCondensed-Regular.ttf | Bin 85532 -> 0 bytes .../fonts/BarlowSemiCondensed-SemiBold.ttf | Bin 89760 -> 0 bytes .../apps/engine/static/engine/fonts/README.md | 95 - .../apps/engine/static/engine/icons/README.md | 5 - cvat/apps/engine/static/engine/icons/copy.png | Bin 254 -> 0 bytes .../static/engine/icons/hidden-shape.png | Bin 532 -> 0 bytes .../static/engine/icons/hidden-text.png | Bin 690 -> 0 bytes .../static/engine/icons/initKeyFrame.png | Bin 668 -> 0 bytes .../engine/static/engine/icons/keyframe.png | Bin 509 -> 0 bytes cvat/apps/engine/static/engine/icons/lock.png | Bin 185 -> 0 bytes .../static/engine/icons/nextKeyFrame.png | Bin 657 -> 0 bytes .../engine/static/engine/icons/non-hidden.png | Bin 634 -> 0 bytes .../static/engine/icons/non-keyframe.png | Bin 630 -> 0 bytes .../static/engine/icons/non-occluded.png | Bin 287 -> 0 bytes .../static/engine/icons/non-outside.png | Bin 410 -> 0 bytes .../engine/static/engine/icons/occluded.png | Bin 422 -> 0 bytes .../engine/static/engine/icons/outside.png | Bin 446 -> 0 bytes .../static/engine/icons/prevKeyFrame.png | Bin 673 -> 0 bytes .../engine/static/engine/icons/propagate.png | Bin 409 -> 0 bytes .../engine/static/engine/icons/unlock.png | Bin 182 -> 0 bytes .../engine/static/engine/js/3rdparty.patch | 128 - .../engine/js/3rdparty/Decoder.worker.js | 2 - .../engine/static/engine/js/3rdparty/avc.wasm | Bin 126815 -> 0 bytes .../static/engine/js/3rdparty/defiant.min.js | 6 - .../static/engine/js/3rdparty/jquery-3.3.1.js | 10364 ---------------- .../engine/js/3rdparty/jquery.fullscreen.js | 184 - .../static/engine/js/3rdparty/js.cookie.js | 165 - .../static/engine/js/3rdparty/mousetrap.js | 1044 -- .../static/engine/js/3rdparty/platform.js | 1219 -- .../engine/js/3rdparty/svg.draggable.js | 227 - .../static/engine/js/3rdparty/svg.draw.js | 442 - .../engine/static/engine/js/3rdparty/svg.js | 5601 --------- .../engine/js/3rdparty/svg.resize.min.js | 1 - .../static/engine/js/3rdparty/svg.select.js | 417 - .../static/engine/js/annotationParser.js | 439 - .../static/engine/js/annotationSaver.js | 452 - .../engine/static/engine/js/annotationUI.js | 761 -- .../engine/js/attributeAnnotationMode.js | 453 - cvat/apps/engine/static/engine/js/base.js | 227 - .../apps/engine/static/engine/js/bootstrap.js | 34 - .../engine/static/engine/js/borderSticker.js | 213 - .../engine/static/engine/js/checkPlatform.js | 22 - .../static/engine/js/coordinateTranslator.js | 177 - .../engine/static/engine/js/cuboidShape.js | 1370 -- .../engine/static/engine/js/cvat-core.min.js | 15 - cvat/apps/engine/static/engine/js/cvat.js | 22 - .../static/engine/js/download.worker.js | 9 - cvat/apps/engine/static/engine/js/history.js | 219 - .../engine/static/engine/js/labelsInfo.js | 192 - cvat/apps/engine/static/engine/js/listener.js | 51 - cvat/apps/engine/static/engine/js/logger.js | 564 - cvat/apps/engine/static/engine/js/player.js | 1041 -- .../static/engine/js/polyshapeEditor.js | 494 - .../engine/static/engine/js/qunitTests.js | 549 - cvat/apps/engine/static/engine/js/server.js | 11 - .../engine/static/engine/js/shapeBuffer.js | 563 - .../static/engine/js/shapeCollection.js | 1659 --- .../engine/static/engine/js/shapeCreator.js | 963 -- .../engine/static/engine/js/shapeFilter.js | 246 - .../engine/static/engine/js/shapeGrouper.js | 274 - .../engine/static/engine/js/shapeMerger.js | 285 - .../engine/static/engine/js/shapeSplitter.js | 91 - cvat/apps/engine/static/engine/js/shapes.js | 3395 ----- .../static/engine/js/unzip_imgs.worker.js | 9 - .../engine/static/engine/js/userConfig.js | 368 - cvat/apps/engine/static/engine/js/utils.js | 56 - cvat/apps/engine/static/engine/stylesheet.css | 599 - .../engine/templates/engine/annotation.html | 473 - cvat/apps/engine/templates/engine/base.html | 90 - cvat/apps/engine/urls.py | 31 +- cvat/apps/engine/views.py | 43 +- cvat/apps/git/admin.py | 3 - cvat/apps/log_viewer/migrations/__init__.py | 0 cvat/apps/restrictions/migrations/__init__.py | 3 - cvat/settings/base.py | 6 +- tests/eslintrc.conf.js | 131 - tests/karma.conf.js | 68 - tests/run_js_linter.sh | 15 - 100 files changed, 44 insertions(+), 37132 deletions(-) delete mode 100644 cvat/apps/authentication/api_urls.py delete mode 100644 cvat/apps/authentication/forms.py delete mode 100644 cvat/apps/authentication/migrations/__init__.py delete mode 100644 cvat/apps/authentication/models.py delete mode 100644 cvat/apps/authentication/templates/403.html delete mode 100644 cvat/apps/authentication/templates/auth_base.html delete mode 100644 cvat/apps/authentication/templates/login.html delete mode 100644 cvat/apps/authentication/templates/register.html delete mode 100644 cvat/apps/authentication/templates/user_profile.html delete mode 100644 cvat/apps/authentication/tests.py delete mode 100644 cvat/apps/documentation/admin.py delete mode 100644 cvat/apps/documentation/migrations/__init__.py delete mode 100644 cvat/apps/documentation/models.py delete mode 100644 cvat/apps/documentation/tests.py delete mode 100644 cvat/apps/engine/static/engine/base.css delete mode 100644 cvat/apps/engine/static/engine/fonts/BarlowSemiCondensed-Bold.ttf delete mode 100644 cvat/apps/engine/static/engine/fonts/BarlowSemiCondensed-Regular.ttf delete mode 100644 cvat/apps/engine/static/engine/fonts/BarlowSemiCondensed-SemiBold.ttf delete mode 100644 cvat/apps/engine/static/engine/fonts/README.md delete mode 100644 cvat/apps/engine/static/engine/icons/README.md delete mode 100644 cvat/apps/engine/static/engine/icons/copy.png delete mode 100644 cvat/apps/engine/static/engine/icons/hidden-shape.png delete mode 100644 cvat/apps/engine/static/engine/icons/hidden-text.png delete mode 100644 cvat/apps/engine/static/engine/icons/initKeyFrame.png delete mode 100644 cvat/apps/engine/static/engine/icons/keyframe.png delete mode 100644 cvat/apps/engine/static/engine/icons/lock.png delete mode 100644 cvat/apps/engine/static/engine/icons/nextKeyFrame.png delete mode 100644 cvat/apps/engine/static/engine/icons/non-hidden.png delete mode 100644 cvat/apps/engine/static/engine/icons/non-keyframe.png delete mode 100644 cvat/apps/engine/static/engine/icons/non-occluded.png delete mode 100644 cvat/apps/engine/static/engine/icons/non-outside.png delete mode 100644 cvat/apps/engine/static/engine/icons/occluded.png delete mode 100644 cvat/apps/engine/static/engine/icons/outside.png delete mode 100644 cvat/apps/engine/static/engine/icons/prevKeyFrame.png delete mode 100644 cvat/apps/engine/static/engine/icons/propagate.png delete mode 100644 cvat/apps/engine/static/engine/icons/unlock.png delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty.patch delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/Decoder.worker.js delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/avc.wasm delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/defiant.min.js delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/jquery-3.3.1.js delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/jquery.fullscreen.js delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/js.cookie.js delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/mousetrap.js delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/platform.js delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/svg.draggable.js delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/svg.draw.js delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/svg.js delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/svg.resize.min.js delete mode 100644 cvat/apps/engine/static/engine/js/3rdparty/svg.select.js delete mode 100644 cvat/apps/engine/static/engine/js/annotationParser.js delete mode 100644 cvat/apps/engine/static/engine/js/annotationSaver.js delete mode 100644 cvat/apps/engine/static/engine/js/annotationUI.js delete mode 100644 cvat/apps/engine/static/engine/js/attributeAnnotationMode.js delete mode 100644 cvat/apps/engine/static/engine/js/base.js delete mode 100644 cvat/apps/engine/static/engine/js/bootstrap.js delete mode 100644 cvat/apps/engine/static/engine/js/borderSticker.js delete mode 100644 cvat/apps/engine/static/engine/js/checkPlatform.js delete mode 100644 cvat/apps/engine/static/engine/js/coordinateTranslator.js delete mode 100644 cvat/apps/engine/static/engine/js/cuboidShape.js delete mode 100644 cvat/apps/engine/static/engine/js/cvat-core.min.js delete mode 100644 cvat/apps/engine/static/engine/js/cvat.js delete mode 100644 cvat/apps/engine/static/engine/js/download.worker.js delete mode 100644 cvat/apps/engine/static/engine/js/history.js delete mode 100644 cvat/apps/engine/static/engine/js/labelsInfo.js delete mode 100644 cvat/apps/engine/static/engine/js/listener.js delete mode 100644 cvat/apps/engine/static/engine/js/logger.js delete mode 100644 cvat/apps/engine/static/engine/js/player.js delete mode 100644 cvat/apps/engine/static/engine/js/polyshapeEditor.js delete mode 100644 cvat/apps/engine/static/engine/js/qunitTests.js delete mode 100644 cvat/apps/engine/static/engine/js/server.js delete mode 100644 cvat/apps/engine/static/engine/js/shapeBuffer.js delete mode 100644 cvat/apps/engine/static/engine/js/shapeCollection.js delete mode 100644 cvat/apps/engine/static/engine/js/shapeCreator.js delete mode 100644 cvat/apps/engine/static/engine/js/shapeFilter.js delete mode 100644 cvat/apps/engine/static/engine/js/shapeGrouper.js delete mode 100644 cvat/apps/engine/static/engine/js/shapeMerger.js delete mode 100644 cvat/apps/engine/static/engine/js/shapeSplitter.js delete mode 100644 cvat/apps/engine/static/engine/js/shapes.js delete mode 100644 cvat/apps/engine/static/engine/js/unzip_imgs.worker.js delete mode 100644 cvat/apps/engine/static/engine/js/userConfig.js delete mode 100644 cvat/apps/engine/static/engine/js/utils.js delete mode 100644 cvat/apps/engine/static/engine/stylesheet.css delete mode 100644 cvat/apps/engine/templates/engine/annotation.html delete mode 100644 cvat/apps/engine/templates/engine/base.html delete mode 100644 cvat/apps/git/admin.py delete mode 100644 cvat/apps/log_viewer/migrations/__init__.py delete mode 100644 cvat/apps/restrictions/migrations/__init__.py delete mode 100644 tests/eslintrc.conf.js delete mode 100644 tests/karma.conf.js delete mode 100644 tests/run_js_linter.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index e230af8b..7f51fc05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed - Removed OpenVINO and CUDA components because they are not necessary anymore () +- Removed the old UI code () ### Fixed - Some objects aren't shown on canvas sometimes. For example after propagation on of objects is invisible () diff --git a/Dockerfile b/Dockerfile index c70baef8..02535a02 100644 --- a/Dockerfile +++ b/Dockerfile @@ -106,9 +106,6 @@ COPY datumaro/ ${HOME}/datumaro RUN python3 -m pip install --no-cache-dir -r ${HOME}/datumaro/requirements.txt -# Binary option is necessary to correctly apply the patch on Windows platform. -# https://unix.stackexchange.com/questions/239364/how-to-fix-hunk-1-failed-at-1-different-line-endings-message -RUN patch --binary -p1 < ${HOME}/cvat/apps/engine/static/engine/js/3rdparty.patch RUN chown -R ${USER}:${USER} . # RUN all commands below as 'django' user diff --git a/Dockerfile.ci b/Dockerfile.ci index d3d06874..3c4807b4 100644 --- a/Dockerfile.ci +++ b/Dockerfile.ci @@ -27,17 +27,7 @@ COPY .coveragerc . # RUN all commands below as 'django' user USER ${USER} -RUN mkdir -p tests && cd tests && npm install \ - eslint \ - eslint-detailed-reporter \ - karma \ - karma-chrome-launcher \ - karma-coveralls \ - karma-coverage \ - karma-junit-reporter \ - karma-qunit \ - qunit; \ - CI=true npm install cypress; \ +RUN mkdir -p tests && cd tests && CI=true npm install cypress; \ echo "export PATH=~/tests/node_modules/.bin:${PATH}" >> ~/.bashrc; ENTRYPOINT [] diff --git a/cvat-ui/src/components/task-page/job-list.tsx b/cvat-ui/src/components/task-page/job-list.tsx index 647d7258..dc89b51a 100644 --- a/cvat-ui/src/components/task-page/job-list.tsx +++ b/cvat-ui/src/components/task-page/job-list.tsx @@ -54,15 +54,6 @@ function JobListComponent(props: Props & RouteComponentProps): JSX.Element { > {`Job #${id}`} - | - - - ), }, { diff --git a/cvat/apps/authentication/api_urls.py b/cvat/apps/authentication/api_urls.py deleted file mode 100644 index a3752ad5..00000000 --- a/cvat/apps/authentication/api_urls.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.urls import path -from django.conf import settings -from rest_auth.views import ( - LoginView, LogoutView, PasswordChangeView, - PasswordResetView, PasswordResetConfirmView) -from rest_auth.registration.views import RegisterView -from .views import SigningView - -urlpatterns = [ - path('login', LoginView.as_view(), name='rest_login'), - path('logout', LogoutView.as_view(), name='rest_logout'), - path('signing', SigningView.as_view(), name='signing') -] - -if settings.DJANGO_AUTH_TYPE == 'BASIC': - urlpatterns += [ - path('register', RegisterView.as_view(), name='rest_register'), - path('password/reset', PasswordResetView.as_view(), - name='rest_password_reset'), - path('password/reset/confirm', PasswordResetConfirmView.as_view(), - name='rest_password_reset_confirm'), - path('password/change', PasswordChangeView.as_view(), - name='rest_password_change'), - ] diff --git a/cvat/apps/authentication/forms.py b/cvat/apps/authentication/forms.py deleted file mode 100644 index 238b1598..00000000 --- a/cvat/apps/authentication/forms.py +++ /dev/null @@ -1,60 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.contrib.auth.forms import ( - UsernameField, - AuthenticationForm, - UserCreationForm, -) -from django.utils.translation import gettext, gettext_lazy as _ -from django.contrib.auth.models import User - -from django import forms - -class AuthForm(AuthenticationForm): - username = UsernameField( - widget=forms.TextInput(attrs={'autofocus': True, 'placeholder': "Username"}), - ) - password = forms.CharField( - label=_("Password"), - strip=False, - widget=forms.PasswordInput(attrs={'placeholder': "Password"}), - ) - -class NewUserForm(UserCreationForm): - username = UsernameField( - widget=forms.TextInput(attrs={'autofocus': True, 'placeholder': "Username (required)"}), - required=True, - ) - - first_name = UsernameField( - widget=forms.TextInput(attrs={'placeholder': "First name"}), - required=False, - ) - - last_name = UsernameField( - widget=forms.TextInput(attrs={'placeholder': "Last name"}), - required=False, - ) - - email = forms.EmailField( - widget=forms.EmailInput(attrs={'placeholder': "Email (required)"}), - required=True, - ) - - password1 = forms.CharField( - label=_("Password"), - strip=False, - widget=forms.PasswordInput(attrs={'placeholder': "Password (required)"}), - ) - password2 = forms.CharField( - label=_("Password confirmation"), - widget=forms.PasswordInput(attrs={'placeholder': "Password confirmation (required)"}), - strip=False, - ) - - class Meta: - model = User - fields = ('username', 'first_name', 'last_name', 'email', ) diff --git a/cvat/apps/authentication/migrations/__init__.py b/cvat/apps/authentication/migrations/__init__.py deleted file mode 100644 index d8e62e54..00000000 --- a/cvat/apps/authentication/migrations/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - diff --git a/cvat/apps/authentication/models.py b/cvat/apps/authentication/models.py deleted file mode 100644 index cdf3b082..00000000 --- a/cvat/apps/authentication/models.py +++ /dev/null @@ -1,9 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.db import models - -# Create your models here. - diff --git a/cvat/apps/authentication/templates/403.html b/cvat/apps/authentication/templates/403.html deleted file mode 100644 index e275bb1f..00000000 --- a/cvat/apps/authentication/templates/403.html +++ /dev/null @@ -1,17 +0,0 @@ - -{% extends "auth_base.html" %} - -{% block title %}Forbidden{% endblock %} - -{% block content %} -

Forbidden

- {% if user.is_authenticated %} -

Your account doesn't have access to this page. To proceed, - please login with an account that has access or contact your admin.
- Login

- {% endif %} -{% endblock %} diff --git a/cvat/apps/authentication/templates/auth_base.html b/cvat/apps/authentication/templates/auth_base.html deleted file mode 100644 index a9a4b98f..00000000 --- a/cvat/apps/authentication/templates/auth_base.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - {% block title %}{% endblock %} - - - - - - - -
- {% block note %} {% endblock %} -
- - diff --git a/cvat/apps/authentication/templates/login.html b/cvat/apps/authentication/templates/login.html deleted file mode 100644 index 855031f7..00000000 --- a/cvat/apps/authentication/templates/login.html +++ /dev/null @@ -1,29 +0,0 @@ - -{% extends "auth_base.html" %} - -{% block title %}Login{% endblock %} - -{% block content %} -

Login

- {% if form.errors %} - Your username and password didn't match. Please try again. - {% endif %} -
- {% csrf_token %} - {% for field in form %} - {{ field }} - {% endfor %} - - -
-{% endblock %} - -{% block note%} - {% autoescape off %} - {{ note }} - {% endautoescape %} -{% endblock %} \ No newline at end of file diff --git a/cvat/apps/authentication/templates/register.html b/cvat/apps/authentication/templates/register.html deleted file mode 100644 index b655e221..00000000 --- a/cvat/apps/authentication/templates/register.html +++ /dev/null @@ -1,32 +0,0 @@ - -{% extends "auth_base.html" %} - -{% block title %}Create user{% endblock %} - -{% block content %} - - -
- -
-{% endblock %} diff --git a/cvat/apps/authentication/templates/user_profile.html b/cvat/apps/authentication/templates/user_profile.html deleted file mode 100644 index 37ea7d49..00000000 --- a/cvat/apps/authentication/templates/user_profile.html +++ /dev/null @@ -1,21 +0,0 @@ - -
- {% if user.is_authenticated %} - {% if user.ldap_user and 'thumbnailPhoto' in user.ldap_user.attrs %} - {# TODO insert photo from ldap #} - {% endif %} - - {% if user.first_name and user.last_name %} -

{{ user.first_name }} {{ user.last_name }}

- {% else %} -

{{ user.username }}

- {% endif %} -
- -
- {% endif %} -
\ No newline at end of file diff --git a/cvat/apps/authentication/tests.py b/cvat/apps/authentication/tests.py deleted file mode 100644 index 53bc3b7a..00000000 --- a/cvat/apps/authentication/tests.py +++ /dev/null @@ -1,9 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.test import TestCase - -# Create your tests here. - diff --git a/cvat/apps/authentication/urls.py b/cvat/apps/authentication/urls.py index e05d7340..a3752ad5 100644 --- a/cvat/apps/authentication/urls.py +++ b/cvat/apps/authentication/urls.py @@ -1,23 +1,28 @@ - # Copyright (C) 2018 Intel Corporation # # SPDX-License-Identifier: MIT from django.urls import path -from django.contrib.auth import views as auth_views from django.conf import settings - -from . import forms -from . import views +from rest_auth.views import ( + LoginView, LogoutView, PasswordChangeView, + PasswordResetView, PasswordResetConfirmView) +from rest_auth.registration.views import RegisterView +from .views import SigningView urlpatterns = [ - path('login', auth_views.LoginView.as_view(form_class=forms.AuthForm, - template_name='login.html', extra_context={'note': settings.AUTH_LOGIN_NOTE}), - name='login'), - path('logout', auth_views.LogoutView.as_view(next_page='login'), name='logout'), + path('login', LoginView.as_view(), name='rest_login'), + path('logout', LogoutView.as_view(), name='rest_logout'), + path('signing', SigningView.as_view(), name='signing') ] if settings.DJANGO_AUTH_TYPE == 'BASIC': urlpatterns += [ - path('register', views.register_user, name='register'), + path('register', RegisterView.as_view(), name='rest_register'), + path('password/reset', PasswordResetView.as_view(), + name='rest_password_reset'), + path('password/reset/confirm', PasswordResetConfirmView.as_view(), + name='rest_password_reset_confirm'), + path('password/change', PasswordChangeView.as_view(), + name='rest_password_change'), ] diff --git a/cvat/apps/authentication/views.py b/cvat/apps/authentication/views.py index b2497e2a..f38e3409 100644 --- a/cvat/apps/authentication/views.py +++ b/cvat/apps/authentication/views.py @@ -2,35 +2,17 @@ # # SPDX-License-Identifier: MIT -from django.shortcuts import render, redirect -from django.conf import settings -from django.contrib.auth import login, authenticate from rest_framework import views from rest_framework.exceptions import ValidationError from rest_framework.response import Response from furl import furl -from . import forms from . import signature from django.utils.decorators import method_decorator from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi -def register_user(request): - if request.method == 'POST': - form = forms.NewUserForm(request.POST) - if form.is_valid(): - form.save() - username = form.cleaned_data.get('username') - raw_password = form.cleaned_data.get('password1') - user = authenticate(username=username, password=raw_password) - login(request, user) - return redirect(settings.LOGIN_REDIRECT_URL) - else: - form = forms.NewUserForm() - return render(request, 'register.html', {'form': form}) - @method_decorator(name='post', decorator=swagger_auto_schema( request_body=openapi.Schema( type=openapi.TYPE_OBJECT, diff --git a/cvat/apps/documentation/admin.py b/cvat/apps/documentation/admin.py deleted file mode 100644 index af8dfc47..00000000 --- a/cvat/apps/documentation/admin.py +++ /dev/null @@ -1,9 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.contrib import admin - -# Register your models here. - diff --git a/cvat/apps/documentation/migrations/__init__.py b/cvat/apps/documentation/migrations/__init__.py deleted file mode 100644 index d8e62e54..00000000 --- a/cvat/apps/documentation/migrations/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - diff --git a/cvat/apps/documentation/models.py b/cvat/apps/documentation/models.py deleted file mode 100644 index cdf3b082..00000000 --- a/cvat/apps/documentation/models.py +++ /dev/null @@ -1,9 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.db import models - -# Create your models here. - diff --git a/cvat/apps/documentation/tests.py b/cvat/apps/documentation/tests.py deleted file mode 100644 index 53bc3b7a..00000000 --- a/cvat/apps/documentation/tests.py +++ /dev/null @@ -1,9 +0,0 @@ - -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT - -from django.test import TestCase - -# Create your tests here. - diff --git a/cvat/apps/engine/static/engine/base.css b/cvat/apps/engine/static/engine/base.css deleted file mode 100644 index 61115dd7..00000000 --- a/cvat/apps/engine/static/engine/base.css +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2018 Intel Corporation - * - * SPDX-License-Identifier: MIT - */ - -html { - background-color: #FFFFFF; - margin: 0px auto; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -@font-face { - font-family: BarlowSemiCondensed-Regular; - src: url(fonts/BarlowSemiCondensed-Regular.ttf); -} - -@font-face { - font-family: BarlowSemiCondensed-SemiBold; - src: url(fonts/BarlowSemiCondensed-SemiBold.ttf); -} - -@font-face { - font-family: BarlowSemiCondensed-Bold; - src: url(fonts/BarlowSemiCondensed-Bold.ttf); -} - -.regular { - font-family: BarlowSemiCondensed-Regular; -} - -.semiBold { - font-family: BarlowSemiCondensed-SemiBold; -} - -.bold { - font-family: BarlowSemiCondensed-Bold; -} - -.h2 { - font-size: 1.2em; -} - -.h1 { - font-size: 1.4em; -} - -.h3 { - font-size: 1.1em; -} - -.overlay { - position: fixed; - display: none; - width: 100%; - height: 100%; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: white; - z-index: 100; -} - -.modal { - position: fixed; - z-index: 10; - left: 0; - top: 0; - width: 100%; - height: 100%; - overflow: auto; - background-color: rgb(0,0,0); - background-color: rgba(0,0,0,0.4); -} - -.modal-content { - background-color: #FFFFFF; - margin: 15% auto; - padding: 20px; - border: 1px solid #888; - width: 80%; -} - -.close { - position: absolute; - right: 5px; - top: 5px; - width: 32px; - height: 32px; - opacity: 0.3; - } - - .close:hover { - opacity: 1; - } - - .close:before, .close:after { - position: absolute; - left: 15px; - content: ' '; - height: 22px; - width: 2px; - background-color: #333; - } - - .close:before { - transform: rotate(45deg); - } - - .close:after { - transform: rotate(-45deg); - } - -.tab { - overflow: hidden; - border: 1px solid black; - background-color: #B0C4DE; -} - -.tab button { - background-color: inherit; - float: left; - border: none; - outline: none; - cursor: pointer; - padding: 3px 0px; - transition: 0.3s; - -} - -.tab button:hover { - background-color: #81aee8; -} - -.tab button.active { - background-color: #ccc; -} - -.activeTabButton { - background-color: #81aee8 !important; -} - -.hidden { - display: none; -} - -.selectable { - -webkit-user-select: text; - -moz-user-select: text; - -ms-user-select: text; - user-select: text; -} - -.dropdown { - position: relative; -} - -.dropdown-content { - position: absolute; - background-color: #f1f1f1; - min-width: 160px; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); - z-index: 1; - list-style-type: none; - padding-inline-start: 0; - margin-left: 20%; - margin-top: -1%; -} - -.dropdown-content li { - color: black; - padding: 12px 16px; - text-decoration: none; - display: block; -} - -.dropdown-content li:hover {background-color: #ddd} \ No newline at end of file diff --git a/cvat/apps/engine/static/engine/fonts/BarlowSemiCondensed-Bold.ttf b/cvat/apps/engine/static/engine/fonts/BarlowSemiCondensed-Bold.ttf deleted file mode 100644 index 35b5a372f108b748b669f3a5247eececc9c12903..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91412 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 diff --git a/cvat/apps/engine/static/engine/fonts/BarlowSemiCondensed-Regular.ttf b/cvat/apps/engine/static/engine/fonts/BarlowSemiCondensed-Regular.ttf deleted file mode 100644 index ccdebedcd51e3e589fc28fa45ee852b88a8de194..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85532 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 z 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 YSbBl=w997J6yUC67oh8bDW8D>05sneW&i*H diff --git a/cvat/apps/engine/static/engine/fonts/BarlowSemiCondensed-SemiBold.ttf b/cvat/apps/engine/static/engine/fonts/BarlowSemiCondensed-SemiBold.ttf deleted file mode 100644 index 660b40256c7c938563cfdcdc7c1f1bcc673bc8af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89760 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 diff --git a/cvat/apps/engine/static/engine/fonts/README.md b/cvat/apps/engine/static/engine/fonts/README.md deleted file mode 100644 index 73a8fef3..00000000 --- a/cvat/apps/engine/static/engine/fonts/README.md +++ /dev/null @@ -1,95 +0,0 @@ -Fonts was downloaded from: https://fonts.google.com/specimen/Barlow+Semi+Condensed - -Copyright 2017 The Barlow Project Authors (https://github.com/jpt/barlow) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/cvat/apps/engine/static/engine/icons/README.md b/cvat/apps/engine/static/engine/icons/README.md deleted file mode 100644 index bad04298..00000000 --- a/cvat/apps/engine/static/engine/icons/README.md +++ /dev/null @@ -1,5 +0,0 @@ -Icons was downloaded from: https://icomoon.io/#preview-free [GitHub](https://github.com/Keyamoon/IcoMoon-Free) - -[License](https://github.com/Keyamoon/IcoMoon-Free/blob/master/License.txt): - -You can use this package under one of these two licenses: [CC BY 4.0](http://creativecommons.org/licenses/by/4.0/) or [GPL](http://www.gnu.org/licenses/gpl.html). diff --git a/cvat/apps/engine/static/engine/icons/copy.png b/cvat/apps/engine/static/engine/icons/copy.png deleted file mode 100644 index 5e76a30c5e38eb741746b1f2aa159500177deabe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 254 zcmVC zZs(iz)*t1%Sc}hU3wj$;09Wxe7w7vqA2k$=K$G6}!0KIQ&IprSR zEb7`jMd21NW5@u|xxqLPk{e!tu-xzfgyx0^Aarbh4Z!3^je5p`0Wcg0cK|ue!iP_z z`H?4j3SI+1g_*yn)~XH+fZ@Pz9YDd&dQY0Q4kQrR4tUT~38>HiRR91007*qoM6N<$ Ef)TE2!vFvP diff --git a/cvat/apps/engine/static/engine/icons/hidden-shape.png b/cvat/apps/engine/static/engine/icons/hidden-shape.png deleted file mode 100644 index 60fb969e58d73e0d861be843277f5414b37d7378..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 532 zcmV+v0_**WP)2dmxF25>9s zG9X+Q0_0xOT^&Ik0G_@kA@+FPw1yO&R7Il-fV?8^4YwDLXaE6BVPybBKYI{2K_K?h zNTdMk4trf>h`^!!nF3I7RQnJ{QKBaUpw&Kl41HC1WT`NKM@i>HxSnV{NxCoqieqbF z05qonFyWpD7B{&W0A0fWE$J%hX=Vo#Zzt%;0|0N5jshDIN01PvMjO*&5r}sH*t8!2 znB@me)s|>F7XbVP#92CRIN@k#CaK#t0$|J(EV~pTw;pDBRS_~xNrTt2BJ9$JK+uNE zT!|v44I|=g&Dt#{+FjWLRUIs7)}Fk*_4*P#w1yr*7@jClOwrhDB2_Pb;WK%i_JL2W(xsrnNM<`4t zUe{>gH4`$s0asbu+mJof1s`EzdO;B8aSHs3*C~hxAYBgxKYN~AiU=`6bP=gT+-3hF W{bK%rzCf4&0000I1y04tC_9duIb&`a;mPY?w{S+ zd9Po8-blmjP||^<4N0q#w$tbDl4g=VB|S=ds=anpaS*TzNq_@dV~~N!c_J2m(?{S^ z(&+$T4+N1LNmmhrhyb2G8;NVY?m9z=_DgD%2oP7mOLBiDXyw^@J4>?KPDs6TX=LQlt$7LN8U&E}!MwnGLQ=B6{t(uCx{OwBRTx9S%RiBX zhb04Gt0yU1S?Mj`ZSze2!!MUA$)RRXQ?KJ$xI zAZMty<{SimoLA9&@aOu(sJdq<2>eF~rokljA($>j5-z$7Bk#$XVj23@RmQJhYFbrNT1tH=AjdOSsIGZ$ zRU+Y7@BCPAq|b+=wVYD3`H;`&zh1m&Z?J1Qb3U)-rF{Z$-gmC$83_5h>V0TVg#DrB zuNn1TQlo|hUeh1u8*s_`2=EPRa0$s&O9Wt&7xJCSTSLGShXlX;_uO_ufQT=l1H8(9 Y0qsVj{)r9IfdBvi07*qoM6N<$f&j)gQUCw| diff --git a/cvat/apps/engine/static/engine/icons/initKeyFrame.png b/cvat/apps/engine/static/engine/icons/initKeyFrame.png deleted file mode 100644 index 62761e7cc41f363527b487c6f2e544fbfddf8061..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 668 zcmV;N0%QG&P)|ftl_% z@AcP?)Xz>N9ZTAlG?uhiT%Sw&lJp_zNz!xF?I>`NU{{g|PSA(}1|XLOu*N%G0InsS z_XwN@0?3`Dnn{#KrjE50wCyn5*!_&F~=?>-6kM*JQE&3O8a*~XY|!g0AT~kHeAK* z+hGp?iph2}=o%W_d;tPk%}7e(l@d^DZ;tv1?H+LHutg^?2l=p+!Wg)hbXr^{;XvGF zKgofvlIA#!T4Fv(IQ`JODwYMXYB;+iemWspXT=EVhPKE*? zaOoolfW0`U3MzMVBp3?7ORyM{gt-h%@& zV9-S{o09f-`}SkY#i9Q&0kD0Tq)QF76C7DrtZVv_n9%6i=pzLn>3qu#xX!u&a0fPU z!t0_y2nJV)Y&#%o4RI2Z zoG@D#U^Cc@7!P8++c#&*cVM|bgChX(yoPs+5dd6EItXG;9oI0Nngc+Dd?_WCYxagg zI5CY&uxf~fI7^Y{z^Wkr#A6PmZjBA`Pdo>}yRjga#7h7Xg7SLQkW4LI9wl9-+b<5X z4k92he00000NkvXXu0mjfRMX74 diff --git a/cvat/apps/engine/static/engine/icons/lock.png b/cvat/apps/engine/static/engine/icons/lock.png deleted file mode 100644 index c8174e56b4f446bca1ed940b39bfe9d8e18a79b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ22U5qkcif|7cO!(81S%MkY1=< zVr<={oU$b^!2FVYYmm~Vf<^M;C&HcIt2Ufk&$NK?M*c3whj~`RP-;n zBE_+PmjT1$Z=w!m&p!Qh+ka@sRPlSt$11HFZ1o!${5}fC@+jr~nm^3M3Vv11jMB_Pp6Md3Lk2abh#) z(rF9e90(#elCJ6))DhsO&rV`{{v+Lt+ungl)iUmFo%U9@7xeZOiL(U@pR(UOa{ z;G*tb&zTuUEF;Ko18LdgnAV^-%`F-wMZp4raFq@M0yS@9d z<>Ju4m_XQGO!B1$*#Rf4GuAZyNK9n(YP1OjBw0X;4YFynACc^gMx*CT}c8Q(2{@*L@ood?4C9P z*OJaFfISdIZYAC17~}|W(ibCf$*C8u!J@;I8Yu$!3V2HHuORJf@S7JC?7^yoVAW=V z4QfCl?wKv|1OWX=fCG#j_k~iNhV`BZB(|**mOxH+GMX2%xh8lYgt;{~P+%`Uumm_E z*>2+@fY$)~wU9V*4@pY!8Vm66-AT{Mxq4j$SJEocSP>QQEb*Mgs+B!Q7CVsM=EO|h zNC2QUv-_+f;Yt-EkM7K3FgGB8%#Y>|PLCyh1f|-lFob}Ye^Ipshjum(LvDN)TA41(TIX!lhqB ze>Er;w9GytS%?5yMk)TL`Q@4sOsNN5HY4u8E%9^Bh;9X_ZAi3Gs$v)6+cBqy%(QJF zAwlVk|B0f3q$!QAEb|=pkf^l-RcXI|sF~PlJ2jMgD3wK7n9?N U{#xv9p#T5?07*qoM6N<$f)4>5CjbBd diff --git a/cvat/apps/engine/static/engine/icons/non-keyframe.png b/cvat/apps/engine/static/engine/icons/non-keyframe.png deleted file mode 100644 index 619dd5bdbac98565d4c2fb9b67248f3011c84bff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 630 zcmV-+0*U>JP)>Y5g-CC0z`la5CQd0x9S?RGkbHcbk$X<-P!5a zU;oS)=$~ycrT<;~{<3wSX#rj&eM(yX4*;USFvok6npBuZ0is_t0RC=Lp%oxT@9H zPxfrQ27qHp>*lPFY$x_jZY_Hq_1VOrMgR~YIis-LMn*{lPVUk4+22)jB~g%P1nPzo zLr*~p(KJ*lWU+n6&IvNsz$_uM&b=h4pKa=!8B-)j!z6+|c^jqXxi2ZamWf6n)eH;_R=jO_g!*;@ME!)bmK+ zrsKGl3O_ZA^-}{lle91CR?=3+<9L{K)CTtgiul|LFbiA*U_>)M)A`ScW#-5G0Bhn2 z=;s1s9ndBKqMNfz1~94PbW^&J{k#g$2C{){U^id{Mvx8k!!|)uv=4YB8g6obfaIJ&fD3!} z$YX&E&;bwM&L6Yd@L~X+YM});3Gh&(Ay5efDh&ZA5O5j-y+GiuA&?3W-39(nzzN_^ zL!cH2)EWZ0Kp@u;fV9WpwBYdi#((-C^(g%ZhRG)+dK7Q{I3^-swt|PKzxTsrzyTH@IYW&F$n|vm3xeZA_rq lP@stkNH*Wns%*yJ%o7xZT0(vLCQASS002ovPDHLkV1o2ZbbtT= diff --git a/cvat/apps/engine/static/engine/icons/non-outside.png b/cvat/apps/engine/static/engine/icons/non-outside.png deleted file mode 100644 index 567710452b9e5b591eb36ca1ca4fd520a6bf3c27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410 zcmV;L0cHM)P)az0vo^x-5_iL8^8vzLAycNApJm`3Snb#^VP#U=Y2$y^(4zS zffFZA?1uwBfCtb5Pv9kditQmW?w!JSpjKjgSBZ7Bu3 zRBUGKc__)J5wSa>VLRI@0LiU=4wf?-JR;g(@Ouc09parQ-=O@h73dSY46%$9&_R3z z4j2=}N7hfWcLcC~2z~xNwAVI^_*d7kF#hU*copfqvEndYv%v(mEVnUZdmJOn-E*v8 z)`7@tXm>)N{y8R-xK7xJZBFd)-;!!eT%!zhSWDuoNpulgLHN^M?h)3wv3|!>*pcu# z*0|#zON-CZ3 zD=pZ=0|%f7eg^fxaTu!_K|qWt)Pivam?T#NXrBSJuK^SdAQAWgRyBaG3QVX0A!7>W zQ{;JGyYN6^7mmT4MNUw_i>{=$I?e!7)P-8{>Mo2U#kKJQVw|tpHhJ z9#?iz#CHR7+;7dl1HoQfG#Bolqp<=kgj-On00Z<3;Jw8965RqwA3_MP(iA*)ZM9!; ztsCMiq3t;M1&07*qoM6N<$f+_pO)&Kwi diff --git a/cvat/apps/engine/static/engine/icons/prevKeyFrame.png b/cvat/apps/engine/static/engine/icons/prevKeyFrame.png deleted file mode 100644 index 82b6520016ac264be28a465633040e1b6a634faf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 673 zcmV;S0$%-zP)Py-S+b5E~C4EYImh@8UwpXwauq#P`16pE`fyiYbmfh1t z;9Amo3*Z)Zwjw~*9i`Mr5x^PXUhc6Z z)Oah=U(#V%f8f?b7!pQ$_E$^*(2oe5I3i;gyO4Ank=XG{cmlEPKS9pYQ|Abx1|i#U zH)h`!djd#IwwobWDfmzla-U^bK!UKEk(A(7A>gXLJL%iV4)}fW{7^%}hl6~Wg~AkI z<7se0!oj%2Jh-i|BY~opn2(Z%MgT?@qf+Tp;E*5;kVu&i1(=%<;NCuk)!cK!(PUk~ z%_rsB>cjv7UjC6JVpV6$fa8}dO?Aaa5b$wnl7CrnKz$g-5TG*c21eY^xk}}v_z!U0 zQE9nx*aQN<4kXtb{tMioD$KPYu*wij*CGj5ehqygqDWAqn{1h+Tqs0j3{g`rb=pQB!wuebP)F3GPo#u^U+*P`n1u+5?X5`Y057sX8F8%sc7fs>00000NkvXX Hu0mjf!L~7y diff --git a/cvat/apps/engine/static/engine/icons/propagate.png b/cvat/apps/engine/static/engine/icons/propagate.png deleted file mode 100644 index a575441e63bd8ae262fab35da1ee504a8e0b1818..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 409 zcmV;K0cQS*P)z+422&XbOYFc5y~d80o|bO2CxBa0wb^iY|s&UFK73Jkz&aSmmk!BNU)vv+19f( z!^CYiu|9?XtN?tb1$+ZIwJfFuAPe(XHUfk}A^@83EfLHGNeILPU0KSJo z`T#t_<*|oBG=LW2W)KN5hHw~!0M8J1gJb{((7Tv*O+j^R@wPIDvB5iIA^OhLD34%l z5K}l`TviYc1*r<>ov7I`3gQ;l02qu*06g~}aaR1l2I3Wd1F!~gkw;LvfZ{si`fkN#-4Jzw z1rin>>H-PEXBk|5D<0hi+D+{Z#(x)dMXWa$yoL*`)UV}&Ru?>Ic&g$&$pR@qs=2_d zYa#$OkdUya9x$m>N8S-F7u4qd^|$PR`{SO0lLPz$a?!D&*$jGy00000NkvXXu0mjf D_rj#{ diff --git a/cvat/apps/engine/static/engine/icons/unlock.png b/cvat/apps/engine/static/engine/icons/unlock.png deleted file mode 100644 index 5b736985c3d3aecfd099a13e7e9d1ef82b3833d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJT2B|pkcif|7cO!(81S%MkY1=< zVr<={oMK|WLi%OD6Q^LNE$c(3?^h4(6}eEbj9~@Cw(byy%hE?*F0*J-QA>EMkuNx9 zCi|)LB5ViZ_cNS07-x6y#r_BDyG}*7++WUo<2Mt>2iXHn$1h4ep0r%hfq{`l07(2} fH%Qv~b=v#$Ro8MIn7Sqd9m3%0>gTe~DWM4fl2SxJ diff --git a/cvat/apps/engine/static/engine/js/3rdparty.patch b/cvat/apps/engine/static/engine/js/3rdparty.patch deleted file mode 100644 index 7fb96693..00000000 --- a/cvat/apps/engine/static/engine/js/3rdparty.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 11bd98c7f1ecf5a57b0eb327e6e86fa1e6ca33d9 Mon Sep 17 00:00:00 2001 -From: Boris Sekachev -Date: Tue, 25 Feb 2020 19:08:36 +0300 -Subject: [PATCH] Applied patch - ---- - .../static/engine/js/3rdparty/svg.draggable.js | 1 + - .../static/engine/js/3rdparty/svg.draw.js | 17 +++++++++++++++-- - .../static/engine/js/3rdparty/svg.resize.min.js | 2 +- - .../static/engine/js/3rdparty/svg.select.js | 5 ++++- - 4 files changed, 21 insertions(+), 4 deletions(-) - -diff --git a/cvat/apps/engine/static/engine/js/3rdparty/svg.draggable.js b/cvat/apps/engine/static/engine/js/3rdparty/svg.draggable.js -index d88abf5..aba474c 100644 ---- a/cvat/apps/engine/static/engine/js/3rdparty/svg.draggable.js -+++ b/cvat/apps/engine/static/engine/js/3rdparty/svg.draggable.js -@@ -109,6 +109,7 @@ - - // while dragging - DragHandler.prototype.drag = function(e){ -+ this.m = this.el.node.getScreenCTM().inverse(); - - var box = this.getBBox() - , p = this.transformPoint(e) -diff --git a/cvat/apps/engine/static/engine/js/3rdparty/svg.draw.js b/cvat/apps/engine/static/engine/js/3rdparty/svg.draw.js -index 68dbf2a..20a6917 100644 ---- a/cvat/apps/engine/static/engine/js/3rdparty/svg.draw.js -+++ b/cvat/apps/engine/static/engine/js/3rdparty/svg.draw.js -@@ -18,6 +18,7 @@ - this.startPoint = null; - this.lastUpdateCall = null; - this.options = {}; -+ this.set = new SVG.Set(); - - // Merge options and defaults - for (var i in this.el.draw.defaults) { -@@ -139,6 +140,8 @@ - // Call the calc-function which calculates the new position and size - this.calc(event); - -+ this.m = this.el.node.getScreenCTM().inverse(); -+ this.offset = { x: window.pageXOffset, y: window.pageYOffset }; - // Fire the `drawupdate`-event - this.el.fire('drawupdate', {event:event, p:this.p, m:this.m}); - }; -@@ -160,6 +163,16 @@ - this.el.fire('drawcancel'); - }; - -+ // Undo last drawed point -+ PaintHandler.prototype.undo = function () { -+ if (this.set.length()) { -+ this.set.members.splice(-1, 1)[0].remove(); -+ this.el.array().value.splice(-2, 1); -+ this.el.plot(this.el.array()); -+ this.el.fire('undopoint'); -+ } -+ }; -+ - // Calculate the corrected position when using `snapToGrid` - PaintHandler.prototype.snapToGrid = function (draw) { - -@@ -371,14 +384,14 @@ - - this.set.clear(); - -- for (var i = 0; i < array.length; ++i) { -+ for (var i = 0; i < array.length - 1; ++i) { - - this.p.x = array[i][0] - this.p.y = array[i][1] - - var p = this.p.matrixTransform(this.parent.node.getScreenCTM().inverse().multiply(this.el.node.getScreenCTM())); - -- this.set.add(this.parent.circle(5).stroke({width: 1}).fill('#ccc').center(p.x, p.y)); -+ this.set.add(this.parent.circle(5).stroke({width: 1}).fill('#ccc').center(p.x, p.y)).addClass("svg_draw_point"); - } - } - -diff --git a/cvat/apps/engine/static/engine/js/3rdparty/svg.resize.min.js b/cvat/apps/engine/static/engine/js/3rdparty/svg.resize.min.js -index 2dca34b..50ef3d3 100644 ---- a/cvat/apps/engine/static/engine/js/3rdparty/svg.resize.min.js -+++ b/cvat/apps/engine/static/engine/js/3rdparty/svg.resize.min.js -@@ -1 +1 @@ --/*! svg.resize.js v1.4.3 MIT*/;!function(){"use strict";(function(){function t(t){t.remember("_resizeHandler",this),this.el=t,this.parameters={},this.lastUpdateCall=null,this.p=t.doc().node.createSVGPoint()}t.prototype.transformPoint=function(t,e,i){return this.p.x=t-(this.offset.x-window.pageXOffset),this.p.y=e-(this.offset.y-window.pageYOffset),this.p.matrixTransform(i||this.m)},t.prototype._extractPosition=function(t){return{x:null!=t.clientX?t.clientX:t.touches[0].clientX,y:null!=t.clientY?t.clientY:t.touches[0].clientY}},t.prototype.init=function(t){var e=this;if(this.stop(),"stop"!==t){this.options={};for(var i in this.el.resize.defaults)this.options[i]=this.el.resize.defaults[i],void 0!==t[i]&&(this.options[i]=t[i]);this.el.on("lt.resize",function(t){e.resize(t||window.event)}),this.el.on("rt.resize",function(t){e.resize(t||window.event)}),this.el.on("rb.resize",function(t){e.resize(t||window.event)}),this.el.on("lb.resize",function(t){e.resize(t||window.event)}),this.el.on("t.resize",function(t){e.resize(t||window.event)}),this.el.on("r.resize",function(t){e.resize(t||window.event)}),this.el.on("b.resize",function(t){e.resize(t||window.event)}),this.el.on("l.resize",function(t){e.resize(t||window.event)}),this.el.on("rot.resize",function(t){e.resize(t||window.event)}),this.el.on("point.resize",function(t){e.resize(t||window.event)}),this.update()}},t.prototype.stop=function(){return this.el.off("lt.resize"),this.el.off("rt.resize"),this.el.off("rb.resize"),this.el.off("lb.resize"),this.el.off("t.resize"),this.el.off("r.resize"),this.el.off("b.resize"),this.el.off("l.resize"),this.el.off("rot.resize"),this.el.off("point.resize"),this},t.prototype.resize=function(t){var e=this;this.m=this.el.node.getScreenCTM().inverse(),this.offset={x:window.pageXOffset,y:window.pageYOffset};var i=this._extractPosition(t.detail.event);if(this.parameters={type:this.el.type,p:this.transformPoint(i.x,i.y),x:t.detail.x,y:t.detail.y,box:this.el.bbox(),rotation:this.el.transform().rotation},"text"===this.el.type&&(this.parameters.fontSize=this.el.attr()["font-size"]),void 0!==t.detail.i){var s=this.el.array().valueOf();this.parameters.i=t.detail.i,this.parameters.pointCoords=[s[t.detail.i][0],s[t.detail.i][1]]}switch(t.type){case"lt":this.calc=function(t,e){var i=this.snapToGrid(t,e);if(this.parameters.box.width-i[0]>0&&this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x+i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize-i[0]);i=this.checkAspectRatio(i),this.el.move(this.parameters.box.x+i[0],this.parameters.box.y+i[1]).size(this.parameters.box.width-i[0],this.parameters.box.height-i[1])}};break;case"rt":this.calc=function(t,e){var i=this.snapToGrid(t,e,2);if(this.parameters.box.width+i[0]>0&&this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x-i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize+i[0]);i=this.checkAspectRatio(i,!0),this.el.move(this.parameters.box.x,this.parameters.box.y+i[1]).size(this.parameters.box.width+i[0],this.parameters.box.height-i[1])}};break;case"rb":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.width+i[0]>0&&this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x-i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize+i[0]);i=this.checkAspectRatio(i),this.el.move(this.parameters.box.x,this.parameters.box.y).size(this.parameters.box.width+i[0],this.parameters.box.height+i[1])}};break;case"lb":this.calc=function(t,e){var i=this.snapToGrid(t,e,1);if(this.parameters.box.width-i[0]>0&&this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x+i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize-i[0]);i=this.checkAspectRatio(i,!0),this.el.move(this.parameters.box.x+i[0],this.parameters.box.y).size(this.parameters.box.width-i[0],this.parameters.box.height+i[1])}};break;case"t":this.calc=function(t,e){var i=this.snapToGrid(t,e,2);if(this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y+i[1]).height(this.parameters.box.height-i[1])}};break;case"r":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.width+i[0]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y).width(this.parameters.box.width+i[0])}};break;case"b":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y).height(this.parameters.box.height+i[1])}};break;case"l":this.calc=function(t,e){var i=this.snapToGrid(t,e,1);if(this.parameters.box.width-i[0]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x+i[0],this.parameters.box.y).width(this.parameters.box.width-i[0])}};break;case"rot":this.calc=function(t,e){var i={x:t+this.parameters.p.x,y:e+this.parameters.p.y},s=Math.atan2(this.parameters.p.y-this.parameters.box.y-this.parameters.box.height/2,this.parameters.p.x-this.parameters.box.x-this.parameters.box.width/2),r=Math.atan2(i.y-this.parameters.box.y-this.parameters.box.height/2,i.x-this.parameters.box.x-this.parameters.box.width/2),a=this.parameters.rotation+180*(r-s)/Math.PI+this.options.snapToAngle/2;this.el.center(this.parameters.box.cx,this.parameters.box.cy).rotate(a-a%this.options.snapToAngle,this.parameters.box.cx,this.parameters.box.cy)};break;case"point":this.calc=function(t,e){var i=this.snapToGrid(t,e,this.parameters.pointCoords[0],this.parameters.pointCoords[1]),s=this.el.array().valueOf();s[this.parameters.i][0]=this.parameters.pointCoords[0]+i[0],s[this.parameters.i][1]=this.parameters.pointCoords[1]+i[1],this.el.plot(s)}}this.el.fire("resizestart",{dx:this.parameters.x,dy:this.parameters.y,event:t}),SVG.on(window,"touchmove.resize",function(t){e.update(t||window.event)}),SVG.on(window,"touchend.resize",function(){e.done()}),SVG.on(window,"mousemove.resize",function(t){e.update(t||window.event)}),SVG.on(window,"mouseup.resize",function(){e.done()})},t.prototype.update=function(t){if(!t)return void(this.lastUpdateCall&&this.calc(this.lastUpdateCall[0],this.lastUpdateCall[1]));var e=this._extractPosition(t),i=this.transformPoint(e.x,e.y),s=i.x-this.parameters.p.x,r=i.y-this.parameters.p.y;this.lastUpdateCall=[s,r],this.calc(s,r),this.el.fire("resizing",{dx:s,dy:r,event:t})},t.prototype.done=function(){this.lastUpdateCall=null,SVG.off(window,"mousemove.resize"),SVG.off(window,"mouseup.resize"),SVG.off(window,"touchmove.resize"),SVG.off(window,"touchend.resize"),this.el.fire("resizedone")},t.prototype.snapToGrid=function(t,e,i,s){var r;return void 0!==s?r=[(i+t)%this.options.snapToGrid,(s+e)%this.options.snapToGrid]:(i=null==i?3:i,r=[(this.parameters.box.x+t+(1&i?0:this.parameters.box.width))%this.options.snapToGrid,(this.parameters.box.y+e+(2&i?0:this.parameters.box.height))%this.options.snapToGrid]),t<0&&(r[0]-=this.options.snapToGrid),e<0&&(r[1]-=this.options.snapToGrid),t-=Math.abs(r[0])o.maxX&&(t=o.maxX-r),void 0!==o.minY&&a+eo.maxY&&(e=o.maxY-a),[t,e]},t.prototype.checkAspectRatio=function(t,e){if(!this.options.saveAspectRatio)return t;var i=t.slice(),s=this.parameters.box.width/this.parameters.box.height,r=this.parameters.box.width+t[0],a=this.parameters.box.height-t[1],o=r/a;return os&&(i[0]=this.parameters.box.width-a*s,e&&(i[0]=-i[0])),i},SVG.extend(SVG.Element,{resize:function(e){return(this.remember("_resizeHandler")||new t(this)).init(e||{}),this}}),SVG.Element.prototype.resize.defaults={snapToAngle:.1,snapToGrid:1,constraint:{},saveAspectRatio:!1}}).call(this)}(); -+/*! svg.resize.js v1.4.3 MIT*/;!function(){"use strict";(function(){function t(t){t.remember("_resizeHandler",this),this.el=t,this.parameters={},this.lastUpdateCall=null,this.p=t.doc().node.createSVGPoint()}t.prototype.transformPoint=function(t,e,i){return this.p.x=t-(this.offset.x-window.pageXOffset),this.p.y=e-(this.offset.y-window.pageYOffset),this.p.matrixTransform(i||this.m)},t.prototype._extractPosition=function(t){return{x:null!=t.clientX?t.clientX:t.touches[0].clientX,y:null!=t.clientY?t.clientY:t.touches[0].clientY}},t.prototype.init=function(t){var e=this;if(this.stop(),"stop"!==t){this.options={};for(var i in this.el.resize.defaults)this.options[i]=this.el.resize.defaults[i],void 0!==t[i]&&(this.options[i]=t[i]);this.el.on("lt.resize",function(t){e.resize(t||window.event)}),this.el.on("rt.resize",function(t){e.resize(t||window.event)}),this.el.on("rb.resize",function(t){e.resize(t||window.event)}),this.el.on("lb.resize",function(t){e.resize(t||window.event)}),this.el.on("t.resize",function(t){e.resize(t||window.event)}),this.el.on("r.resize",function(t){e.resize(t||window.event)}),this.el.on("b.resize",function(t){e.resize(t||window.event)}),this.el.on("l.resize",function(t){e.resize(t||window.event)}),this.el.on("rot.resize",function(t){e.resize(t||window.event)}),this.el.on("point.resize",function(t){e.resize(t||window.event)}),this.update()}},t.prototype.stop=function(){return this.el.off("lt.resize"),this.el.off("rt.resize"),this.el.off("rb.resize"),this.el.off("lb.resize"),this.el.off("t.resize"),this.el.off("r.resize"),this.el.off("b.resize"),this.el.off("l.resize"),this.el.off("rot.resize"),this.el.off("point.resize"),this},t.prototype.resize=function(t){if(!t.detail.event.button){var e=this;this.m=this.el.node.getScreenCTM().inverse(),this.offset={x:window.pageXOffset,y:window.pageYOffset};var i=this._extractPosition(t.detail.event);if(this.parameters={type:this.el.type,p:this.transformPoint(i.x,i.y),x:t.detail.x,y:t.detail.y,box:this.el.bbox(),rotation:this.el.transform().rotation},"text"===this.el.type&&(this.parameters.fontSize=this.el.attr()["font-size"]),void 0!==t.detail.i){var s=this.el.array().valueOf();this.parameters.i=t.detail.i,this.parameters.pointCoords=[s[t.detail.i][0],s[t.detail.i][1]]}switch(t.type){case"lt":this.calc=function(t,e){var i=this.snapToGrid(t,e);if(this.parameters.box.width-i[0]>0&&this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x+i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize-i[0]);i=this.checkAspectRatio(i),this.el.move(this.parameters.box.x+i[0],this.parameters.box.y+i[1]).size(this.parameters.box.width-i[0],this.parameters.box.height-i[1])}};break;case"rt":this.calc=function(t,e){var i=this.snapToGrid(t,e,2);if(this.parameters.box.width+i[0]>0&&this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x-i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize+i[0]);i=this.checkAspectRatio(i,!0),this.el.move(this.parameters.box.x,this.parameters.box.y+i[1]).size(this.parameters.box.width+i[0],this.parameters.box.height-i[1])}};break;case"rb":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.width+i[0]>0&&this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x-i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize+i[0]);i=this.checkAspectRatio(i),this.el.move(this.parameters.box.x,this.parameters.box.y).size(this.parameters.box.width+i[0],this.parameters.box.height+i[1])}};break;case"lb":this.calc=function(t,e){var i=this.snapToGrid(t,e,1);if(this.parameters.box.width-i[0]>0&&this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x+i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize-i[0]);i=this.checkAspectRatio(i,!0),this.el.move(this.parameters.box.x+i[0],this.parameters.box.y).size(this.parameters.box.width-i[0],this.parameters.box.height+i[1])}};break;case"t":this.calc=function(t,e){var i=this.snapToGrid(t,e,2);if(this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y+i[1]).height(this.parameters.box.height-i[1])}};break;case"r":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.width+i[0]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y).width(this.parameters.box.width+i[0])}};break;case"b":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y).height(this.parameters.box.height+i[1])}};break;case"l":this.calc=function(t,e){var i=this.snapToGrid(t,e,1);if(this.parameters.box.width-i[0]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x+i[0],this.parameters.box.y).width(this.parameters.box.width-i[0])}};break;case"rot":this.calc=function(t,e){var i={x:t+this.parameters.p.x,y:e+this.parameters.p.y},s=Math.atan2(this.parameters.p.y-this.parameters.box.y-this.parameters.box.height/2,this.parameters.p.x-this.parameters.box.x-this.parameters.box.width/2),r=Math.atan2(i.y-this.parameters.box.y-this.parameters.box.height/2,i.x-this.parameters.box.x-this.parameters.box.width/2),a=this.parameters.rotation+180*(r-s)/Math.PI+this.options.snapToAngle/2;this.el.center(this.parameters.box.cx,this.parameters.box.cy).rotate(a-a%this.options.snapToAngle,this.parameters.box.cx,this.parameters.box.cy)};break;case"point":this.calc=function(t,e){var i=this.snapToGrid(t,e,this.parameters.pointCoords[0],this.parameters.pointCoords[1]),s=this.el.array().valueOf();s[this.parameters.i][0]=this.parameters.pointCoords[0]+i[0],s[this.parameters.i][1]=this.parameters.pointCoords[1]+i[1],this.el.plot(s)}}this.el.fire("resizestart",{dx:this.parameters.x,dy:this.parameters.y,event:t}),SVG.on(window,"touchmove.resize",function(t){e.update(t||window.event)}),SVG.on(window,"touchend.resize",function(){e.done()}),SVG.on(window,"mousemove.resize",function(t){e.update(t||window.event)}),SVG.on(window,"mouseup.resize",function(){e.done()})}},t.prototype.update=function(t){if(!t)return void(this.lastUpdateCall&&this.calc(this.lastUpdateCall[0],this.lastUpdateCall[1]));this.m=this.el.node.getScreenCTM().inverse();var e=this._extractPosition(t),i=this.transformPoint(e.x,e.y),s=i.x-this.parameters.p.x,r=i.y-this.parameters.p.y;this.lastUpdateCall=[s,r],this.calc(s,r),this.el.fire("resizing",{dx:s,dy:r,event:t})},t.prototype.done=function(){this.lastUpdateCall=null,SVG.off(window,"mousemove.resize"),SVG.off(window,"mouseup.resize"),SVG.off(window,"touchmove.resize"),SVG.off(window,"touchend.resize"),this.el.fire("resizedone")},t.prototype.snapToGrid=function(t,e,i,s){var r;return void 0!==s?r=[(i+t)%this.options.snapToGrid,(s+e)%this.options.snapToGrid]:(i=null==i?3:i,r=[(this.parameters.box.x+t+(1&i?0:this.parameters.box.width))%this.options.snapToGrid,(this.parameters.box.y+e+(2&i?0:this.parameters.box.height))%this.options.snapToGrid]),t<0&&(r[0]-=this.options.snapToGrid),e<0&&(r[1]-=this.options.snapToGrid),t-=Math.abs(r[0])o.maxX&&(t=o.maxX-r),void 0!==o.minY&&a+eo.maxY&&(e=o.maxY-a),[t,e]},t.prototype.checkAspectRatio=function(t,e){if(!this.options.saveAspectRatio)return t;var i=t.slice(),s=this.parameters.box.width/this.parameters.box.height,r=this.parameters.box.width+t[0],a=this.parameters.box.height-t[1],o=r/a;return os&&(i[0]=this.parameters.box.width-a*s,e&&(i[0]=-i[0])),i},SVG.extend(SVG.Element,{resize:function(e){return(this.remember("_resizeHandler")||new t(this)).init(e||{}),this}}),SVG.Element.prototype.resize.defaults={snapToAngle:.1,snapToGrid:1,constraint:{},saveAspectRatio:!1}}).call(this)}(); -\ No newline at end of file -diff --git a/cvat/apps/engine/static/engine/js/3rdparty/svg.select.js b/cvat/apps/engine/static/engine/js/3rdparty/svg.select.js -index 47e07bd..cee6d34 100644 ---- a/cvat/apps/engine/static/engine/js/3rdparty/svg.select.js -+++ b/cvat/apps/engine/static/engine/js/3rdparty/svg.select.js -@@ -160,6 +160,7 @@ SelectHandler.prototype.drawPoints = function () { - ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; - ev.stopPropagation(); - -+ if (ev.which != 1) return false; - var x = ev.pageX || ev.touches[0].pageX; - var y = ev.pageY || ev.touches[0].pageY; - _this.el.fire('point', {x: x, y: y, i: k, event: ev}); -@@ -361,6 +362,7 @@ SelectHandler.prototype.cleanup = function () { - // stop watching the element, remove the selection - this.rectSelection.set.each(function () { - this.remove(); -+ SVG.off(this.node); - }); - - this.rectSelection.set.clear(); -@@ -371,6 +373,7 @@ SelectHandler.prototype.cleanup = function () { - // Remove all points, clear the set, stop watching the element - this.pointSelection.set.each(function () { - this.remove(); -+ SVG.off(this.node); - }); - - this.pointSelection.set.clear(); -@@ -379,8 +382,8 @@ SelectHandler.prototype.cleanup = function () { - - if (!this.pointSelection.isSelected && !this.rectSelection.isSelected) { - this.nested.remove(); -+ SVG.off(this.nested.node); - delete this.nested; -- - } - }; - --- -2.19.1 - diff --git a/cvat/apps/engine/static/engine/js/3rdparty/Decoder.worker.js b/cvat/apps/engine/static/engine/js/3rdparty/Decoder.worker.js deleted file mode 100644 index 23f3206a..00000000 --- a/cvat/apps/engine/static/engine/js/3rdparty/Decoder.worker.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(e){var n={};function t(r){if(n[r])return n[r].exports;var a=n[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,t),a.l=!0,a.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var a in e)t.d(r,a,function(n){return e[n]}.bind(null,a));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=0)}([function(e,n,t){var r,a,i;a=[],void 0===(i="function"==typeof(r=function(){var e;!function(){(e=this)||("undefined"!=typeof window?e=window:"undefined"!=typeof self&&(e=self))}();var n=function(n,t){var r,a=void 0!==a?a:{},i={};for(r in a)a.hasOwnProperty(r)&&(i[r]=a[r]);var o,f=[],u=!1,s=!0,c="";(u||s)&&(s?c=self.location.href:document.currentScript&&(c=document.currentScript.src),c=0!==c.indexOf("blob:")?c.substr(0,c.lastIndexOf("/")+1):"",s&&(o=function(e){var n=new XMLHttpRequest;return n.open("GET",e,!1),n.responseType="arraybuffer",n.send(null),new Uint8Array(n.response)}));var d=a.print||console.log.bind(console),l=a.printErr||console.warn.bind(console);for(r in i)i.hasOwnProperty(r)&&(a[r]=i[r]);i=null,a.arguments&&(f=a.arguments),a.thisProgram&&a.thisProgram,a.quit&&a.quit;var p,y,h={"f64-rem":function(e,n){return e%n},debugger:function(){}};new Array(0),a.wasmBinary&&(p=a.wasmBinary),a.noExitRuntime&&a.noExitRuntime,"object"!=typeof WebAssembly&&l("no native wasm support detected");var v,m,g,b,w=new WebAssembly.Table({initial:10,maximum:10,element:"anyfunc"}),A=!1,M="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0;function P(e,n,t){for(var r=n+t,a=n;e[a]&&!(a>=r);)++a;if(a-n>16&&e.subarray&&M)return M.decode(e.subarray(n,a));for(var i="";n>10,56320|1023&s)}}else i+=String.fromCharCode((31&o)<<6|f)}else i+=String.fromCharCode(o)}return i}"undefined"!=typeof TextDecoder&&new TextDecoder("utf-16le");var D,S=a.TOTAL_MEMORY||104857600;function _(e){for(;e.length>0;){var n=e.shift();if("function"!=typeof n){var t=n.func;"number"==typeof t?void 0===n.arg?a.dynCall_v(t):a.dynCall_vi(t,n.arg):t(void 0===n.arg?null:n.arg)}else n()}}(y=a.wasmMemory?a.wasmMemory:new WebAssembly.Memory({initial:S/65536,maximum:S/65536}))&&(v=y.buffer),S=v.byteLength,v=D=v,a.HEAP8=m=new Int8Array(D),a.HEAP16=new Int16Array(D),a.HEAP32=b=new Int32Array(D),a.HEAPU8=g=new Uint8Array(D),a.HEAPU16=new Uint16Array(D),a.HEAPU32=new Uint32Array(D),a.HEAPF32=new Float32Array(D),a.HEAPF64=new Float64Array(D),b[2748]=5254064;var R=[],U=[],E=[],I=[],O=0,x=null,B=null;function C(e){throw a.onAbort&&a.onAbort(e),d(e+=""),l(e),A=!0,e="abort("+e+"). Build with -s ASSERTIONS=1 for more info.",new WebAssembly.RuntimeError(e)}a.preloadedImages={},a.preloadedAudios={};var H="data:application/octet-stream;base64,";function T(e){return String.prototype.startsWith?e.startsWith(H):0===e.indexOf(H)}var W,j="avc.wasm";function F(){try{if(p)return new Uint8Array(p);if(o)return o(j);throw"both async and sync fetching of the wasm failed"}catch(e){C(e)}}T(j)||(W=j,j=a.locateFile?a.locateFile(W,c):c+W),a.asm=function(){var e={env:V,wasi_unstable:V,global:{NaN:NaN,Infinity:1/0},"global.Math":Math,asm2wasm:h};function n(e,n){var t=e.exports;a.asm=t,function(e){if(O--,a.monitorRunDependencies&&a.monitorRunDependencies(O),0==O&&(null!==x&&(clearInterval(x),x=null),B)){var n=B;B=null,n()}}()}function t(e){n(e.instance)}function r(n){return(p||!u&&!s||"function"!=typeof fetch?new Promise((function(e,n){e(F())})):fetch(j,{credentials:"same-origin"}).then((function(e){if(!e.ok)throw"failed to load wasm binary file at '"+j+"'";return e.arrayBuffer()})).catch((function(){return F()}))).then((function(n){return WebAssembly.instantiate(n,e)})).then(n,(function(e){l("failed to asynchronously prepare wasm: "+e),C(e)}))}if(O++,a.monitorRunDependencies&&a.monitorRunDependencies(O),a.instantiateWasm)try{return a.instantiateWasm(e,n)}catch(e){return l("Module.instantiateWasm callback failed with error: "+e),!1}return function(){if(p||"function"!=typeof WebAssembly.instantiateStreaming||T(j)||"function"!=typeof fetch)return r(t);fetch(j,{credentials:"same-origin"}).then((function(n){return WebAssembly.instantiateStreaming(n,e).then(t,(function(e){l("wasm streaming compile failed: "+e),l("falling back to ArrayBuffer instantiation"),r(t)}))}))}(),{}};var N={buffers:[null,[],[]],printChar:function(e,n){var t=N.buffers[e];0===n||10===n?((1===e?d:l)(P(t,0)),t.length=0):t.push(n)},varargs:0,get:function(e){return N.varargs+=4,b[N.varargs-4>>2]},getStr:function(){var e,n;return(e=N.get())?P(g,e,n):""},get64:function(){var e=N.get();return N.get(),e},getZero:function(){N.get()}};function k(e,n,t,r){try{for(var a=0,i=0;i>2],f=b[n+(8*i+4)>>2],u=0;u>2]=a,0}catch(e){return"undefined"!=typeof FS&&e instanceof FS.ErrnoError||C(e),e.errno}}function z(){n()}function L(e,n,r){t(e,n,r)}a._broadwayOnHeadersDecoded=z,a._broadwayOnPictureDecoded=L;var q,G,V={g:function(){return k.apply(null,arguments)},__memory_base:1024,__table_base:0,f:z,e:L,b:function(){return m.length},d:function(e,n,t){g.set(g.subarray(n,n+t),e)},a:function(e){C("OOM")},c:C,memory:y,table:w},X=a.asm({},V,v);function Y(e){function n(){q||(q=!0,A||(_(U),_(E),a.onRuntimeInitialized&&a.onRuntimeInitialized(),function(){if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;)e=a.postRun.shift(),I.unshift(e);var e;_(I)}()))}e=e||f,O>0||(function(){if(a.preRun)for("function"==typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)e=a.preRun.shift(),R.unshift(e);var e;_(R)}(),O>0||(a.setStatus?(a.setStatus("Running..."),setTimeout((function(){setTimeout((function(){a.setStatus("")}),1),n()}),1)):n()))}if(a.asm=X,a._broadwayCreateStream=function(){return a.asm.h.apply(null,arguments)},a._broadwayExit=function(){return a.asm.i.apply(null,arguments)},a._broadwayGetMajorVersion=function(){return a.asm.j.apply(null,arguments)},a._broadwayGetMinorVersion=function(){return a.asm.k.apply(null,arguments)},a._broadwayInit=function(){return a.asm.l.apply(null,arguments)},a._broadwayPlayStream=function(){return a.asm.m.apply(null,arguments)},a.asm=X,B=function e(){q||Y(),q||(B=e)},a.run=Y,a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);a.preInit.length>0;)a.preInit.pop()();Y(),void 0!==e&&e.Module&&(G=e.Module),void 0!==a&&(G=a),G._broadwayOnHeadersDecoded=n,G._broadwayOnPictureDecoded=t;var Z,J=!1;return G.onRuntimeInitialized=function(){J=!0,Z&&Z(G)},function(e){J?e(G):Z=e}};return function(){"use strict";var t=function(){return(new Date).getTime()};"undefined"!=typeof performance&&performance.now&&(t=function(){return performance.now()});var r=function(e){var r;this.options=e||{},this.now=t;var a,o,f=function(e,n,o){var f,u=this.pictureBuffers[e];u||(u=this.pictureBuffers[e]=a(e,n*o*3/2));var s=!1;if(this.infoAr.length&&(s=!0,f=this.infoAr),this.infoAr=[],this.options.rgb){r||(r=i(n,o)),r.inp.set(u),r.doit();var c=new Uint8Array(r.outSize);return c.set(r.out),s&&(f[0].finishDecoding=t()),void this.onPictureDecoded(c,n,o,f)}s&&(f[0].finishDecoding=t()),this.onPictureDecoded(u,n,o,f)}.bind(this);this.options.sliceMode&&(f=function(e,n,r,i){var f=this.pictureBuffers[e];f||(f=this.pictureBuffers[e]=a(e,n*r*3/2));var u,s=this.pictureBuffers[i];s||(s=this.pictureBuffers[i]=o(i,18)),this.infoAr.length&&(u=this.infoAr),this.infoAr=[],u[0].finishDecoding=t();for(var c=[],d=0;d<20;++d)c.push(s[d]);u[0].sliceInfoAr=c,this.onPictureDecoded(f,n,r,u)}.bind(this));var u=n.apply({},[function(){},f]),s=this;this.onPictureDecoded=function(e,n,t,r){},this.onDecoderReady=function(){};var c=[];this.decode=function(e,n,t){c.push([e,n,t])},u((function(e){e.HEAP8;var n=e.HEAPU8;e.HEAP16,e.HEAP32,e._broadwayInit(),a=function(e,t){return n.subarray(e,e+t)},o=function(e,t){return new Uint32Array(n.buffer,e,t)},s.streamBuffer=a(e._broadwayCreateStream(1048576),1048576),s.pictureBuffers={},s.infoAr=[];var r=0;if(s.options.sliceMode?(r=s.options.sliceNum,s.decode=function(n,a,i){s.infoAr.push(a),a.startDecoding=t();var o,f=a.nals;if(!f){f=[],a.nals=f;var u=n.length,c=!1,d=0,l=0;for(o=0;o>2,f=i+o+o,u=n*t*4,s=f+u+4*Math.pow(2,24),c=Math.pow(2,24),d=c;d>2;m=r(r(l,p)|0,4)|0;v=(y+h|0)+h|0;b=0;g=b+m|0;A=g+v|0;a=~~+o(+2,+24);a=r(a,4)|0;for(t=0|0;(t|0)<(a|0)|0;t=t+4|0){d[(A+t|0)>>2]=0}}function P(){var e=0;var n=0;var t=0;var r=0;var a=0;var i=0;var o=0;var f=0;var u=0;var c=0;var v=0;var m=0;var M=0;var P=0;M=b|0;e=g|0;n=e+y|0|0;t=n+h|0;for(u=0;(u|0)<(p|0);u=u+2|0){v=n;m=t;for(c=0;(c|0)<(l|0);c=c+2|0){r=s[e>>0]|0;a=s[(e+l|0)>>0]|0;i=s[n>>0]|0;o=s[t>>0]|0;P=((r<<16|0)+(i<<8|0)|0)+o|0;f=d[(A>>2)+P|0]|0;if(f){}else{f=D(r,i,o)|0;d[(A>>2)+P|0]=f|0}d[M>>2]=f;P=((a<<16|0)+(i<<8|0)|0)+o|0;f=d[(A>>2)+P|0]|0;if(f){}else{f=D(a,i,o)|0;d[(A>>2)+P|0]=f|0}d[(M+w|0)>>2]=f;M=M+4|0;e=e+1|0;r=s[e>>0]|0;a=s[(e+l|0)>>0]|0;P=((r<<16|0)+(i<<8|0)|0)+o|0;f=d[(A>>2)+P|0]|0;if(f){}else{f=D(r,i,o)|0;d[(A>>2)+P|0]=f|0}d[M>>2]=f;P=((a<<16|0)+(i<<8|0)|0)+o|0;f=d[(A>>2)+P|0]|0;if(f){}else{f=D(a,i,o)|0;d[(A>>2)+P|0]=f|0}d[(M+w|0)>>2]=f;M=M+4|0;e=e+1|0;n=n+1|0;t=t+1|0}M=M+w|0;e=e+l|0}}function D(e,n,t){e=e|0;n=n|0;t=t|0;var o=0;var f=0;var u=0;var s=0;var c=0;var d=0;var l=0;var p=0;var y=0;c=r(1192,e-16|0)|0;d=r(1634,t-128|0)|0;l=r(832,t-128|0)|0;p=r(400,n-128|0)|0;y=r(2066,n-128|0)|0;o=(c+d|0)>>10|0;f=((c-l|0)-p|0)>>10|0;u=(c+y|0)>>10|0;if((o&255|0)!=(o|0)|0){o=a(255,i(0,o|0)|0)|0}if((f&255|0)!=(f|0)|0){f=a(255,i(0,f|0)|0)|0}if((u&255|0)!=(u|0)|0){u=a(255,i(0,u|0)|0)|0}s=255;s=s<<8|0;s=s+u|0;s=s<<8|0;s=s+f|0;s=s<<8|0;s=s+o|0;return s|0}return{init:M,doit:P}}(e,{},l);return p.init(n,t),a[r]=p,p.heap=l,p.out=new Uint8Array(l,0,u),p.inp=new Uint8Array(l,u,f),p.outSize=u,p};if("undefined"!=typeof self){var o,f,u,s,c,d,l=!1,p=!1,y=!1,h=0,v=0,m=0,g=0,b=[],w=[],A=function(e){if(w.length){for(var n=w.shift();n&&n.byteLength!==e;)n=w.shift();if(n)return n}return new ArrayBuffer(e)},M=function(e,n,t,r,a){var i=function(t,a){var i=0;for(i=0;i<16;++i){var o=t+r*i,f=a+r*i;n.set(e.subarray(o,f),o)}},o=function(t,a){var i=0;for(i=0;i<8;++i){var o=t+r/2*i,f=a+r/2*i;n.set(e.subarray(o,f),o)}},f=function(t,r){n.set(e.subarray(t,r),t)},u=t[0],s=t[1];s>0&&(i(u,s),o(t[2],t[3]),o(t[4],t[5])),u=t[6],(s=t[7])>0&&(i(u,s),o(t[8],t[9]),o(t[10],t[11])),u=t[12],(s=t[15])>0&&(f(u,s),f(t[13],t[16]),f(t[14],t[17]))},P=function(e){m=(v=e)-1};self.addEventListener("message",(function(e){if(l){if(p&&e.data.reuse&&w.push(e.data.reuse),e.data.buf)return void(y&&0!==g?b.push(e.data):o.decode(new Uint8Array(e.data.buf,e.data.offset||0,e.data.length),e.data.info,(function(){y&&h!==m&&postMessage(e.data,[e.data.buf])})));if(e.data.slice){var n=t();if(M(new Uint8Array(e.data.slice),u,e.data.infos[0].sliceInfoAr,e.data.width,e.data.height),e.data.theOne&&(M(u,new Uint8Array(e.data.slice),f,e.data.width,e.data.height),d>e.data.infos[0].timeDecoding&&(e.data.infos[0].timeDecoding=d),e.data.infos[0].timeCopy+=t()-n),postMessage(e.data,[e.data.slice]),0==(g-=1)&&b.length){var a=b.shift();o.decode(new Uint8Array(a.buf,a.offset||0,a.length),a.info,(function(){y&&h!==m&&postMessage(a,[a.buf])}))}return}if(e.data.setSliceCnt)return void P(e.data.sliceCnt)}else e.data&&"Broadway.js - Worker init"===e.data.type&&(l=!0,o=new r(e.data.options),e.data.options.sliceMode?(p=!0,y=!0,h=e.data.options.sliceNum,P(e.data.options.sliceCnt),o.onPictureDecoded=function(e,n,t,r){var a=new Uint8Array(A(e.length));M(e,a,r[0].sliceInfoAr,n),s=r[0].startDecoding,c=r[0].finishDecoding,d=c-s,r[0].timeDecoding=d,r[0].timeCopy=0,postMessage({slice:a.buffer,sliceNum:h,width:n,height:t,infos:r},[a.buffer]),g=v-1,u=e,f=r[0].sliceInfoAr}):e.data.options.reuseMemory?(p=!0,o.onPictureDecoded=function(e,n,t,r){var a=new Uint8Array(A(e.length));a.set(e,0,e.length),postMessage({buf:a.buffer,length:e.length,width:n,height:t,infos:r},[a.buffer])}):o.onPictureDecoded=function(e,n,t,r){e&&(e=new Uint8Array(e));var a=new Uint8Array(e.length);a.set(e,0,e.length),postMessage({buf:a.buffer,length:e.length,width:n,height:t,infos:r},[a.buffer])},postMessage({consoleLog:"broadway worker initialized"}))}),!1)}return r.nowValue=t,r}()})?r.apply(n,a):r)||(e.exports=i)}]); -//# sourceMappingURL=Decoder.worker.js.map \ No newline at end of file diff --git a/cvat/apps/engine/static/engine/js/3rdparty/avc.wasm b/cvat/apps/engine/static/engine/js/3rdparty/avc.wasm deleted file mode 100644 index 559b2b3157a0fccbcf3128e8a5d4e371654d2d3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 126815 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 - * License GNU AGPLv3 - */if(function(window,module){"use strict";var defiant={is_ie:/(msie|trident)/i.test(navigator.userAgent),is_safari:/safari/i.test(navigator.userAgent),env:"production",xml_decl:'',namespace:'xmlns:d="defiant-namespace"',tabsize:4,snapshots:{},node:{},renderXml:function(e,t){var n=new window.XSLTProcessor,r=document.createElement("span"),a='//xsl:template[@name="'+e+'"]',s=this.node.selectSingleNode(this.xsl_template,a);return(s=this.node.selectSingleNode(this.xsl_template,a)).setAttribute("match","/"),n.importStylesheet(this.xsl_template),r.appendChild(n.transformToFragment(t,document)),s.removeAttribute("match"),r.innerHTML},render:function(e,t){var n,r,a,s,o=new window.XSLTProcessor,i=document.createElement("span"),l={match:"/"};switch(typeof e){case"object":this.extend(l,e),l.data||(l.data=t);break;case"string":l.template=e,l.data=t;break;default:throw"error"}if(l.data=l.data.nodeType?l.data:defiant.json.toXML(l.data),n='//xsl:template[@name="'+l.template+'"]',this.xsl_template||this.gatherTemplates(),l.sorter&&(s=this.node.selectSingleNode(this.xsl_template,n+"//xsl:for-each//xsl:sort"))&&(l.sorter.order&&s.setAttribute("order",l.sorter.order),l.sorter.select&&s.setAttribute("select",l.sorter.select),s.setAttribute("data-type",l.sorter.type||"text")),(a=this.node.selectSingleNode(this.xsl_template,n)).setAttribute("match",l.match),o.importStylesheet(this.xsl_template),i.appendChild(o.transformToFragment(l.data,document)),a.removeAttribute("match"),this.is_safari)for(var c=0,d=(r=i.getElementsByTagName("script")).length;c"+t.replace(/defiant:(\w+)/g,"$1")+"")},registerTemplate:function(e){this.xsl_template=this.xmlFromString('"+e.replace(/defiant:(\w+)/g,"$1")+"")},getSnapshot:function(e,t){return this.json.toXML(e,t||!0)},createSnapshot:function(e,t){var n=this,r="snapshot_"+Date.now();this.json.toXML(e,function(e){n.snapshots[r]=e,t(r)})},getFacets:function(e,t){var n,r,a,s,o,i,l=e.constructor===String&&"snapshot_"===e.slice(0,9)?this.snapshots[e].doc:defiant.json.toXML(e),c=l.cloneNode(!0),d={},u={},p=0,h=function(e){var t=e.childNodes.length;switch(e.nodeType){case 1:t>=p&&(p=t,r=e);case 9:e.childNodes.map(function(e){return h(e)})}};for(i in h(l),r.childNodes.map(function(e){u[e.nodeName]||(u[e.nodeName]=1),u[e.nodeName]++}),p=0,u)p<=u[i]&&(p=u[i],o=i);return this.createFacetTemplate(t),s=defiant.node.selectSingleNode(c,'//*[@d:mi="'+r.getAttribute("d:mi")+'"]'),defiant.node.selectNodes(c,'//*[@d:mi="'+r.getAttribute("d:mi")+'"]/'+o).map(function(e){return e.parentNode.removeChild(e)}),a=defiant.node.selectNodes(l,'//*[@d:mi="'+r.getAttribute("d:mi")+'"]/'+o),n=a.length-1,a.map(function(e,t){if(s.appendChild(e.cloneNode(!0)),t%50==49||t===n){var a=defiant.render("facets",c).replace(/\n|\t/g,"").replace(/"": 0,?/g,"").replace(/,\}/g,"}"),i=JSON.parse(a);d=defiant.concatFacet(i,d),defiant.node.selectNodes(c,'//*[@d:mi="'+r.getAttribute("d:mi")+'"]/'+o).map(function(e){return e.parentNode.removeChild(e)})}}),d},createFacetTemplate:function(e){var t,n,r=[],a=[];for(n in e)r.push(''),a.push('"'+n+'": {"": '+',}'.replace(/\n|\t/g,""));t=r.join("")+'{'+a.join(",")+"}",this.registerTemplate(t)},xmlFromString:function(e){var t;return null===(e=e.replace(/>\s{1,}<")).trim().match(/<\?xml/)&&(e=this.xml_decl+e),"ActiveXObject"in window?((t=new ActiveXObject("Msxml2.DOMDocument")).loadXML(e),t.setProperty("SelectionNamespaces",this.namespace),-1===e.indexOf("xsl:stylesheet")&&t.setProperty("SelectionLanguage","XPath")):t=(new DOMParser).parseFromString(e,"text/xml"),t},concatFacet:function(e,t){for(var n in t)e[n]&&"object"==typeof t[n]?this.concatFacet(e[n],t[n]):e[n]=(e[n]||0)+t[n];return e},extend:function(e,t){for(var n in t)e[n]&&"object"==typeof t[n]?this.extend(e[n],t[n]):e[n]=t[n];return e},node:{selectNodes:function(e,t){if(e.evaluate){for(var n=e.createNSResolver(e.documentElement),r=e.evaluate(t,e,n,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null),a=[],s=0,o=r.snapshotLength;s0?n[0]:null}return e.selectSingleNode(t)},prettyPrint:function(e){var t,n=defiant,r=n.tabsize,a=n.xml_decl.toLowerCase();t=n.is_ie?e.xml:(new XMLSerializer).serializeToString(e),"development"!==n.env&&(t=t.replace(/ \w+\:d=".*?"| d\:\w+=".*?"/g,""));for(var s,o,i=t.trim().replace(/(>)\s*(<)(\/*)/g,"$1\n$2$3").split("\n"),l=-1,c=0,d=i.length;c/g),o=null!==i[c].match(/<\/[\w\:]+>/g),null!==i[c].match(/<.*?\/>/g)&&(s=o=!0),s&&l++,i[c]=String().fill(l,"\t")+i[c],s&&o&&l--,!s&&o&&l--);return i.join("\n").replace(/\t/g,String().fill(r," "))},toJSON:function(e,t){var n=function(e){var t,r,a,s,o,i,l,c,d,u,p={},h=window;switch(e.nodeType){case 1:for("Array"===(o=e.getAttribute("d:constr"))?p=[]:"String"===o&&""===e.textContent&&(p=""),c=0,d=(t=e.attributes).length;c/,rx_constructor:/<(.+?)( d:contr=".*?")>/,rx_namespace:/ xmlns\:d="defiant\-namespace"/,rx_data:/(<.+?>)(.*?)(<\/d:data>)/i,rx_function:/function (\w+)/i,namespace:'xmlns:d="defiant-namespace"',to_xml_str:function(e){return{str:this.hash_to_xml(null,e),map:this.map}},hash_to_xml:function(e,t,n){var r,a,s,o,i,l,c,d,u,p=t.constructor===Array,h=this,m=[],f=[],g=function(t,r){if(null!==(a=r[t])&&void 0!==a&&"NaN"!==a.toString()||(a=null),o="@"===t.slice(0,1),(i=n?e:t)==+i&&r.constructor!==Object&&(i="d:item"),null===a?(l=null,c=!1):(l=a.constructor,c=l.toString().match(h.rx_function)[1]),o)f.push(i.slice(1)+'="'+h.escape_xml(a)+'"'),"String"!==c&&f.push("d:"+i.slice(1)+'="'+c+'"');else if(null===a)m.push(h.scalar_to_xml(i,a));else switch(l){case Function:throw"JSON data should not contain functions. Please check your structure.";case Object:m.push(h.hash_to_xml(i,a));break;case Array:if(t===i){if(s=a.constructor===Array)for(d=a.length;d--;)null!==a[d]&&a[d]&&a[d].constructor!==Array||(s=!0),s||a[d].constructor!==Object||(s=!0);m.push(h.scalar_to_xml(i,a,s));break}case String:if("string"==typeof a&&(a=a.toString().replace(/\&/g,"&").replace(/\r|\n/g," ")),"#text"===i){h.map.push(r),f.push('d:mi="'+h.map.length+'"'),f.push('d:constr="'+c+'"'),m.push(h.escape_xml(a));break}case Number:case Boolean:if("#text"===i&&"String"!==c){h.map.push(r),f.push('d:mi="'+h.map.length+'"'),f.push('d:constr="'+c+'"'),m.push(h.escape_xml(a));break}m.push(h.scalar_to_xml(i,a))}};if(t.constructor===Array)for(d=0,u=t.length;d"+m.join("")+"":"/>"))},scalar_to_xml:function(e,t,n){var r,a,s,o="";if(null===e.match(this.rx_validate_name)&&(o+=' d:name="'+e+'"',e="d:name",n=!1),null!==t&&"NaN"!==t.toString()||(t=null),null===t)return"<"+e+' d:constr="null"/>';if(1===t.length&&t.constructor===Array&&!t[0])return"<"+e+' d:constr="null" d:type="ArrayItem"/>';if(1===t.length&&t[0].constructor===Object){var i=(r=this.hash_to_xml(!1,t[0])).match(this.rx_node),l=r.match(this.rx_constructor);return"<"+e+(i=null!==i?i[2].replace(this.rx_namespace,"").replace(/>/,"").replace(/"\/$/,'"'):"")+" "+(l=null!==l?l[2]:"")+' d:type="ArrayItem">'+(r=null!==(r=r.match(this.rx_data))?r[2]:"")+""}return 0===t.length&&t.constructor===Array?"<"+e+' d:constr="Array"/>':n?this.hash_to_xml(e,t,!0):(s=(a=t.constructor).toString().match(this.rx_function)[1],r=a===Array?this.hash_to_xml("d:item",t,!0):this.escape_xml(t),o+=' d:constr="'+s+'"',this.map.push(t),o+=' d:mi="'+this.map.length+'"',"#text"===e?this.escape_xml(t):"<"+e+o+">"+r+"")},escape_xml:function(e){return String(e).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/ /g," ")}},toXML:function(e,t){var n,r,a=defiant.json.interpreter;switch(typeof t){case"function":return void defiant.compiled.to_xml_str(e,function(n){t({doc:defiant.xmlFromString(n.str),src:e,map:n.map})});case"boolean":return n=a.to_xml_str.call(a,e),{doc:defiant.xmlFromString(n.str),src:e,map:n.map};default:return n=a.to_xml_str.call(a,e),r=defiant.xmlFromString(n.str),this.search.map=n.map,r}},search:function(e,t,n){e.constructor===String&&"snapshot_"===e.slice(0,9)&&defiant.snapshots[e]&&(e=defiant.snapshots[e]);var r,a,s=defiant.json,o=e.doc&&e.doc.nodeType,i=o?e.doc:s.toXML(e),l=o?e.map:s.search.map,c=o?e.src:e,d=defiant.node[n?"selectSingleNode":"selectNodes"](i,t.xTransform()),u=[];for(n&&(d=[d]),a=d.length;a--;)switch(d[a].nodeType){case 2:case 3:u.unshift(d[a].nodeValue);break;default:r=+d[a].getAttribute("d:mi"),u.unshift(l[r-1])}return"development"===defiant.env&&(u.trace=s.matchTrace(c,u,d)),u},matchTrace:function(e,t,n){var r=[],a=0,s=window,o=defiant.node.toJSON,i=function(e){return JSON.stringify(e,null,"\t").replace(/\t/g,"")},l=i(e);return n.map(function(e,c){var d,u,p,h,m,f,g,x=0;switch(e.nodeType){case 2:d=n[c].ownerElement?n[c].ownerElement.getAttribute("d:"+n[c].nodeName):"String",h=s[d](t[c]),m='"@'+n[c].nodeName+'": '+h,f=l.indexOf(m,a);break;case 3:d=n[c].parentNode.getAttribute("d:constr"),h=s[d](t[c]),m='"'+n[c].parentNode.nodeName+'": '+("Number"===m?h:'"'+h+'"'),f=l.indexOf(m,a);break;default:d=e.getAttribute("d:constr"),["String","Number"].indexOf(d)>-1?(u=o(n[c].parentNode),p=i(u),h=s[d](t[c]),m='"'+n[c].nodeName+'": '+("Number"===d?h:'"'+h+'"'),f=l.indexOf(p,a)+p.indexOf(m)):(m=i(t[c]),f=l.indexOf(m),x=m.split("\n").length-1)}a=f+1,g=l.slice(0,f).split("\n").length,r.push([g,x])}),r}}},x10={id:1,work_handler:function(e){var t=Array.prototype.slice.call(e.data,2),n=e.data[0],r=e.data[1],a=tree[n].apply(tree,t);a.map=JSON.parse(JSON.stringify(a.map)),postMessage([r,n,a])},setup:function(e){var t=window.URL||window.webkitURL,n="var tree = {"+this.parse(e).join(",")+"};",r=new Blob([n+'self.addEventListener("message", '+this.work_handler.toString()+", false);"],{type:"text/javascript"}),a=new Worker(t.createObjectURL(r));return a.onmessage=function(e){var t=Array.prototype.slice.call(e.data,2),n=e.data[0],r=e.data[1];x10.observer.emit("x10:"+r+n,t),x10.observer.off("x10:"+r+n)},a},call_handler:function(e,t){return function(){var n=Array.prototype.slice.call(arguments,0,-1),r=arguments[arguments.length-1],a=x10.id++;n.unshift(a),n.unshift(e),x10.observer.on("x10:"+e+a,function(e){r(e.detail[0])}),t.postMessage(n)}},compile:function(e){var t,n=this.setup("function"==typeof e?{func:e}:e),r={};if("function"==typeof e)return r.func=this.call_handler("func",n),r.func;for(t in e)r[t]=this.call_handler(t,n);return r},parse:function(e,t){var n,r,a,s=[];for(n in e)if(null!==(a=e[n]))if(void 0!==a){switch(a.constructor){case Date:r="new Date("+a.valueOf()+")";break;case Object:r="{"+this.parse(a).join(",")+"}";break;case Array:r="["+this.parse(a,!0).join(",")+"]";break;case String:r='"'+a.replace(/"/g,'\\"')+'"';break;case RegExp:case Function:r=a.toString();break;default:r=a}t?s.push(r):s.push(n+":"+r)}else s.push(n+":undefined");else s.push(n+":null");return s},observer:(stack={},{on:function(e,t){stack[e]||(stack[e]=[]),stack[e].unshift(t)},off:function(e,t){if(stack[e]){var n=stack[e].indexOf(t);stack[e].splice(n,1)}},emit:function(e,t){if(stack[e])for(var n={type:e,detail:t,isCanceled:!1,cancelBubble:function(){this.isCanceled=!0}},r=stack[e].length;r--;){if(n.isCanceled)return;stack[e][r](n)}}})},stack;String.prototype.fill||(String.prototype.fill=function(e,t){var n=this;for(t=t||" ";n.length elements - // (i.e., `typeof document.createElement( "object" ) === "function"`). - // We don't want to classify *any* DOM node as a function. - return typeof obj === "function" && typeof obj.nodeType !== "number"; - }; - - -var isWindow = function isWindow( obj ) { - return obj != null && obj === obj.window; - }; - - - - - var preservedScriptAttributes = { - type: true, - src: true, - noModule: true - }; - - function DOMEval( code, doc, node ) { - doc = doc || document; - - var i, - script = doc.createElement( "script" ); - - script.text = code; - if ( node ) { - for ( i in preservedScriptAttributes ) { - if ( node[ i ] ) { - script[ i ] = node[ i ]; - } - } - } - doc.head.appendChild( script ).parentNode.removeChild( script ); - } - - -function toType( obj ) { - if ( obj == null ) { - return obj + ""; - } - - // Support: Android <=2.3 only (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call( obj ) ] || "object" : - typeof obj; -} -/* global Symbol */ -// Defining this global in .eslintrc.json would create a danger of using the global -// unguarded in another place, it seems safer to define global only for this module - - - -var - version = "3.3.1", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, - - // Support: Android <=4.0 only - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; - -jQuery.fn = jQuery.prototype = { - - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - - // Return all the elements in a clean array - if ( num == null ) { - return slice.call( this ); - } - - // Return just the one element from the set - return num < 0 ? this[ num + this.length ] : this[ num ]; - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - each: function( callback ) { - return jQuery.each( this, callback ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map( this, function( elem, i ) { - return callback.call( elem, i, elem ); - } ) ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[ 0 ] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // Skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !isFunction( target ) ) { - target = {}; - } - - // Extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - - // Only deal with non-null/undefined values - if ( ( options = arguments[ i ] ) != null ) { - - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject( copy ) || - ( copyIsArray = Array.isArray( copy ) ) ) ) { - - if ( copyIsArray ) { - copyIsArray = false; - clone = src && Array.isArray( src ) ? src : []; - - } else { - clone = src && jQuery.isPlainObject( src ) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend( { - - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - isPlainObject: function( obj ) { - var proto, Ctor; - - // Detect obvious negatives - // Use toString instead of jQuery.type to catch host objects - if ( !obj || toString.call( obj ) !== "[object Object]" ) { - return false; - } - - proto = getProto( obj ); - - // Objects with no prototype (e.g., `Object.create( null )`) are plain - if ( !proto ) { - return true; - } - - // Objects with prototype are plain iff they were constructed by a global Object function - Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; - return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; - }, - - isEmptyObject: function( obj ) { - - /* eslint-disable no-unused-vars */ - // See https://github.com/eslint/eslint/issues/6125 - var name; - - for ( name in obj ) { - return false; - } - return true; - }, - - // Evaluates a script in a global context - globalEval: function( code ) { - DOMEval( code ); - }, - - each: function( obj, callback ) { - var length, i = 0; - - if ( isArrayLike( obj ) ) { - length = obj.length; - for ( ; i < length; i++ ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } else { - for ( i in obj ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } - - return obj; - }, - - // Support: Android <=4.0 only - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArrayLike( Object( arr ) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var length, value, - i = 0, - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArrayLike( elems ) ) { - length = elems.length; - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -} ); - -if ( typeof Symbol === "function" ) { - jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; -} - -// Populate the class2type map -jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), -function( i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -} ); - -function isArrayLike( obj ) { - - // Support: real iOS 8.2 only (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, - type = toType( obj ); - - if ( isFunction( obj ) || isWindow( obj ) ) { - return false; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.3.3 - * https://sizzlejs.com/ - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2016-08-08 - */ -(function( window ) { - -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf as it's faster than native - // https://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - - // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + identifier + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - - // CSS escapes - // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, - fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { - - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; - } - - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }, - - disabledAncestor = addCombinator( - function( elem ) { - return elem.disabled === true && ("form" in elem || "label" in elem); - }, - { dir: "parentNode", next: "legend" } - ); - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, match, groups, newSelector, - newContext = context && context.ownerDocument, - - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; - - results = results || []; - - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - context = context || document; - - if ( documentIsHTML ) { - - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { - - // ID selector - if ( (m = match[1]) ) { - - // Document context - if ( nodeType === 9 ) { - if ( (elem = context.getElementById( m )) ) { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - - // Element context - } else { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && (elem = newContext.getElementById( m )) && - contains( context, elem ) && - elem.id === m ) { - - results.push( elem ); - return results; - } - } - - // Type selector - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Class selector - } else if ( (m = match[3]) && support.getElementsByClassName && - context.getElementsByClassName ) { - - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // Take advantage of querySelectorAll - if ( support.qsa && - !compilerCache[ selector + " " ] && - (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - - if ( nodeType !== 1 ) { - newContext = context; - newSelector = selector; - - // qSA looks outside Element context, which is not what we want - // Thanks to Andrew Dupont for this workaround technique - // Support: IE <=8 - // Exclude object elements - } else if ( context.nodeName.toLowerCase() !== "object" ) { - - // Capture the context ID, setting it first if necessary - if ( (nid = context.getAttribute( "id" )) ) { - nid = nid.replace( rcssescape, fcssescape ); - } else { - context.setAttribute( "id", (nid = expando) ); - } - - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - while ( i-- ) { - groups[i] = "#" + nid + " " + toSelector( groups[i] ); - } - newSelector = groups.join( "," ); - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created element and returns a boolean result - */ -function assert( fn ) { - var el = document.createElement("fieldset"); - - try { - return !!fn( el ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( el.parentNode ) { - el.parentNode.removeChild( el ); - } - // release memory in IE - el = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = arr.length; - - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - a.sourceIndex - b.sourceIndex; - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for :enabled/:disabled - * @param {Boolean} disabled true for :disabled; false for :enabled - */ -function createDisabledPseudo( disabled ) { - - // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable - return function( elem ) { - - // Only certain elements can match :enabled or :disabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled - if ( "form" in elem ) { - - // Check for inherited disabledness on relevant non-disabled elements: - // * listed form-associated elements in a disabled fieldset - // https://html.spec.whatwg.org/multipage/forms.html#category-listed - // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled - // * option elements in a disabled optgroup - // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled - // All such elements have a "form" property. - if ( elem.parentNode && elem.disabled === false ) { - - // Option elements defer to a parent optgroup if present - if ( "label" in elem ) { - if ( "label" in elem.parentNode ) { - return elem.parentNode.disabled === disabled; - } else { - return elem.disabled === disabled; - } - } - - // Support: IE 6 - 11 - // Use the isDisabled shortcut property to check for disabled fieldset ancestors - return elem.isDisabled === disabled || - - // Where there is no isDisabled, check manually - /* jshint -W018 */ - elem.isDisabled !== !disabled && - disabledAncestor( elem ) === disabled; - } - - return elem.disabled === disabled; - - // Try to winnow out elements that can't be disabled before trusting the disabled property. - // Some victims get caught in our net (label, legend, menu, track), but it shouldn't - // even exist on them, let alone have a boolean value. - } else if ( "label" in elem ) { - return elem.disabled === disabled; - } - - // Remaining elements are neither :enabled nor :disabled - return false; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, subWindow, - doc = node ? node.ownerDocument || node : preferredDoc; - - // Return early if doc is invalid or already selected - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Update global variables - document = doc; - docElem = document.documentElement; - documentIsHTML = !isXML( document ); - - // Support: IE 9-11, Edge - // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - if ( preferredDoc !== document && - (subWindow = document.defaultView) && subWindow.top !== subWindow ) { - - // Support: IE 11, Edge - if ( subWindow.addEventListener ) { - subWindow.addEventListener( "unload", unloadHandler, false ); - - // Support: IE 9 - 10 only - } else if ( subWindow.attachEvent ) { - subWindow.attachEvent( "onunload", unloadHandler ); - } - } - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert(function( el ) { - el.className = "i"; - return !el.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( el ) { - el.appendChild( document.createComment("") ); - return !el.getElementsByTagName("*").length; - }); - - // Support: IE<9 - support.getElementsByClassName = rnative.test( document.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programmatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( el ) { - docElem.appendChild( el ).id = expando; - return !document.getElementsByName || !document.getElementsByName( expando ).length; - }); - - // ID filter and find - if ( support.getById ) { - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var elem = context.getElementById( id ); - return elem ? [ elem ] : []; - } - }; - } else { - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - - // Support: IE 6 - 7 only - // getElementById is not reliable as a find shortcut - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var node, i, elems, - elem = context.getElementById( id ); - - if ( elem ) { - - // Verify the id attribute - node = elem.getAttributeNode("id"); - if ( node && node.value === id ) { - return [ elem ]; - } - - // Fall back on getElementsByName - elems = context.getElementsByName( id ); - i = 0; - while ( (elem = elems[i++]) ) { - node = elem.getAttributeNode("id"); - if ( node && node.value === id ) { - return [ elem ]; - } - } - } - - return []; - } - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); - - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See https://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( el ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // https://bugs.jquery.com/ticket/12359 - docElem.appendChild( el ).innerHTML = "" + - ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( el.querySelectorAll("[msallowcapture^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !el.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ - if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push("~="); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !el.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibling-combinator selector` fails - if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push(".#.+[+~]"); - } - }); - - assert(function( el ) { - el.innerHTML = "" + - ""; - - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement("input"); - input.setAttribute( "type", "hidden" ); - el.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( el.querySelectorAll("[name=d]").length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( el.querySelectorAll(":enabled").length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Support: IE9-11+ - // IE's :disabled selector does not pick up the children of disabled fieldsets - docElem.appendChild( el ).disabled = true; - if ( el.querySelectorAll(":disabled").length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - el.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { - - assert(function( el ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( el, "*" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( el, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully self-exclusive - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { - - // Choose the first element that is related to our preferred document - if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { - return -1; - } - if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - return a === document ? -1 : - b === document ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return document; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - if ( support.matchesSelector && documentIsHTML && - !compilerCache[ expr + " " ] && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch (e) {} - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; - -Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); -}; - -Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; -}; - -Sizzle.escape = function( sel ) { - return (sel + "").replace( rcssescape, fcssescape ); -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; -}; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); - - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[6] && match[2]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); - }); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, context, xml ) { - var cache, uniqueCache, outerCache, node, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType, - diff = false; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) { - - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - - // Seek `elem` from a previously-cached index - - // ...in a gzip-friendly way - node = parent; - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex && cache[ 2 ]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( (node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - } else { - // Use previously-cached element index if available - if ( useCache ) { - // ...in a gzip-friendly way - node = elem; - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex; - } - - // xml :nth-child(...) - // or :nth-last-child(...) or :nth(-last)?-of-type(...) - if ( diff === false ) { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { - - if ( ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) && - ++diff ) { - - // Cache the index of each encountered element - if ( useCache ) { - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - uniqueCache[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - // Don't keep the element (issue #299) - input[0] = null; - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - text = text.replace( runescape, funescape ); - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; - }; - }), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": createDisabledPseudo( false ), - "disabled": createDisabledPseudo( true ), - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); - }, - - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} - -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); - -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( (tokens = []) ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; - -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - skip = combinator.next, - key = skip || dir, - checkNonElements = base && key === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - return false; - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, uniqueCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); - - if ( skip && skip === elem.nodeName.toLowerCase() ) { - elem = elem[ dir ] || elem; - } else if ( (oldCache = uniqueCache[ key ]) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); - } else { - // Reuse newcache so results back-propagate to previous elements - uniqueCache[ key ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { - return true; - } - } - } - } - } - return false; - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - // Avoid hanging onto element (issue #299) - checkContext = null; - return ret; - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if ( outermost ) { - outermostContext = context === document || context || outermost; - } - - // Add elements passing elementMatchers directly to results - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - if ( !context && elem.ownerDocument !== document ) { - setDocument( elem ); - xml = !documentIsHTML; - } - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context || document, xml) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // `i` is now the count of elements visited above, and adding it to `matchedCount` - // makes the latter nonnegative. - matchedCount += i; - - // Apply set filters to unmatched elements - // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` - // equals `i`), unless we didn't visit _any_ elements in the above loop because we have - // no element matchers and no seed. - // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that - // case, which will result in a "00" `matchedCount` that differs from `i` but is also - // numerically zero. - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); - - results = results || []; - - // Try to minimize operations if there is only one selector in the list and no seed - // (the latter of which guarantees us context) - if ( match.length === 1 ) { - - // Reduce context if the leading compound selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { - - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - !context || rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; - -// One-time assignments - -// Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; - -// Support: Chrome 14-35+ -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( el ) { - // Should return 1, but returns 4 (following) - return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; -}); - -// Support: IE<8 -// Prevent attribute/property "interpolation" -// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( el ) { - el.innerHTML = ""; - return el.firstChild.getAttribute("href") === "#" ; -}) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); -} - -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( el ) { - el.innerHTML = ""; - el.firstChild.setAttribute( "value", "" ); - return el.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); -} - -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( el ) { - return el.getAttribute("disabled") == null; -}) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - null; - } - }); -} - -return Sizzle; - -})( window ); - - - -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; - -// Deprecated -jQuery.expr[ ":" ] = jQuery.expr.pseudos; -jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; -jQuery.escapeSelector = Sizzle.escape; - - - - -var dir = function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; -}; - - -var siblings = function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; -}; - - -var rneedsContext = jQuery.expr.match.needsContext; - - - -function nodeName( elem, name ) { - - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - -}; -var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); - - - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - return !!qualifier.call( elem, i, elem ) !== not; - } ); - } - - // Single element - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - } ); - } - - // Arraylike of elements (jQuery, arguments, Array) - if ( typeof qualifier !== "string" ) { - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) > -1 ) !== not; - } ); - } - - // Filtered directly for both simple and complex selectors - return jQuery.filter( qualifier, elements, not ); -} - -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - if ( elems.length === 1 && elem.nodeType === 1 ) { - return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; - } - - return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - } ) ); -}; - -jQuery.fn.extend( { - find: function( selector ) { - var i, ret, - len = this.length, - self = this; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter( function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - } ) ); - } - - ret = this.pushStack( [] ); - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - return len > 1 ? jQuery.uniqueSort( ret ) : ret; - }, - filter: function( selector ) { - return this.pushStack( winnow( this, selector || [], false ) ); - }, - not: function( selector ) { - return this.pushStack( winnow( this, selector || [], true ) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -} ); - - -// Initialize a jQuery object - - -// A central reference to the root jQuery(document) -var rootjQuery, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - // Shortcut simple #id case for speed - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, - - init = jQuery.fn.init = function( selector, context, root ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Method init() accepts an alternate rootjQuery - // so migrate can support jQuery.sub (gh-2101) - root = root || rootjQuery; - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[ 0 ] === "<" && - selector[ selector.length - 1 ] === ">" && - selector.length >= 3 ) { - - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && ( match[ 1 ] || !context ) ) { - - // HANDLE: $(html) -> $(array) - if ( match[ 1 ] ) { - context = context instanceof jQuery ? context[ 0 ] : context; - - // Option to run scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[ 1 ], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - - // Properties of context are called as methods if possible - if ( isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[ 2 ] ); - - if ( elem ) { - - // Inject the element directly into the jQuery object - this[ 0 ] = elem; - this.length = 1; - } - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || root ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this[ 0 ] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( isFunction( selector ) ) { - return root.ready !== undefined ? - root.ready( selector ) : - - // Execute immediately if ready is not present - selector( jQuery ); - } - - return jQuery.makeArray( selector, this ); - }; - -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; - -// Initialize central reference -rootjQuery = jQuery( document ); - - -var rparentsprev = /^(?:parents|prev(?:Until|All))/, - - // Methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend( { - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; - - return this.filter( function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[ i ] ) ) { - return true; - } - } - } ); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - targets = typeof selectors !== "string" && jQuery( selectors ); - - // Positional selectors never match, since there's no _selection_ context - if ( !rneedsContext.test( selectors ) ) { - for ( ; i < l; i++ ) { - for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { - - // Always skip document fragments - if ( cur.nodeType < 11 && ( targets ? - targets.index( cur ) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector( cur, selectors ) ) ) { - - matched.push( cur ); - break; - } - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); - }, - - // Determine the position of an element within the set - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // Index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); - } - - // Locate the position of the desired element - return indexOf.call( this, - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.uniqueSort( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - } -} ); - -function sibling( cur, dir ) { - while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} - return cur; -} - -jQuery.each( { - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return siblings( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return siblings( elem.firstChild ); - }, - contents: function( elem ) { - if ( nodeName( elem, "iframe" ) ) { - return elem.contentDocument; - } - - // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only - // Treat the template element as a regular one in browsers that - // don't support it. - if ( nodeName( elem, "template" ) ) { - elem = elem.content || elem; - } - - return jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); - } - - if ( this.length > 1 ) { - - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.uniqueSort( matched ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); - } - } - - return this.pushStack( matched ); - }; -} ); -var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); - - - -// Convert String-formatted options into Object-formatted ones -function createOptions( options ) { - var object = {}; - jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { - object[ flag ] = true; - } ); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - createOptions( options ) : - jQuery.extend( {}, options ); - - var // Flag to know if list is currently firing - firing, - - // Last fire value for non-forgettable lists - memory, - - // Flag to know if list was already fired - fired, - - // Flag to prevent firing - locked, - - // Actual callback list - list = [], - - // Queue of execution data for repeatable lists - queue = [], - - // Index of currently firing callback (modified by add/remove as needed) - firingIndex = -1, - - // Fire callbacks - fire = function() { - - // Enforce single-firing - locked = locked || options.once; - - // Execute callbacks for all pending executions, - // respecting firingIndex overrides and runtime changes - fired = firing = true; - for ( ; queue.length; firingIndex = -1 ) { - memory = queue.shift(); - while ( ++firingIndex < list.length ) { - - // Run callback and check for early termination - if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && - options.stopOnFalse ) { - - // Jump to end and forget the data so .add doesn't re-fire - firingIndex = list.length; - memory = false; - } - } - } - - // Forget the data if we're done with it - if ( !options.memory ) { - memory = false; - } - - firing = false; - - // Clean up if we're done firing for good - if ( locked ) { - - // Keep an empty list if we have data for future add calls - if ( memory ) { - list = []; - - // Otherwise, this object is spent - } else { - list = ""; - } - } - }, - - // Actual Callbacks object - self = { - - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - - // If we have memory from a past run, we should fire after adding - if ( memory && !firing ) { - firingIndex = list.length - 1; - queue.push( memory ); - } - - ( function add( args ) { - jQuery.each( args, function( _, arg ) { - if ( isFunction( arg ) ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && toType( arg ) !== "string" ) { - - // Inspect recursively - add( arg ); - } - } ); - } )( arguments ); - - if ( memory && !firing ) { - fire(); - } - } - return this; - }, - - // Remove a callback from the list - remove: function() { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - - // Handle firing indexes - if ( index <= firingIndex ) { - firingIndex--; - } - } - } ); - return this; - }, - - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? - jQuery.inArray( fn, list ) > -1 : - list.length > 0; - }, - - // Remove all callbacks from the list - empty: function() { - if ( list ) { - list = []; - } - return this; - }, - - // Disable .fire and .add - // Abort any current/pending executions - // Clear all callbacks and values - disable: function() { - locked = queue = []; - list = memory = ""; - return this; - }, - disabled: function() { - return !list; - }, - - // Disable .fire - // Also disable .add unless we have memory (since it would have no effect) - // Abort any pending executions - lock: function() { - locked = queue = []; - if ( !memory && !firing ) { - list = memory = ""; - } - return this; - }, - locked: function() { - return !!locked; - }, - - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( !locked ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - queue.push( args ); - if ( !firing ) { - fire(); - } - } - return this; - }, - - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; - - -function Identity( v ) { - return v; -} -function Thrower( ex ) { - throw ex; -} - -function adoptValue( value, resolve, reject, noValue ) { - var method; - - try { - - // Check for promise aspect first to privilege synchronous behavior - if ( value && isFunction( ( method = value.promise ) ) ) { - method.call( value ).done( resolve ).fail( reject ); - - // Other thenables - } else if ( value && isFunction( ( method = value.then ) ) ) { - method.call( value, resolve, reject ); - - // Other non-thenables - } else { - - // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: - // * false: [ value ].slice( 0 ) => resolve( value ) - // * true: [ value ].slice( 1 ) => resolve() - resolve.apply( undefined, [ value ].slice( noValue ) ); - } - - // For Promises/A+, convert exceptions into rejections - // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in - // Deferred#then to conditionally suppress rejection. - } catch ( value ) { - - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - reject.apply( undefined, [ value ] ); - } -} - -jQuery.extend( { - - Deferred: function( func ) { - var tuples = [ - - // action, add listener, callbacks, - // ... .then handlers, argument index, [final state] - [ "notify", "progress", jQuery.Callbacks( "memory" ), - jQuery.Callbacks( "memory" ), 2 ], - [ "resolve", "done", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 0, "resolved" ], - [ "reject", "fail", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 1, "rejected" ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - "catch": function( fn ) { - return promise.then( null, fn ); - }, - - // Keep pipe for back-compat - pipe: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - - return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - - // Map tuples (progress, done, fail) to arguments (done, fail, progress) - var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; - - // deferred.progress(function() { bind to newDefer or newDefer.notify }) - // deferred.done(function() { bind to newDefer or newDefer.resolve }) - // deferred.fail(function() { bind to newDefer or newDefer.reject }) - deferred[ tuple[ 1 ] ]( function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && isFunction( returned.promise ) ) { - returned.promise() - .progress( newDefer.notify ) - .done( newDefer.resolve ) - .fail( newDefer.reject ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( - this, - fn ? [ returned ] : arguments - ); - } - } ); - } ); - fns = null; - } ).promise(); - }, - then: function( onFulfilled, onRejected, onProgress ) { - var maxDepth = 0; - function resolve( depth, deferred, handler, special ) { - return function() { - var that = this, - args = arguments, - mightThrow = function() { - var returned, then; - - // Support: Promises/A+ section 2.3.3.3.3 - // https://promisesaplus.com/#point-59 - // Ignore double-resolution attempts - if ( depth < maxDepth ) { - return; - } - - returned = handler.apply( that, args ); - - // Support: Promises/A+ section 2.3.1 - // https://promisesaplus.com/#point-48 - if ( returned === deferred.promise() ) { - throw new TypeError( "Thenable self-resolution" ); - } - - // Support: Promises/A+ sections 2.3.3.1, 3.5 - // https://promisesaplus.com/#point-54 - // https://promisesaplus.com/#point-75 - // Retrieve `then` only once - then = returned && - - // Support: Promises/A+ section 2.3.4 - // https://promisesaplus.com/#point-64 - // Only check objects and functions for thenability - ( typeof returned === "object" || - typeof returned === "function" ) && - returned.then; - - // Handle a returned thenable - if ( isFunction( then ) ) { - - // Special processors (notify) just wait for resolution - if ( special ) { - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ) - ); - - // Normal processors (resolve) also hook into progress - } else { - - // ...and disregard older resolution values - maxDepth++; - - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ), - resolve( maxDepth, deferred, Identity, - deferred.notifyWith ) - ); - } - - // Handle all other returned values - } else { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Identity ) { - that = undefined; - args = [ returned ]; - } - - // Process the value(s) - // Default process is resolve - ( special || deferred.resolveWith )( that, args ); - } - }, - - // Only normal processors (resolve) catch and reject exceptions - process = special ? - mightThrow : - function() { - try { - mightThrow(); - } catch ( e ) { - - if ( jQuery.Deferred.exceptionHook ) { - jQuery.Deferred.exceptionHook( e, - process.stackTrace ); - } - - // Support: Promises/A+ section 2.3.3.3.4.1 - // https://promisesaplus.com/#point-61 - // Ignore post-resolution exceptions - if ( depth + 1 >= maxDepth ) { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Thrower ) { - that = undefined; - args = [ e ]; - } - - deferred.rejectWith( that, args ); - } - } - }; - - // Support: Promises/A+ section 2.3.3.3.1 - // https://promisesaplus.com/#point-57 - // Re-resolve promises immediately to dodge false rejection from - // subsequent errors - if ( depth ) { - process(); - } else { - - // Call an optional hook to record the stack, in case of exception - // since it's otherwise lost when execution goes async - if ( jQuery.Deferred.getStackHook ) { - process.stackTrace = jQuery.Deferred.getStackHook(); - } - window.setTimeout( process ); - } - }; - } - - return jQuery.Deferred( function( newDefer ) { - - // progress_handlers.add( ... ) - tuples[ 0 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onProgress ) ? - onProgress : - Identity, - newDefer.notifyWith - ) - ); - - // fulfilled_handlers.add( ... ) - tuples[ 1 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onFulfilled ) ? - onFulfilled : - Identity - ) - ); - - // rejected_handlers.add( ... ) - tuples[ 2 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onRejected ) ? - onRejected : - Thrower - ) - ); - } ).promise(); - }, - - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 5 ]; - - // promise.progress = list.add - // promise.done = list.add - // promise.fail = list.add - promise[ tuple[ 1 ] ] = list.add; - - // Handle state - if ( stateString ) { - list.add( - function() { - - // state = "resolved" (i.e., fulfilled) - // state = "rejected" - state = stateString; - }, - - // rejected_callbacks.disable - // fulfilled_callbacks.disable - tuples[ 3 - i ][ 2 ].disable, - - // rejected_handlers.disable - // fulfilled_handlers.disable - tuples[ 3 - i ][ 3 ].disable, - - // progress_callbacks.lock - tuples[ 0 ][ 2 ].lock, - - // progress_handlers.lock - tuples[ 0 ][ 3 ].lock - ); - } - - // progress_handlers.fire - // fulfilled_handlers.fire - // rejected_handlers.fire - list.add( tuple[ 3 ].fire ); - - // deferred.notify = function() { deferred.notifyWith(...) } - // deferred.resolve = function() { deferred.resolveWith(...) } - // deferred.reject = function() { deferred.rejectWith(...) } - deferred[ tuple[ 0 ] ] = function() { - deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); - return this; - }; - - // deferred.notifyWith = list.fireWith - // deferred.resolveWith = list.fireWith - // deferred.rejectWith = list.fireWith - deferred[ tuple[ 0 ] + "With" ] = list.fireWith; - } ); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( singleValue ) { - var - - // count of uncompleted subordinates - remaining = arguments.length, - - // count of unprocessed arguments - i = remaining, - - // subordinate fulfillment data - resolveContexts = Array( i ), - resolveValues = slice.call( arguments ), - - // the master Deferred - master = jQuery.Deferred(), - - // subordinate callback factory - updateFunc = function( i ) { - return function( value ) { - resolveContexts[ i ] = this; - resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( !( --remaining ) ) { - master.resolveWith( resolveContexts, resolveValues ); - } - }; - }; - - // Single- and empty arguments are adopted like Promise.resolve - if ( remaining <= 1 ) { - adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, - !remaining ); - - // Use .then() to unwrap secondary thenables (cf. gh-3000) - if ( master.state() === "pending" || - isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { - - return master.then(); - } - } - - // Multiple arguments are aggregated like Promise.all array elements - while ( i-- ) { - adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); - } - - return master.promise(); - } -} ); - - -// These usually indicate a programmer mistake during development, -// warn about them ASAP rather than swallowing them by default. -var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; - -jQuery.Deferred.exceptionHook = function( error, stack ) { - - // Support: IE 8 - 9 only - // Console exists when dev tools are open, which can happen at any time - if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { - window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); - } -}; - - - - -jQuery.readyException = function( error ) { - window.setTimeout( function() { - throw error; - } ); -}; - - - - -// The deferred used on DOM ready -var readyList = jQuery.Deferred(); - -jQuery.fn.ready = function( fn ) { - - readyList - .then( fn ) - - // Wrap jQuery.readyException in a function so that the lookup - // happens at the time of error handling instead of callback - // registration. - .catch( function( error ) { - jQuery.readyException( error ); - } ); - - return this; -}; - -jQuery.extend( { - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - } -} ); - -jQuery.ready.then = readyList.then; - -// The ready event handler and self cleanup method -function completed() { - document.removeEventListener( "DOMContentLoaded", completed ); - window.removeEventListener( "load", completed ); - jQuery.ready(); -} - -// Catch cases where $(document).ready() is called -// after the browser event has already occurred. -// Support: IE <=9 - 10 only -// Older IE sometimes signals "interactive" too soon -if ( document.readyState === "complete" || - ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { - - // Handle it asynchronously to allow scripts the opportunity to delay ready - window.setTimeout( jQuery.ready ); - -} else { - - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed ); -} - - - - -// Multifunctional method to get and set values of a collection -// The value/s can optionally be executed if it's a function -var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; - - // Sets many values - if ( toType( key ) === "object" ) { - chainable = true; - for ( i in key ) { - access( elems, fn, i, key[ i ], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < len; i++ ) { - fn( - elems[ i ], key, raw ? - value : - value.call( elems[ i ], i, fn( elems[ i ], key ) ) - ); - } - } - } - - if ( chainable ) { - return elems; - } - - // Gets - if ( bulk ) { - return fn.call( elems ); - } - - return len ? fn( elems[ 0 ], key ) : emptyGet; -}; - - -// Matches dashed string for camelizing -var rmsPrefix = /^-ms-/, - rdashAlpha = /-([a-z])/g; - -// Used by camelCase as callback to replace() -function fcamelCase( all, letter ) { - return letter.toUpperCase(); -} - -// Convert dashed to camelCase; used by the css and data modules -// Support: IE <=9 - 11, Edge 12 - 15 -// Microsoft forgot to hump their vendor prefix (#9572) -function camelCase( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); -} -var acceptData = function( owner ) { - - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); -}; - - - - -function Data() { - this.expando = jQuery.expando + Data.uid++; -} - -Data.uid = 1; - -Data.prototype = { - - cache: function( owner ) { - - // Check if the owner object already has a cache - var value = owner[ this.expando ]; - - // If not, create one - if ( !value ) { - value = {}; - - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return an empty object. - if ( acceptData( owner ) ) { - - // If it is a node unlikely to be stringify-ed or looped over - // use plain assignment - if ( owner.nodeType ) { - owner[ this.expando ] = value; - - // Otherwise secure it in a non-enumerable property - // configurable must be true to allow the property to be - // deleted when data is removed - } else { - Object.defineProperty( owner, this.expando, { - value: value, - configurable: true - } ); - } - } - } - - return value; - }, - set: function( owner, data, value ) { - var prop, - cache = this.cache( owner ); - - // Handle: [ owner, key, value ] args - // Always use camelCase key (gh-2257) - if ( typeof data === "string" ) { - cache[ camelCase( data ) ] = value; - - // Handle: [ owner, { properties } ] args - } else { - - // Copy the properties one-by-one to the cache object - for ( prop in data ) { - cache[ camelCase( prop ) ] = data[ prop ]; - } - } - return cache; - }, - get: function( owner, key ) { - return key === undefined ? - this.cache( owner ) : - - // Always use camelCase key (gh-2257) - owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; - }, - access: function( owner, key, value ) { - - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ( ( key && typeof key === "string" ) && value === undefined ) ) { - - return this.get( owner, key ); - } - - // When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); - - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, - cache = owner[ this.expando ]; - - if ( cache === undefined ) { - return; - } - - if ( key !== undefined ) { - - // Support array or space separated string of keys - if ( Array.isArray( key ) ) { - - // If key is an array of keys... - // We always set camelCase keys, so remove that. - key = key.map( camelCase ); - } else { - key = camelCase( key ); - - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - key = key in cache ? - [ key ] : - ( key.match( rnothtmlwhite ) || [] ); - } - - i = key.length; - - while ( i-- ) { - delete cache[ key[ i ] ]; - } - } - - // Remove the expando if there's no more data - if ( key === undefined || jQuery.isEmptyObject( cache ) ) { - - // Support: Chrome <=35 - 45 - // Webkit & Blink performance suffers when deleting properties - // from DOM nodes, so set to undefined instead - // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) - if ( owner.nodeType ) { - owner[ this.expando ] = undefined; - } else { - delete owner[ this.expando ]; - } - } - }, - hasData: function( owner ) { - var cache = owner[ this.expando ]; - return cache !== undefined && !jQuery.isEmptyObject( cache ); - } -}; -var dataPriv = new Data(); - -var dataUser = new Data(); - - - -// Implementation Summary -// -// 1. Enforce API surface and semantic compatibility with 1.9.x branch -// 2. Improve the module's maintainability by reducing the storage -// paths to a single mechanism. -// 3. Use the same single mechanism to support "private" and "user" data. -// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) -// 5. Avoid exposing implementation details on user objects (eg. expando properties) -// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 - -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /[A-Z]/g; - -function getData( data ) { - if ( data === "true" ) { - return true; - } - - if ( data === "false" ) { - return false; - } - - if ( data === "null" ) { - return null; - } - - // Only convert to a number if it doesn't change the string - if ( data === +data + "" ) { - return +data; - } - - if ( rbrace.test( data ) ) { - return JSON.parse( data ); - } - - return data; -} - -function dataAttr( elem, key, data ) { - var name; - - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = getData( data ); - } catch ( e ) {} - - // Make sure we set the data so it isn't changed later - dataUser.set( elem, key, data ); - } else { - data = undefined; - } - } - return data; -} - -jQuery.extend( { - hasData: function( elem ) { - return dataUser.hasData( elem ) || dataPriv.hasData( elem ); - }, - - data: function( elem, name, data ) { - return dataUser.access( elem, name, data ); - }, - - removeData: function( elem, name ) { - dataUser.remove( elem, name ); - }, - - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to dataPriv methods, these can be deprecated. - _data: function( elem, name, data ) { - return dataPriv.access( elem, name, data ); - }, - - _removeData: function( elem, name ) { - dataPriv.remove( elem, name ); - } -} ); - -jQuery.fn.extend( { - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = dataUser.get( elem ); - - if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE 11 only - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = camelCase( name.slice( 5 ) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - dataPriv.set( elem, "hasDataAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each( function() { - dataUser.set( this, key ); - } ); - } - - return access( this, function( value ) { - var data; - - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { - - // Attempt to get data from the cache - // The key will always be camelCased in Data - data = dataUser.get( elem, key ); - if ( data !== undefined ) { - return data; - } - - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, key ); - if ( data !== undefined ) { - return data; - } - - // We tried really hard, but the data doesn't exist. - return; - } - - // Set the data... - this.each( function() { - - // We always store the camelCased key - dataUser.set( this, key, value ); - } ); - }, null, value, arguments.length > 1, null, true ); - }, - - removeData: function( key ) { - return this.each( function() { - dataUser.remove( this, key ); - } ); - } -} ); - - -jQuery.extend( { - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = dataPriv.get( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || Array.isArray( data ) ) { - queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // Clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // Not public - generate a queueHooks object, or return the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { - empty: jQuery.Callbacks( "once memory" ).add( function() { - dataPriv.remove( elem, [ type + "queue", key ] ); - } ) - } ); - } -} ); - -jQuery.fn.extend( { - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[ 0 ], type ); - } - - return data === undefined ? - this : - this.each( function() { - var queue = jQuery.queue( this, type, data ); - - // Ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - } ); - }, - dequeue: function( type ) { - return this.each( function() { - jQuery.dequeue( this, type ); - } ); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -} ); -var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; - -var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); - - -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - -var isHiddenWithinTree = function( elem, el ) { - - // isHiddenWithinTree might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - - // Inline style trumps all - return elem.style.display === "none" || - elem.style.display === "" && - - // Otherwise, check computed style - // Support: Firefox <=43 - 45 - // Disconnected elements can have computed display: none, so first confirm that elem is - // in the document. - jQuery.contains( elem.ownerDocument, elem ) && - - jQuery.css( elem, "display" ) === "none"; - }; - -var swap = function( elem, options, callback, args ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.apply( elem, args || [] ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}; - - - - -function adjustCSS( elem, prop, valueParts, tween ) { - var adjusted, scale, - maxIterations = 20, - currentValue = tween ? - function() { - return tween.cur(); - } : - function() { - return jQuery.css( elem, prop, "" ); - }, - initial = currentValue(), - unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - - // Starting value computation is required for potential unit mismatches - initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && - rcssNum.exec( jQuery.css( elem, prop ) ); - - if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { - - // Support: Firefox <=54 - // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) - initial = initial / 2; - - // Trust units reported by jQuery.css - unit = unit || initialInUnit[ 3 ]; - - // Iteratively approximate from a nonzero starting point - initialInUnit = +initial || 1; - - while ( maxIterations-- ) { - - // Evaluate and update our best guess (doubling guesses that zero out). - // Finish if the scale equals or crosses 1 (making the old*new product non-positive). - jQuery.style( elem, prop, initialInUnit + unit ); - if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { - maxIterations = 0; - } - initialInUnit = initialInUnit / scale; - - } - - initialInUnit = initialInUnit * 2; - jQuery.style( elem, prop, initialInUnit + unit ); - - // Make sure we update the tween properties later on - valueParts = valueParts || []; - } - - if ( valueParts ) { - initialInUnit = +initialInUnit || +initial || 0; - - // Apply relative offset (+=/-=) if specified - adjusted = valueParts[ 1 ] ? - initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : - +valueParts[ 2 ]; - if ( tween ) { - tween.unit = unit; - tween.start = initialInUnit; - tween.end = adjusted; - } - } - return adjusted; -} - - -var defaultDisplayMap = {}; - -function getDefaultDisplay( elem ) { - var temp, - doc = elem.ownerDocument, - nodeName = elem.nodeName, - display = defaultDisplayMap[ nodeName ]; - - if ( display ) { - return display; - } - - temp = doc.body.appendChild( doc.createElement( nodeName ) ); - display = jQuery.css( temp, "display" ); - - temp.parentNode.removeChild( temp ); - - if ( display === "none" ) { - display = "block"; - } - defaultDisplayMap[ nodeName ] = display; - - return display; -} - -function showHide( elements, show ) { - var display, elem, - values = [], - index = 0, - length = elements.length; - - // Determine new display value for elements that need to change - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - - display = elem.style.display; - if ( show ) { - - // Since we force visibility upon cascade-hidden elements, an immediate (and slow) - // check is required in this first loop unless we have a nonempty display value (either - // inline or about-to-be-restored) - if ( display === "none" ) { - values[ index ] = dataPriv.get( elem, "display" ) || null; - if ( !values[ index ] ) { - elem.style.display = ""; - } - } - if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { - values[ index ] = getDefaultDisplay( elem ); - } - } else { - if ( display !== "none" ) { - values[ index ] = "none"; - - // Remember what we're overwriting - dataPriv.set( elem, "display", display ); - } - } - } - - // Set the display of the elements in a second loop to avoid constant reflow - for ( index = 0; index < length; index++ ) { - if ( values[ index ] != null ) { - elements[ index ].style.display = values[ index ]; - } - } - - return elements; -} - -jQuery.fn.extend( { - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state ) { - if ( typeof state === "boolean" ) { - return state ? this.show() : this.hide(); - } - - return this.each( function() { - if ( isHiddenWithinTree( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - } ); - } -} ); -var rcheckableType = ( /^(?:checkbox|radio)$/i ); - -var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); - -var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); - - - -// We have to close these tags to support XHTML (#13200) -var wrapMap = { - - // Support: IE <=9 only - option: [ 1, "" ], - - // XHTML parsers do not magically insert elements in the - // same way that tag soup parsers do. So we cannot shorten - // this by omitting or other required elements. - thead: [ 1, "", "
" ], - col: [ 2, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], - - _default: [ 0, "", "" ] -}; - -// Support: IE <=9 only -wrapMap.optgroup = wrapMap.option; - -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - - -function getAll( context, tag ) { - - // Support: IE <=9 - 11 only - // Use typeof to avoid zero-argument method invocation on host objects (#15151) - var ret; - - if ( typeof context.getElementsByTagName !== "undefined" ) { - ret = context.getElementsByTagName( tag || "*" ); - - } else if ( typeof context.querySelectorAll !== "undefined" ) { - ret = context.querySelectorAll( tag || "*" ); - - } else { - ret = []; - } - - if ( tag === undefined || tag && nodeName( context, tag ) ) { - return jQuery.merge( [ context ], ret ); - } - - return ret; -} - - -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - dataPriv.set( - elems[ i ], - "globalEval", - !refElements || dataPriv.get( refElements[ i ], "globalEval" ) - ); - } -} - - -var rhtml = /<|&#?\w+;/; - -function buildFragment( elems, context, scripts, selection, ignored ) { - var elem, tmp, tag, wrap, contains, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( toType( elem ) === "object" ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Ensure the created nodes are orphaned (#12392) - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( ( elem = nodes[ i++ ] ) ) { - - // Skip elements already in the context collection (trac-4087) - if ( selection && jQuery.inArray( elem, selection ) > -1 ) { - if ( ignored ) { - ignored.push( elem ); - } - continue; - } - - contains = jQuery.contains( elem.ownerDocument, elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( ( elem = tmp[ j++ ] ) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; -} - - -( function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // Support: Android 4.0 - 4.3 only - // Check state lost if the name is set (#11217) - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Android <=4.1 only - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE <=11 only - // Make sure textarea (and checkbox) defaultValue is properly cloned - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; -} )(); -var documentElement = document.documentElement; - - - -var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)/; - -function returnTrue() { - return true; -} - -function returnFalse() { - return false; -} - -// Support: IE <=9 only -// See #13393 for more info -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - -function on( elem, types, selector, data, fn, one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - on( elem, type, selector, data, types[ type ], one ); - } - return elem; - } - - if ( data == null && fn == null ) { - - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return elem; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return elem.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - } ); -} - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.get( elem ); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Ensure that invalid selectors throw exceptions at attach time - // Evaluate against documentElement in case elem is a non-element node (e.g., document) - if ( selector ) { - jQuery.find.matchesSelector( documentElement, selector ); - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !( events = elemData.events ) ) { - events = elemData.events = {}; - } - if ( !( eventHandle = elemData.handle ) ) { - eventHandle = elemData.handle = function( e ) { - - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend( { - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join( "." ) - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !( handlers = events[ type ] ) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener if the special events handler returns false - if ( !special.setup || - special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); - - if ( !elemData || !( events = elemData.events ) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[ 2 ] && - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || - selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || - special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove data and the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - dataPriv.remove( elem, "handle events" ); - } - }, - - dispatch: function( nativeEvent ) { - - // Make a writable jQuery.Event from the native event object - var event = jQuery.event.fix( nativeEvent ); - - var i, j, ret, matched, handleObj, handlerQueue, - args = new Array( arguments.length ), - handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[ 0 ] = event; - - for ( i = 1; i < arguments.length; i++ ) { - args[ i ] = arguments[ i ]; - } - - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( ( handleObj = matched.handlers[ j++ ] ) && - !event.isImmediatePropagationStopped() ) { - - // Triggered event must either 1) have no namespace, or 2) have namespace(s) - // a subset or equal to those in the bound event (both can have no namespace). - if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || - handleObj.handler ).apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( ( event.result = ret ) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, handleObj, sel, matchedHandlers, matchedSelectors, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - if ( delegateCount && - - // Support: IE <=9 - // Black-hole SVG instance trees (trac-13180) - cur.nodeType && - - // Support: Firefox <=42 - // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) - // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click - // Support: IE 11 only - // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) - !( event.type === "click" && event.button >= 1 ) ) { - - for ( ; cur !== this; cur = cur.parentNode || this ) { - - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { - matchedHandlers = []; - matchedSelectors = {}; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matchedSelectors[ sel ] === undefined ) { - matchedSelectors[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) > -1 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matchedSelectors[ sel ] ) { - matchedHandlers.push( handleObj ); - } - } - if ( matchedHandlers.length ) { - handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); - } - } - } - } - - // Add the remaining (directly-bound) handlers - cur = this; - if ( delegateCount < handlers.length ) { - handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); - } - - return handlerQueue; - }, - - addProp: function( name, hook ) { - Object.defineProperty( jQuery.Event.prototype, name, { - enumerable: true, - configurable: true, - - get: isFunction( hook ) ? - function() { - if ( this.originalEvent ) { - return hook( this.originalEvent ); - } - } : - function() { - if ( this.originalEvent ) { - return this.originalEvent[ name ]; - } - }, - - set: function( value ) { - Object.defineProperty( this, name, { - enumerable: true, - configurable: true, - writable: true, - value: value - } ); - } - } ); - }, - - fix: function( originalEvent ) { - return originalEvent[ jQuery.expando ] ? - originalEvent : - new jQuery.Event( originalEvent ); - }, - - special: { - load: { - - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - this.focus(); - return false; - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return nodeName( event.target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } - } - } -}; - -jQuery.removeEvent = function( elem, type, handle ) { - - // This "if" is needed for plain objects - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle ); - } -}; - -jQuery.Event = function( src, props ) { - - // Allow instantiation without the 'new' keyword - if ( !( this instanceof jQuery.Event ) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - - // Support: Android <=2.3 only - src.returnValue === false ? - returnTrue : - returnFalse; - - // Create target properties - // Support: Safari <=6 - 7 only - // Target should not be a text node (#504, #13143) - this.target = ( src.target && src.target.nodeType === 3 ) ? - src.target.parentNode : - src.target; - - this.currentTarget = src.currentTarget; - this.relatedTarget = src.relatedTarget; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || Date.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - constructor: jQuery.Event, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - isSimulated: false, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - - if ( e && !this.isSimulated ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } -}; - -// Includes all common event props including KeyEvent and MouseEvent specific props -jQuery.each( { - altKey: true, - bubbles: true, - cancelable: true, - changedTouches: true, - ctrlKey: true, - detail: true, - eventPhase: true, - metaKey: true, - pageX: true, - pageY: true, - shiftKey: true, - view: true, - "char": true, - charCode: true, - key: true, - keyCode: true, - button: true, - buttons: true, - clientX: true, - clientY: true, - offsetX: true, - offsetY: true, - pointerId: true, - pointerType: true, - screenX: true, - screenY: true, - targetTouches: true, - toElement: true, - touches: true, - - which: function( event ) { - var button = event.button; - - // Add which for key events - if ( event.which == null && rkeyEvent.test( event.type ) ) { - return event.charCode != null ? event.charCode : event.keyCode; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { - if ( button & 1 ) { - return 1; - } - - if ( button & 2 ) { - return 3; - } - - if ( button & 4 ) { - return 2; - } - - return 0; - } - - return event.which; - } -}, jQuery.event.addProp ); - -// Create mouseenter/leave events using mouseover/out and event-time checks -// so that event delegation works in jQuery. -// Do the same for pointerenter/pointerleave and pointerover/pointerout -// -// Support: Safari 7 only -// Safari sends mouseenter too often; see: -// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 -// for the description of the bug (it existed in older Chrome versions as well). -jQuery.each( { - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mouseenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -} ); - -jQuery.fn.extend( { - - on: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn ); - }, - one: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? - handleObj.origType + "." + handleObj.namespace : - handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each( function() { - jQuery.event.remove( this, types, fn, selector ); - } ); - } -} ); - - -var - - /* eslint-disable max-len */ - - // See https://github.com/eslint/eslint/issues/3229 - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, - - /* eslint-enable */ - - // Support: IE <=10 - 11, Edge 12 - 13 only - // In IE/Edge using regex groups here causes severe slowdowns. - // See https://connect.microsoft.com/IE/feedback/details/1736512/ - rnoInnerhtml = /\s*$/g; - -// Prefer a tbody over its parent table for containing new rows -function manipulationTarget( elem, content ) { - if ( nodeName( elem, "table" ) && - nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { - - return jQuery( elem ).children( "tbody" )[ 0 ] || elem; - } - - return elem; -} - -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { - elem.type = elem.type.slice( 5 ); - } else { - elem.removeAttribute( "type" ); - } - - return elem; -} - -function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; - - if ( dest.nodeType !== 1 ) { - return; - } - - // 1. Copy private data: events, handlers, etc. - if ( dataPriv.hasData( src ) ) { - pdataOld = dataPriv.access( src ); - pdataCur = dataPriv.set( dest, pdataOld ); - events = pdataOld.events; - - if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - } - - // 2. Copy user data - if ( dataUser.hasData( src ) ) { - udataOld = dataUser.access( src ); - udataCur = jQuery.extend( {}, udataOld ); - - dataUser.set( dest, udataCur ); - } -} - -// Fix IE bugs, see support tests -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - -function domManip( collection, args, callback, ignored ) { - - // Flatten any nested arrays - args = concat.apply( [], args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = collection.length, - iNoClone = l - 1, - value = args[ 0 ], - valueIsFunction = isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( valueIsFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return collection.each( function( index ) { - var self = collection.eq( index ); - if ( valueIsFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - domManip( self, args, callback, ignored ); - } ); - } - - if ( l ) { - fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - // Require either new content or an interest in ignored elements to invoke the callback - if ( first || ignored ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item - // instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( collection[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !dataPriv.access( node, "globalEval" ) && - jQuery.contains( doc, node ) ) { - - if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { - - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); - } - } else { - DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); - } - } - } - } - } - } - - return collection; -} - -function remove( elem, selector, keepData ) { - var node, - nodes = selector ? jQuery.filter( selector, elem ) : elem, - i = 0; - - for ( ; ( node = nodes[ i ] ) != null; i++ ) { - if ( !keepData && node.nodeType === 1 ) { - jQuery.cleanData( getAll( node ) ); - } - - if ( node.parentNode ) { - if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { - setGlobalEval( getAll( node, "script" ) ); - } - node.parentNode.removeChild( node ); - } - } - - return elem; -} - -jQuery.extend( { - htmlPrefilter: function( html ) { - return html.replace( rxhtmlTag, "<$1>" ); - }, - - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = jQuery.contains( elem.ownerDocument, elem ); - - // Fix IE cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - // Return the cloned set - return clone; - }, - - cleanData: function( elems ) { - var data, elem, type, - special = jQuery.event.special, - i = 0; - - for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { - if ( acceptData( elem ) ) { - if ( ( data = elem[ dataPriv.expando ] ) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataPriv.expando ] = undefined; - } - if ( elem[ dataUser.expando ] ) { - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataUser.expando ] = undefined; - } - } - } - } -} ); - -jQuery.fn.extend( { - detach: function( selector ) { - return remove( this, selector, true ); - }, - - remove: function( selector ) { - return remove( this, selector ); - }, - - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each( function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - } ); - }, null, value, arguments.length ); - }, - - append: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - } ); - }, - - prepend: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - } ); - }, - - before: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - } ); - }, - - after: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - } ); - }, - - empty: function() { - var elem, - i = 0; - - for ( ; ( elem = this[ i ] ) != null; i++ ) { - if ( elem.nodeType === 1 ) { - - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); - - // Remove any remaining nodes - elem.textContent = ""; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map( function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - } ); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = jQuery.htmlPrefilter( value ); - - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch ( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var ignored = []; - - // Make the changes, replacing each non-ignored context element with the new content - return domManip( this, arguments, function( elem ) { - var parent = this.parentNode; - - if ( jQuery.inArray( this, ignored ) < 0 ) { - jQuery.cleanData( getAll( this ) ); - if ( parent ) { - parent.replaceChild( elem, this ); - } - } - - // Force callback invocation - }, ignored ); - } -} ); - -jQuery.each( { - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Support: Android <=4.0 only, PhantomJS 1 only - // .get() because push.apply(_, arraylike) throws on ancient WebKit - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -} ); -var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); - -var getStyles = function( elem ) { - - // Support: IE <=11 only, Firefox <=30 (#15098, #14150) - // IE throws on elements created in popups - // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" - var view = elem.ownerDocument.defaultView; - - if ( !view || !view.opener ) { - view = window; - } - - return view.getComputedStyle( elem ); - }; - -var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); - - - -( function() { - - // Executing both pixelPosition & boxSizingReliable tests require only one layout - // so they're executed at the same time to save the second computation. - function computeStyleTests() { - - // This is a singleton, we need to execute it only once - if ( !div ) { - return; - } - - container.style.cssText = "position:absolute;left:-11111px;width:60px;" + - "margin-top:1px;padding:0;border:0"; - div.style.cssText = - "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + - "margin:auto;border:1px;padding:1px;" + - "width:60%;top:1%"; - documentElement.appendChild( container ).appendChild( div ); - - var divStyle = window.getComputedStyle( div ); - pixelPositionVal = divStyle.top !== "1%"; - - // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 - reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; - - // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 - // Some styles come back with percentage values, even though they shouldn't - div.style.right = "60%"; - pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; - - // Support: IE 9 - 11 only - // Detect misreporting of content dimensions for box-sizing:border-box elements - boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; - - // Support: IE 9 only - // Detect overflow:scroll screwiness (gh-3699) - div.style.position = "absolute"; - scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; - - documentElement.removeChild( container ); - - // Nullify the div so it wouldn't be stored in the memory and - // it will also be a sign that checks already performed - div = null; - } - - function roundPixelMeasures( measure ) { - return Math.round( parseFloat( measure ) ); - } - - var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, - reliableMarginLeftVal, - container = document.createElement( "div" ), - div = document.createElement( "div" ); - - // Finish early in limited (non-browser) environments - if ( !div.style ) { - return; - } - - // Support: IE <=9 - 11 only - // Style of cloned element affects source element cloned (#8908) - div.style.backgroundClip = "content-box"; - div.cloneNode( true ).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; - - jQuery.extend( support, { - boxSizingReliable: function() { - computeStyleTests(); - return boxSizingReliableVal; - }, - pixelBoxStyles: function() { - computeStyleTests(); - return pixelBoxStylesVal; - }, - pixelPosition: function() { - computeStyleTests(); - return pixelPositionVal; - }, - reliableMarginLeft: function() { - computeStyleTests(); - return reliableMarginLeftVal; - }, - scrollboxSize: function() { - computeStyleTests(); - return scrollboxSizeVal; - } - } ); -} )(); - - -function curCSS( elem, name, computed ) { - var width, minWidth, maxWidth, ret, - - // Support: Firefox 51+ - // Retrieving style before computed somehow - // fixes an issue with getting wrong values - // on detached elements - style = elem.style; - - computed = computed || getStyles( elem ); - - // getPropertyValue is needed for: - // .css('filter') (IE 9 only, #12537) - // .css('--customProperty) (#3144) - if ( computed ) { - ret = computed.getPropertyValue( name ) || computed[ name ]; - - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { - ret = jQuery.style( elem, name ); - } - - // A tribute to the "awesome hack by Dean Edwards" - // Android Browser returns percentage for some values, - // but width seems to be reliably pixels. - // This is against the CSSOM draft spec: - // https://drafts.csswg.org/cssom/#resolved-values - if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { - - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - return ret !== undefined ? - - // Support: IE <=9 - 11 only - // IE returns zIndex value as an integer. - ret + "" : - ret; -} - - -function addGetHookIf( conditionFn, hookFn ) { - - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function() { - if ( conditionFn() ) { - - // Hook not needed (or it's not possible to use it due - // to missing dependency), remove it. - delete this.get; - return; - } - - // Hook needed; redefine it so that the support test is not executed again. - return ( this.get = hookFn ).apply( this, arguments ); - } - }; -} - - -var - - // Swappable if display is none or starts with table - // except "table", "table-cell", or "table-caption" - // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rcustomProp = /^--/, - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }, - - cssPrefixes = [ "Webkit", "Moz", "ms" ], - emptyStyle = document.createElement( "div" ).style; - -// Return a css property mapped to a potentially vendor prefixed property -function vendorPropName( name ) { - - // Shortcut for names that are not vendor prefixed - if ( name in emptyStyle ) { - return name; - } - - // Check for vendor prefixed names - var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in emptyStyle ) { - return name; - } - } -} - -// Return a property mapped along what jQuery.cssProps suggests or to -// a vendor prefixed property. -function finalPropName( name ) { - var ret = jQuery.cssProps[ name ]; - if ( !ret ) { - ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; - } - return ret; -} - -function setPositiveNumber( elem, value, subtract ) { - - // Any relative (+/-) values have already been - // normalized at this point - var matches = rcssNum.exec( value ); - return matches ? - - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : - value; -} - -function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { - var i = dimension === "width" ? 1 : 0, - extra = 0, - delta = 0; - - // Adjustment may not be necessary - if ( box === ( isBorderBox ? "border" : "content" ) ) { - return 0; - } - - for ( ; i < 4; i += 2 ) { - - // Both box models exclude margin - if ( box === "margin" ) { - delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); - } - - // If we get here with a content-box, we're seeking "padding" or "border" or "margin" - if ( !isBorderBox ) { - - // Add padding - delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - - // For "border" or "margin", add border - if ( box !== "padding" ) { - delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - - // But still keep track of it otherwise - } else { - extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - - // If we get here with a border-box (content + padding + border), we're seeking "content" or - // "padding" or "margin" - } else { - - // For "content", subtract padding - if ( box === "content" ) { - delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - } - - // For "content" or "padding", subtract border - if ( box !== "margin" ) { - delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } - } - - // Account for positive content-box scroll gutter when requested by providing computedVal - if ( !isBorderBox && computedVal >= 0 ) { - - // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border - // Assuming integer scroll gutter, subtract the rest and round down - delta += Math.max( 0, Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - computedVal - - delta - - extra - - 0.5 - ) ); - } - - return delta; -} - -function getWidthOrHeight( elem, dimension, extra ) { - - // Start with computed style - var styles = getStyles( elem ), - val = curCSS( elem, dimension, styles ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - valueIsBorderBox = isBorderBox; - - // Support: Firefox <=54 - // Return a confounding non-pixel value or feign ignorance, as appropriate. - if ( rnumnonpx.test( val ) ) { - if ( !extra ) { - return val; - } - val = "auto"; - } - - // Check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = valueIsBorderBox && - ( support.boxSizingReliable() || val === elem.style[ dimension ] ); - - // Fall back to offsetWidth/offsetHeight when value is "auto" - // This happens for inline elements with no explicit setting (gh-3571) - // Support: Android <=4.1 - 4.3 only - // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) - if ( val === "auto" || - !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { - - val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; - - // offsetWidth/offsetHeight provide border-box values - valueIsBorderBox = true; - } - - // Normalize "" and auto - val = parseFloat( val ) || 0; - - // Adjust for the element's box model - return ( val + - boxModelAdjustment( - elem, - dimension, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox, - styles, - - // Provide the current computed size to request scroll gutter calculation (gh-3589) - val - ) - ) + "px"; -} - -jQuery.extend( { - - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { - - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - } - } - } - }, - - // Don't automatically add "px" to these possibly-unitless properties - cssNumber: { - "animationIterationCount": true, - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: {}, - - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { - - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = camelCase( name ), - isCustomProp = rcustomProp.test( name ), - style = elem.style; - - // Make sure that we're working with the right name. We don't - // want to query the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Gets hook for the prefixed version, then unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // Convert "+=" or "-=" to relative numbers (#7345) - if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { - value = adjustCSS( elem, name, ret ); - - // Fixes bug #9237 - type = "number"; - } - - // Make sure that null and NaN values aren't set (#7116) - if ( value == null || value !== value ) { - return; - } - - // If a number was passed in, add the unit (except for certain CSS properties) - if ( type === "number" ) { - value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); - } - - // background-* props affect original clone's values - if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { - style[ name ] = "inherit"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !( "set" in hooks ) || - ( value = hooks.set( elem, value, extra ) ) !== undefined ) { - - if ( isCustomProp ) { - style.setProperty( name, value ); - } else { - style[ name ] = value; - } - } - - } else { - - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && - ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { - - return ret; - } - - // Otherwise just get the value from the style object - return style[ name ]; - } - }, - - css: function( elem, name, extra, styles ) { - var val, num, hooks, - origName = camelCase( name ), - isCustomProp = rcustomProp.test( name ); - - // Make sure that we're working with the right name. We don't - // want to modify the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Try prefixed name followed by the unprefixed name - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } - - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name, styles ); - } - - // Convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } - - // Make numeric if forced or a qualifier was provided and val looks numeric - if ( extra === "" || extra ) { - num = parseFloat( val ); - return extra === true || isFinite( num ) ? num || 0 : val; - } - - return val; - } -} ); - -jQuery.each( [ "height", "width" ], function( i, dimension ) { - jQuery.cssHooks[ dimension ] = { - get: function( elem, computed, extra ) { - if ( computed ) { - - // Certain elements can have dimension info if we invisibly show them - // but it must have a current display style that would benefit - return rdisplayswap.test( jQuery.css( elem, "display" ) ) && - - // Support: Safari 8+ - // Table columns in Safari have non-zero offsetWidth & zero - // getBoundingClientRect().width unless display is changed. - // Support: IE <=11 only - // Running getBoundingClientRect on a disconnected node - // in IE throws an error. - ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? - swap( elem, cssShow, function() { - return getWidthOrHeight( elem, dimension, extra ); - } ) : - getWidthOrHeight( elem, dimension, extra ); - } - }, - - set: function( elem, value, extra ) { - var matches, - styles = getStyles( elem ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - subtract = extra && boxModelAdjustment( - elem, - dimension, - extra, - isBorderBox, - styles - ); - - // Account for unreliable border-box dimensions by comparing offset* to computed and - // faking a content-box to get border and padding (gh-3699) - if ( isBorderBox && support.scrollboxSize() === styles.position ) { - subtract -= Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - parseFloat( styles[ dimension ] ) - - boxModelAdjustment( elem, dimension, "border", false, styles ) - - 0.5 - ); - } - - // Convert to pixels if value adjustment is needed - if ( subtract && ( matches = rcssNum.exec( value ) ) && - ( matches[ 3 ] || "px" ) !== "px" ) { - - elem.style[ dimension ] = value; - value = jQuery.css( elem, dimension ); - } - - return setPositiveNumber( elem, value, subtract ); - } - }; -} ); - -jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, - function( elem, computed ) { - if ( computed ) { - return ( parseFloat( curCSS( elem, "marginLeft" ) ) || - elem.getBoundingClientRect().left - - swap( elem, { marginLeft: 0 }, function() { - return elem.getBoundingClientRect().left; - } ) - ) + "px"; - } - } -); - -// These hooks are used by animate to expand properties -jQuery.each( { - margin: "", - padding: "", - border: "Width" -}, function( prefix, suffix ) { - jQuery.cssHooks[ prefix + suffix ] = { - expand: function( value ) { - var i = 0, - expanded = {}, - - // Assumes a single number if not a string - parts = typeof value === "string" ? value.split( " " ) : [ value ]; - - for ( ; i < 4; i++ ) { - expanded[ prefix + cssExpand[ i ] + suffix ] = - parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; - } - - return expanded; - } - }; - - if ( prefix !== "margin" ) { - jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; - } -} ); - -jQuery.fn.extend( { - css: function( name, value ) { - return access( this, function( elem, name, value ) { - var styles, len, - map = {}, - i = 0; - - if ( Array.isArray( name ) ) { - styles = getStyles( elem ); - len = name.length; - - for ( ; i < len; i++ ) { - map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); - } - - return map; - } - - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - } -} ); - - -function Tween( elem, options, prop, end, easing ) { - return new Tween.prototype.init( elem, options, prop, end, easing ); -} -jQuery.Tween = Tween; - -Tween.prototype = { - constructor: Tween, - init: function( elem, options, prop, end, easing, unit ) { - this.elem = elem; - this.prop = prop; - this.easing = easing || jQuery.easing._default; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - }, - cur: function() { - var hooks = Tween.propHooks[ this.prop ]; - - return hooks && hooks.get ? - hooks.get( this ) : - Tween.propHooks._default.get( this ); - }, - run: function( percent ) { - var eased, - hooks = Tween.propHooks[ this.prop ]; - - if ( this.options.duration ) { - this.pos = eased = jQuery.easing[ this.easing ]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = ( this.end - this.start ) * eased + this.start; - - if ( this.options.step ) { - this.options.step.call( this.elem, this.now, this ); - } - - if ( hooks && hooks.set ) { - hooks.set( this ); - } else { - Tween.propHooks._default.set( this ); - } - return this; - } -}; - -Tween.prototype.init.prototype = Tween.prototype; - -Tween.propHooks = { - _default: { - get: function( tween ) { - var result; - - // Use a property on the element directly when it is not a DOM element, - // or when there is no matching style property that exists. - if ( tween.elem.nodeType !== 1 || - tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { - return tween.elem[ tween.prop ]; - } - - // Passing an empty string as a 3rd parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails. - // Simple values such as "10px" are parsed to Float; - // complex values such as "rotate(1rad)" are returned as-is. - result = jQuery.css( tween.elem, tween.prop, "" ); - - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function( tween ) { - - // Use step hook for back compat. - // Use cssHook if its there. - // Use .style if available and use plain properties where available. - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.nodeType === 1 && - ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || - jQuery.cssHooks[ tween.prop ] ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; - -// Support: IE <=9 only -// Panic based approach to setting things on disconnected nodes -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; - -jQuery.easing = { - linear: function( p ) { - return p; - }, - swing: function( p ) { - return 0.5 - Math.cos( p * Math.PI ) / 2; - }, - _default: "swing" -}; - -jQuery.fx = Tween.prototype.init; - -// Back compat <1.8 extension point -jQuery.fx.step = {}; - - - - -var - fxNow, inProgress, - rfxtypes = /^(?:toggle|show|hide)$/, - rrun = /queueHooks$/; - -function schedule() { - if ( inProgress ) { - if ( document.hidden === false && window.requestAnimationFrame ) { - window.requestAnimationFrame( schedule ); - } else { - window.setTimeout( schedule, jQuery.fx.interval ); - } - - jQuery.fx.tick(); - } -} - -// Animations created synchronously will run synchronously -function createFxNow() { - window.setTimeout( function() { - fxNow = undefined; - } ); - return ( fxNow = Date.now() ); -} - -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - i = 0, - attrs = { height: type }; - - // If we include width, step value is 1 to do all cssExpand values, - // otherwise step value is 2 to skip over Left and Right - includeWidth = includeWidth ? 1 : 0; - for ( ; i < 4; i += 2 - includeWidth ) { - which = cssExpand[ i ]; - attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; - } - - if ( includeWidth ) { - attrs.opacity = attrs.width = type; - } - - return attrs; -} - -function createTween( value, prop, animation ) { - var tween, - collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { - - // We're done with this property - return tween; - } - } -} - -function defaultPrefilter( elem, props, opts ) { - var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, - isBox = "width" in props || "height" in props, - anim = this, - orig = {}, - style = elem.style, - hidden = elem.nodeType && isHiddenWithinTree( elem ), - dataShow = dataPriv.get( elem, "fxshow" ); - - // Queue-skipping animations hijack the fx hooks - if ( !opts.queue ) { - hooks = jQuery._queueHooks( elem, "fx" ); - if ( hooks.unqueued == null ) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function() { - if ( !hooks.unqueued ) { - oldfire(); - } - }; - } - hooks.unqueued++; - - anim.always( function() { - - // Ensure the complete handler is called before this completes - anim.always( function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - } ); - } ); - } - - // Detect show/hide animations - for ( prop in props ) { - value = props[ prop ]; - if ( rfxtypes.test( value ) ) { - delete props[ prop ]; - toggle = toggle || value === "toggle"; - if ( value === ( hidden ? "hide" : "show" ) ) { - - // Pretend to be hidden if this is a "show" and - // there is still data from a stopped show/hide - if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { - hidden = true; - - // Ignore all other no-op show/hide data - } else { - continue; - } - } - orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); - } - } - - // Bail out if this is a no-op like .hide().hide() - propTween = !jQuery.isEmptyObject( props ); - if ( !propTween && jQuery.isEmptyObject( orig ) ) { - return; - } - - // Restrict "overflow" and "display" styles during box animations - if ( isBox && elem.nodeType === 1 ) { - - // Support: IE <=9 - 11, Edge 12 - 15 - // Record all 3 overflow attributes because IE does not infer the shorthand - // from identically-valued overflowX and overflowY and Edge just mirrors - // the overflowX value there. - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - - // Identify a display type, preferring old show/hide data over the CSS cascade - restoreDisplay = dataShow && dataShow.display; - if ( restoreDisplay == null ) { - restoreDisplay = dataPriv.get( elem, "display" ); - } - display = jQuery.css( elem, "display" ); - if ( display === "none" ) { - if ( restoreDisplay ) { - display = restoreDisplay; - } else { - - // Get nonempty value(s) by temporarily forcing visibility - showHide( [ elem ], true ); - restoreDisplay = elem.style.display || restoreDisplay; - display = jQuery.css( elem, "display" ); - showHide( [ elem ] ); - } - } - - // Animate inline elements as inline-block - if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { - if ( jQuery.css( elem, "float" ) === "none" ) { - - // Restore the original display value at the end of pure show/hide animations - if ( !propTween ) { - anim.done( function() { - style.display = restoreDisplay; - } ); - if ( restoreDisplay == null ) { - display = style.display; - restoreDisplay = display === "none" ? "" : display; - } - } - style.display = "inline-block"; - } - } - } - - if ( opts.overflow ) { - style.overflow = "hidden"; - anim.always( function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - } ); - } - - // Implement show/hide animations - propTween = false; - for ( prop in orig ) { - - // General show/hide setup for this element animation - if ( !propTween ) { - if ( dataShow ) { - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; - } - } else { - dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); - } - - // Store hidden/visible for toggle so `.stop().toggle()` "reverses" - if ( toggle ) { - dataShow.hidden = !hidden; - } - - // Show elements before animating them - if ( hidden ) { - showHide( [ elem ], true ); - } - - /* eslint-disable no-loop-func */ - - anim.done( function() { - - /* eslint-enable no-loop-func */ - - // The final step of a "hide" animation is actually hiding the element - if ( !hidden ) { - showHide( [ elem ] ); - } - dataPriv.remove( elem, "fxshow" ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - } ); - } - - // Per-property setup - propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = propTween.start; - if ( hidden ) { - propTween.end = propTween.start; - propTween.start = 0; - } - } - } -} - -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( Array.isArray( value ) ) { - easing = value[ 1 ]; - value = props[ index ] = value[ 0 ]; - } - - if ( index !== name ) { - props[ name ] = value; - delete props[ index ]; - } - - hooks = jQuery.cssHooks[ name ]; - if ( hooks && "expand" in hooks ) { - value = hooks.expand( value ); - delete props[ name ]; - - // Not quite $.extend, this won't overwrite existing keys. - // Reusing 'index' because we have the correct "name" - for ( index in value ) { - if ( !( index in props ) ) { - props[ index ] = value[ index ]; - specialEasing[ index ] = easing; - } - } - } else { - specialEasing[ name ] = easing; - } - } -} - -function Animation( elem, properties, options ) { - var result, - stopped, - index = 0, - length = Animation.prefilters.length, - deferred = jQuery.Deferred().always( function() { - - // Don't match elem in the :animated selector - delete tick.elem; - } ), - tick = function() { - if ( stopped ) { - return false; - } - var currentTime = fxNow || createFxNow(), - remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - - // Support: Android 2.3 only - // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) - temp = remaining / animation.duration || 0, - percent = 1 - temp, - index = 0, - length = animation.tweens.length; - - for ( ; index < length; index++ ) { - animation.tweens[ index ].run( percent ); - } - - deferred.notifyWith( elem, [ animation, percent, remaining ] ); - - // If there's more to do, yield - if ( percent < 1 && length ) { - return remaining; - } - - // If this was an empty animation, synthesize a final progress notification - if ( !length ) { - deferred.notifyWith( elem, [ animation, 1, 0 ] ); - } - - // Resolve the animation and report its conclusion - deferred.resolveWith( elem, [ animation ] ); - return false; - }, - animation = deferred.promise( { - elem: elem, - props: jQuery.extend( {}, properties ), - opts: jQuery.extend( true, { - specialEasing: {}, - easing: jQuery.easing._default - }, options ), - originalProperties: properties, - originalOptions: options, - startTime: fxNow || createFxNow(), - duration: options.duration, - tweens: [], - createTween: function( prop, end ) { - var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); - animation.tweens.push( tween ); - return tween; - }, - stop: function( gotoEnd ) { - var index = 0, - - // If we are going to the end, we want to run all the tweens - // otherwise we skip this part - length = gotoEnd ? animation.tweens.length : 0; - if ( stopped ) { - return this; - } - stopped = true; - for ( ; index < length; index++ ) { - animation.tweens[ index ].run( 1 ); - } - - // Resolve when we played the last frame; otherwise, reject - if ( gotoEnd ) { - deferred.notifyWith( elem, [ animation, 1, 0 ] ); - deferred.resolveWith( elem, [ animation, gotoEnd ] ); - } else { - deferred.rejectWith( elem, [ animation, gotoEnd ] ); - } - return this; - } - } ), - props = animation.props; - - propFilter( props, animation.opts.specialEasing ); - - for ( ; index < length; index++ ) { - result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); - if ( result ) { - if ( isFunction( result.stop ) ) { - jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = - result.stop.bind( result ); - } - return result; - } - } - - jQuery.map( props, createTween, animation ); - - if ( isFunction( animation.opts.start ) ) { - animation.opts.start.call( elem, animation ); - } - - // Attach callbacks from options - animation - .progress( animation.opts.progress ) - .done( animation.opts.done, animation.opts.complete ) - .fail( animation.opts.fail ) - .always( animation.opts.always ); - - jQuery.fx.timer( - jQuery.extend( tick, { - elem: elem, - anim: animation, - queue: animation.opts.queue - } ) - ); - - return animation; -} - -jQuery.Animation = jQuery.extend( Animation, { - - tweeners: { - "*": [ function( prop, value ) { - var tween = this.createTween( prop, value ); - adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); - return tween; - } ] - }, - - tweener: function( props, callback ) { - if ( isFunction( props ) ) { - callback = props; - props = [ "*" ]; - } else { - props = props.match( rnothtmlwhite ); - } - - var prop, - index = 0, - length = props.length; - - for ( ; index < length; index++ ) { - prop = props[ index ]; - Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; - Animation.tweeners[ prop ].unshift( callback ); - } - }, - - prefilters: [ defaultPrefilter ], - - prefilter: function( callback, prepend ) { - if ( prepend ) { - Animation.prefilters.unshift( callback ); - } else { - Animation.prefilters.push( callback ); - } - } -} ); - -jQuery.speed = function( speed, easing, fn ) { - var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { - complete: fn || !fn && easing || - isFunction( speed ) && speed, - duration: speed, - easing: fn && easing || easing && !isFunction( easing ) && easing - }; - - // Go to the end state if fx are off - if ( jQuery.fx.off ) { - opt.duration = 0; - - } else { - if ( typeof opt.duration !== "number" ) { - if ( opt.duration in jQuery.fx.speeds ) { - opt.duration = jQuery.fx.speeds[ opt.duration ]; - - } else { - opt.duration = jQuery.fx.speeds._default; - } - } - } - - // Normalize opt.queue - true/undefined/null -> "fx" - if ( opt.queue == null || opt.queue === true ) { - opt.queue = "fx"; - } - - // Queueing - opt.old = opt.complete; - - opt.complete = function() { - if ( isFunction( opt.old ) ) { - opt.old.call( this ); - } - - if ( opt.queue ) { - jQuery.dequeue( this, opt.queue ); - } - }; - - return opt; -}; - -jQuery.fn.extend( { - fadeTo: function( speed, to, easing, callback ) { - - // Show any hidden elements after setting opacity to 0 - return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() - - // Animate to the value specified - .end().animate( { opacity: to }, speed, easing, callback ); - }, - animate: function( prop, speed, easing, callback ) { - var empty = jQuery.isEmptyObject( prop ), - optall = jQuery.speed( speed, easing, callback ), - doAnimation = function() { - - // Operate on a copy of prop so per-property easing won't be lost - var anim = Animation( this, jQuery.extend( {}, prop ), optall ); - - // Empty animations, or finishing resolves immediately - if ( empty || dataPriv.get( this, "finish" ) ) { - anim.stop( true ); - } - }; - doAnimation.finish = doAnimation; - - return empty || optall.queue === false ? - this.each( doAnimation ) : - this.queue( optall.queue, doAnimation ); - }, - stop: function( type, clearQueue, gotoEnd ) { - var stopQueue = function( hooks ) { - var stop = hooks.stop; - delete hooks.stop; - stop( gotoEnd ); - }; - - if ( typeof type !== "string" ) { - gotoEnd = clearQueue; - clearQueue = type; - type = undefined; - } - if ( clearQueue && type !== false ) { - this.queue( type || "fx", [] ); - } - - return this.each( function() { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = dataPriv.get( this ); - - if ( index ) { - if ( data[ index ] && data[ index ].stop ) { - stopQueue( data[ index ] ); - } - } else { - for ( index in data ) { - if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { - stopQueue( data[ index ] ); - } - } - } - - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && - ( type == null || timers[ index ].queue === type ) ) { - - timers[ index ].anim.stop( gotoEnd ); - dequeue = false; - timers.splice( index, 1 ); - } - } - - // Start the next in the queue if the last step wasn't forced. - // Timers currently will call their complete callbacks, which - // will dequeue but only if they were gotoEnd. - if ( dequeue || !gotoEnd ) { - jQuery.dequeue( this, type ); - } - } ); - }, - finish: function( type ) { - if ( type !== false ) { - type = type || "fx"; - } - return this.each( function() { - var index, - data = dataPriv.get( this ), - queue = data[ type + "queue" ], - hooks = data[ type + "queueHooks" ], - timers = jQuery.timers, - length = queue ? queue.length : 0; - - // Enable finishing flag on private data - data.finish = true; - - // Empty the queue first - jQuery.queue( this, type, [] ); - - if ( hooks && hooks.stop ) { - hooks.stop.call( this, true ); - } - - // Look for any active animations, and finish them - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && timers[ index ].queue === type ) { - timers[ index ].anim.stop( true ); - timers.splice( index, 1 ); - } - } - - // Look for any animations in the old queue and finish them - for ( index = 0; index < length; index++ ) { - if ( queue[ index ] && queue[ index ].finish ) { - queue[ index ].finish.call( this ); - } - } - - // Turn off finishing flag - delete data.finish; - } ); - } -} ); - -jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { - var cssFn = jQuery.fn[ name ]; - jQuery.fn[ name ] = function( speed, easing, callback ) { - return speed == null || typeof speed === "boolean" ? - cssFn.apply( this, arguments ) : - this.animate( genFx( name, true ), speed, easing, callback ); - }; -} ); - -// Generate shortcuts for custom animations -jQuery.each( { - slideDown: genFx( "show" ), - slideUp: genFx( "hide" ), - slideToggle: genFx( "toggle" ), - fadeIn: { opacity: "show" }, - fadeOut: { opacity: "hide" }, - fadeToggle: { opacity: "toggle" } -}, function( name, props ) { - jQuery.fn[ name ] = function( speed, easing, callback ) { - return this.animate( props, speed, easing, callback ); - }; -} ); - -jQuery.timers = []; -jQuery.fx.tick = function() { - var timer, - i = 0, - timers = jQuery.timers; - - fxNow = Date.now(); - - for ( ; i < timers.length; i++ ) { - timer = timers[ i ]; - - // Run the timer and safely remove it when done (allowing for external removal) - if ( !timer() && timers[ i ] === timer ) { - timers.splice( i--, 1 ); - } - } - - if ( !timers.length ) { - jQuery.fx.stop(); - } - fxNow = undefined; -}; - -jQuery.fx.timer = function( timer ) { - jQuery.timers.push( timer ); - jQuery.fx.start(); -}; - -jQuery.fx.interval = 13; -jQuery.fx.start = function() { - if ( inProgress ) { - return; - } - - inProgress = true; - schedule(); -}; - -jQuery.fx.stop = function() { - inProgress = null; -}; - -jQuery.fx.speeds = { - slow: 600, - fast: 200, - - // Default speed - _default: 400 -}; - - -// Based off of the plugin by Clint Helfers, with permission. -// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ -jQuery.fn.delay = function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = window.setTimeout( next, time ); - hooks.stop = function() { - window.clearTimeout( timeout ); - }; - } ); -}; - - -( function() { - var input = document.createElement( "input" ), - select = document.createElement( "select" ), - opt = select.appendChild( document.createElement( "option" ) ); - - input.type = "checkbox"; - - // Support: Android <=4.3 only - // Default value for a checkbox should be "on" - support.checkOn = input.value !== ""; - - // Support: IE <=11 only - // Must access selectedIndex to make default options select - support.optSelected = opt.selected; - - // Support: IE <=11 only - // An input loses its value after becoming a radio - input = document.createElement( "input" ); - input.value = "t"; - input.type = "radio"; - support.radioValue = input.value === "t"; -} )(); - - -var boolHook, - attrHandle = jQuery.expr.attrHandle; - -jQuery.fn.extend( { - attr: function( name, value ) { - return access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each( function() { - jQuery.removeAttr( this, name ); - } ); - } -} ); - -jQuery.extend( { - attr: function( elem, name, value ) { - var ret, hooks, - nType = elem.nodeType; - - // Don't get/set attributes on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { - return jQuery.prop( elem, name, value ); - } - - // Attribute hooks are determined by the lowercase version - // Grab necessary hook if one is defined - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - hooks = jQuery.attrHooks[ name.toLowerCase() ] || - ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); - } - - if ( value !== undefined ) { - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return; - } - - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - elem.setAttribute( name, value + "" ); - return value; - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - ret = jQuery.find.attr( elem, name ); - - // Non-existent attributes return null, we normalize to undefined - return ret == null ? undefined : ret; - }, - - attrHooks: { - type: { - set: function( elem, value ) { - if ( !support.radioValue && value === "radio" && - nodeName( elem, "input" ) ) { - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - } - }, - - removeAttr: function( elem, value ) { - var name, - i = 0, - - // Attribute names can contain non-HTML whitespace characters - // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 - attrNames = value && value.match( rnothtmlwhite ); - - if ( attrNames && elem.nodeType === 1 ) { - while ( ( name = attrNames[ i++ ] ) ) { - elem.removeAttribute( name ); - } - } - } -} ); - -// Hooks for boolean attributes -boolHook = { - set: function( elem, value, name ) { - if ( value === false ) { - - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - elem.setAttribute( name, name ); - } - return name; - } -}; - -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { - var getter = attrHandle[ name ] || jQuery.find.attr; - - attrHandle[ name ] = function( elem, name, isXML ) { - var ret, handle, - lowercaseName = name.toLowerCase(); - - if ( !isXML ) { - - // Avoid an infinite loop by temporarily removing this function from the getter - handle = attrHandle[ lowercaseName ]; - attrHandle[ lowercaseName ] = ret; - ret = getter( elem, name, isXML ) != null ? - lowercaseName : - null; - attrHandle[ lowercaseName ] = handle; - } - return ret; - }; -} ); - - - - -var rfocusable = /^(?:input|select|textarea|button)$/i, - rclickable = /^(?:a|area)$/i; - -jQuery.fn.extend( { - prop: function( name, value ) { - return access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - return this.each( function() { - delete this[ jQuery.propFix[ name ] || name ]; - } ); - } -} ); - -jQuery.extend( { - prop: function( elem, name, value ) { - var ret, hooks, - nType = elem.nodeType; - - // Don't get/set properties on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - return ( elem[ name ] = value ); - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - return elem[ name ]; - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - - // Support: IE <=9 - 11 only - // elem.tabIndex doesn't always return the - // correct value when it hasn't been explicitly set - // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - // Use proper attribute retrieval(#12072) - var tabindex = jQuery.find.attr( elem, "tabindex" ); - - if ( tabindex ) { - return parseInt( tabindex, 10 ); - } - - if ( - rfocusable.test( elem.nodeName ) || - rclickable.test( elem.nodeName ) && - elem.href - ) { - return 0; - } - - return -1; - } - } - }, - - propFix: { - "for": "htmlFor", - "class": "className" - } -} ); - -// Support: IE <=11 only -// Accessing the selectedIndex property -// forces the browser to respect setting selected -// on the option -// The getter ensures a default option is selected -// when in an optgroup -// eslint rule "no-unused-expressions" is disabled for this code -// since it considers such accessions noop -if ( !support.optSelected ) { - jQuery.propHooks.selected = { - get: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent && parent.parentNode ) { - parent.parentNode.selectedIndex; - } - return null; - }, - set: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent ) { - parent.selectedIndex; - - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - } - }; -} - -jQuery.each( [ - "tabIndex", - "readOnly", - "maxLength", - "cellSpacing", - "cellPadding", - "rowSpan", - "colSpan", - "useMap", - "frameBorder", - "contentEditable" -], function() { - jQuery.propFix[ this.toLowerCase() ] = this; -} ); - - - - - // Strip and collapse whitespace according to HTML spec - // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace - function stripAndCollapse( value ) { - var tokens = value.match( rnothtmlwhite ) || []; - return tokens.join( " " ); - } - - -function getClass( elem ) { - return elem.getAttribute && elem.getAttribute( "class" ) || ""; -} - -function classesToArray( value ) { - if ( Array.isArray( value ) ) { - return value; - } - if ( typeof value === "string" ) { - return value.match( rnothtmlwhite ) || []; - } - return []; -} - -jQuery.fn.extend( { - addClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - if ( cur.indexOf( " " + clazz + " " ) < 0 ) { - cur += clazz + " "; - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - if ( !arguments.length ) { - return this.attr( "class", "" ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - - // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - - // Remove *all* instances - while ( cur.indexOf( " " + clazz + " " ) > -1 ) { - cur = cur.replace( " " + clazz + " ", " " ); - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isValidValue = type === "string" || Array.isArray( value ); - - if ( typeof stateVal === "boolean" && isValidValue ) { - return stateVal ? this.addClass( value ) : this.removeClass( value ); - } - - if ( isFunction( value ) ) { - return this.each( function( i ) { - jQuery( this ).toggleClass( - value.call( this, i, getClass( this ), stateVal ), - stateVal - ); - } ); - } - - return this.each( function() { - var className, i, self, classNames; - - if ( isValidValue ) { - - // Toggle individual class names - i = 0; - self = jQuery( this ); - classNames = classesToArray( value ); - - while ( ( className = classNames[ i++ ] ) ) { - - // Check each className given, space separated list - if ( self.hasClass( className ) ) { - self.removeClass( className ); - } else { - self.addClass( className ); - } - } - - // Toggle whole class name - } else if ( value === undefined || type === "boolean" ) { - className = getClass( this ); - if ( className ) { - - // Store className if set - dataPriv.set( this, "__className__", className ); - } - - // If the element has a class name or if we're passed `false`, - // then remove the whole classname (if there was one, the above saved it). - // Otherwise bring back whatever was previously saved (if anything), - // falling back to the empty string if nothing was stored. - if ( this.setAttribute ) { - this.setAttribute( "class", - className || value === false ? - "" : - dataPriv.get( this, "__className__" ) || "" - ); - } - } - } ); - }, - - hasClass: function( selector ) { - var className, elem, - i = 0; - - className = " " + selector + " "; - while ( ( elem = this[ i++ ] ) ) { - if ( elem.nodeType === 1 && - ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { - return true; - } - } - - return false; - } -} ); - - - - -var rreturn = /\r/g; - -jQuery.fn.extend( { - val: function( value ) { - var hooks, ret, valueIsFunction, - elem = this[ 0 ]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || - jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && - "get" in hooks && - ( ret = hooks.get( elem, "value" ) ) !== undefined - ) { - return ret; - } - - ret = elem.value; - - // Handle most common string cases - if ( typeof ret === "string" ) { - return ret.replace( rreturn, "" ); - } - - // Handle cases where value is null/undef or number - return ret == null ? "" : ret; - } - - return; - } - - valueIsFunction = isFunction( value ); - - return this.each( function( i ) { - var val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( valueIsFunction ) { - val = value.call( this, i, jQuery( this ).val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - - } else if ( typeof val === "number" ) { - val += ""; - - } else if ( Array.isArray( val ) ) { - val = jQuery.map( val, function( value ) { - return value == null ? "" : value + ""; - } ); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - } ); - } -} ); - -jQuery.extend( { - valHooks: { - option: { - get: function( elem ) { - - var val = jQuery.find.attr( elem, "value" ); - return val != null ? - val : - - // Support: IE <=10 - 11 only - // option.text throws exceptions (#14686, #14858) - // Strip and collapse whitespace - // https://html.spec.whatwg.org/#strip-and-collapse-whitespace - stripAndCollapse( jQuery.text( elem ) ); - } - }, - select: { - get: function( elem ) { - var value, option, i, - options = elem.options, - index = elem.selectedIndex, - one = elem.type === "select-one", - values = one ? null : [], - max = one ? index + 1 : options.length; - - if ( index < 0 ) { - i = max; - - } else { - i = one ? index : 0; - } - - // Loop through all the selected options - for ( ; i < max; i++ ) { - option = options[ i ]; - - // Support: IE <=9 only - // IE8-9 doesn't update selected after form reset (#2551) - if ( ( option.selected || i === index ) && - - // Don't return options that are disabled or in a disabled optgroup - !option.disabled && - ( !option.parentNode.disabled || - !nodeName( option.parentNode, "optgroup" ) ) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - }, - - set: function( elem, value ) { - var optionSet, option, - options = elem.options, - values = jQuery.makeArray( value ), - i = options.length; - - while ( i-- ) { - option = options[ i ]; - - /* eslint-disable no-cond-assign */ - - if ( option.selected = - jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 - ) { - optionSet = true; - } - - /* eslint-enable no-cond-assign */ - } - - // Force browsers to behave consistently when non-matching value is set - if ( !optionSet ) { - elem.selectedIndex = -1; - } - return values; - } - } - } -} ); - -// Radios and checkboxes getter/setter -jQuery.each( [ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - set: function( elem, value ) { - if ( Array.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); - } - } - }; - if ( !support.checkOn ) { - jQuery.valHooks[ this ].get = function( elem ) { - return elem.getAttribute( "value" ) === null ? "on" : elem.value; - }; - } -} ); - - - - -// Return jQuery for attributes-only inclusion - - -support.focusin = "onfocusin" in window; - - -var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - stopPropagationCallback = function( e ) { - e.stopPropagation(); - }; - -jQuery.extend( jQuery.event, { - - trigger: function( event, data, elem, onlyHandlers ) { - - var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; - - cur = lastElement = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf( "." ) > -1 ) { - - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split( "." ); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf( ":" ) < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join( "." ); - event.rnamespace = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === ( elem.ownerDocument || document ) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { - lastElement = cur; - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && - dataPriv.get( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === false ) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( ( !special._default || - special._default.apply( eventPath.pop(), data ) === false ) && - acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name as the event. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - - if ( event.isPropagationStopped() ) { - lastElement.addEventListener( type, stopPropagationCallback ); - } - - elem[ type ](); - - if ( event.isPropagationStopped() ) { - lastElement.removeEventListener( type, stopPropagationCallback ); - } - - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - // Piggyback on a donor event to simulate a different one - // Used only for `focus(in | out)` events - simulate: function( type, elem, event ) { - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true - } - ); - - jQuery.event.trigger( e, null, elem ); - } - -} ); - -jQuery.fn.extend( { - - trigger: function( type, data ) { - return this.each( function() { - jQuery.event.trigger( type, data, this ); - } ); - }, - triggerHandler: function( type, data ) { - var elem = this[ 0 ]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } - } -} ); - - -// Support: Firefox <=44 -// Firefox doesn't have focus(in | out) events -// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 -// -// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 -// focus(in | out) events fire after focus & blur events, -// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order -// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 -if ( !support.focusin ) { - jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - var doc = this.ownerDocument || this, - attaches = dataPriv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this, - attaches = dataPriv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - dataPriv.remove( doc, fix ); - - } else { - dataPriv.access( doc, fix, attaches ); - } - } - }; - } ); -} -var location = window.location; - -var nonce = Date.now(); - -var rquery = ( /\?/ ); - - - -// Cross-browser xml parsing -jQuery.parseXML = function( data ) { - var xml; - if ( !data || typeof data !== "string" ) { - return null; - } - - // Support: IE 9 - 11 only - // IE throws on parseFromString with invalid input. - try { - xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); - } catch ( e ) { - xml = undefined; - } - - if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; -}; - - -var - rbracket = /\[\]$/, - rCRLF = /\r?\n/g, - rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, - rsubmittable = /^(?:input|select|textarea|keygen)/i; - -function buildParams( prefix, obj, traditional, add ) { - var name; - - if ( Array.isArray( obj ) ) { - - // Serialize array item. - jQuery.each( obj, function( i, v ) { - if ( traditional || rbracket.test( prefix ) ) { - - // Treat each array item as a scalar. - add( prefix, v ); - - } else { - - // Item is non-scalar (array or object), encode its numeric index. - buildParams( - prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", - v, - traditional, - add - ); - } - } ); - - } else if ( !traditional && toType( obj ) === "object" ) { - - // Serialize object item. - for ( name in obj ) { - buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); - } - - } else { - - // Serialize scalar item. - add( prefix, obj ); - } -} - -// Serialize an array of form elements or a set of -// key/values into a query string -jQuery.param = function( a, traditional ) { - var prefix, - s = [], - add = function( key, valueOrFunction ) { - - // If value is a function, invoke it and use its return value - var value = isFunction( valueOrFunction ) ? - valueOrFunction() : - valueOrFunction; - - s[ s.length ] = encodeURIComponent( key ) + "=" + - encodeURIComponent( value == null ? "" : value ); - }; - - // If an array was passed in, assume that it is an array of form elements. - if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { - - // Serialize the form elements - jQuery.each( a, function() { - add( this.name, this.value ); - } ); - - } else { - - // If traditional, encode the "old" way (the way 1.3.2 or older - // did it), otherwise encode params recursively. - for ( prefix in a ) { - buildParams( prefix, a[ prefix ], traditional, add ); - } - } - - // Return the resulting serialization - return s.join( "&" ); -}; - -jQuery.fn.extend( { - serialize: function() { - return jQuery.param( this.serializeArray() ); - }, - serializeArray: function() { - return this.map( function() { - - // Can add propHook for "elements" to filter or add form elements - var elements = jQuery.prop( this, "elements" ); - return elements ? jQuery.makeArray( elements ) : this; - } ) - .filter( function() { - var type = this.type; - - // Use .is( ":disabled" ) so that fieldset[disabled] works - return this.name && !jQuery( this ).is( ":disabled" ) && - rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && - ( this.checked || !rcheckableType.test( type ) ); - } ) - .map( function( i, elem ) { - var val = jQuery( this ).val(); - - if ( val == null ) { - return null; - } - - if ( Array.isArray( val ) ) { - return jQuery.map( val, function( val ) { - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ); - } - - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ).get(); - } -} ); - - -var - r20 = /%20/g, - rhash = /#.*$/, - rantiCache = /([?&])_=[^&]*/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, - - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = "*/".concat( "*" ), - - // Anchor tag for parsing the document origin - originAnchor = document.createElement( "a" ); - originAnchor.href = location.href; - -// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport -function addToPrefiltersOrTransports( structure ) { - - // dataTypeExpression is optional and defaults to "*" - return function( dataTypeExpression, func ) { - - if ( typeof dataTypeExpression !== "string" ) { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, - i = 0, - dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; - - if ( isFunction( func ) ) { - - // For each dataType in the dataTypeExpression - while ( ( dataType = dataTypes[ i++ ] ) ) { - - // Prepend if requested - if ( dataType[ 0 ] === "+" ) { - dataType = dataType.slice( 1 ) || "*"; - ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); - - // Otherwise append - } else { - ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); - } - } - } - }; -} - -// Base inspection function for prefilters and transports -function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { - - var inspected = {}, - seekingTransport = ( structure === transports ); - - function inspect( dataType ) { - var selected; - inspected[ dataType ] = true; - jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { - var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); - if ( typeof dataTypeOrTransport === "string" && - !seekingTransport && !inspected[ dataTypeOrTransport ] ) { - - options.dataTypes.unshift( dataTypeOrTransport ); - inspect( dataTypeOrTransport ); - return false; - } else if ( seekingTransport ) { - return !( selected = dataTypeOrTransport ); - } - } ); - return selected; - } - - return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); -} - -// A special extend for ajax options -// that takes "flat" options (not to be deep extended) -// Fixes #9887 -function ajaxExtend( target, src ) { - var key, deep, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - - for ( key in src ) { - if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; - } - } - if ( deep ) { - jQuery.extend( true, target, deep ); - } - - return target; -} - -/* Handles responses to an ajax request: - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ -function ajaxHandleResponses( s, jqXHR, responses ) { - - var ct, type, finalDataType, firstDataType, - contents = s.contents, - dataTypes = s.dataTypes; - - // Remove auto dataType and get content-type in the process - while ( dataTypes[ 0 ] === "*" ) { - dataTypes.shift(); - if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); - } - } - - // Check if we're dealing with a known content-type - if ( ct ) { - for ( type in contents ) { - if ( contents[ type ] && contents[ type ].test( ct ) ) { - dataTypes.unshift( type ); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if ( dataTypes[ 0 ] in responses ) { - finalDataType = dataTypes[ 0 ]; - } else { - - // Try convertible dataTypes - for ( type in responses ) { - if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { - finalDataType = type; - break; - } - if ( !firstDataType ) { - firstDataType = type; - } - } - - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if ( finalDataType ) { - if ( finalDataType !== dataTypes[ 0 ] ) { - dataTypes.unshift( finalDataType ); - } - return responses[ finalDataType ]; - } -} - -/* Chain conversions given the request and the original response - * Also sets the responseXXX fields on the jqXHR instance - */ -function ajaxConvert( s, response, jqXHR, isSuccess ) { - var conv2, current, conv, tmp, prev, - converters = {}, - - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(); - - // Create converters map with lowercased keys - if ( dataTypes[ 1 ] ) { - for ( conv in s.converters ) { - converters[ conv.toLowerCase() ] = s.converters[ conv ]; - } - } - - current = dataTypes.shift(); - - // Convert to each sequential dataType - while ( current ) { - - if ( s.responseFields[ current ] ) { - jqXHR[ s.responseFields[ current ] ] = response; - } - - // Apply the dataFilter if provided - if ( !prev && isSuccess && s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } - - prev = current; - current = dataTypes.shift(); - - if ( current ) { - - // There's only work to do if current dataType is non-auto - if ( current === "*" ) { - - current = prev; - - // Convert response if prev dataType is non-auto and differs from current - } else if ( prev !== "*" && prev !== current ) { - - // Seek a direct converter - conv = converters[ prev + " " + current ] || converters[ "* " + current ]; - - // If none found, seek a pair - if ( !conv ) { - for ( conv2 in converters ) { - - // If conv2 outputs current - tmp = conv2.split( " " ); - if ( tmp[ 1 ] === current ) { - - // If prev can be converted to accepted input - conv = converters[ prev + " " + tmp[ 0 ] ] || - converters[ "* " + tmp[ 0 ] ]; - if ( conv ) { - - // Condense equivalence converters - if ( conv === true ) { - conv = converters[ conv2 ]; - - // Otherwise, insert the intermediate dataType - } else if ( converters[ conv2 ] !== true ) { - current = tmp[ 0 ]; - dataTypes.unshift( tmp[ 1 ] ); - } - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if ( conv !== true ) { - - // Unless errors are allowed to bubble, catch and return them - if ( conv && s.throws ) { - response = conv( response ); - } else { - try { - response = conv( response ); - } catch ( e ) { - return { - state: "parsererror", - error: conv ? e : "No conversion from " + prev + " to " + current - }; - } - } - } - } - } - } - - return { state: "success", data: response }; -} - -jQuery.extend( { - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {}, - - ajaxSettings: { - url: location.href, - type: "GET", - isLocal: rlocalProtocol.test( location.protocol ), - global: true, - processData: true, - async: true, - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - "*": allTypes, - text: "text/plain", - html: "text/html", - xml: "application/xml, text/xml", - json: "application/json, text/javascript" - }, - - contents: { - xml: /\bxml\b/, - html: /\bhtml/, - json: /\bjson\b/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText", - json: "responseJSON" - }, - - // Data converters - // Keys separate source (or catchall "*") and destination types with a single space - converters: { - - // Convert anything to text - "* text": String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": JSON.parse, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - url: true, - context: true - } - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - return settings ? - - // Building a settings object - ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : - - // Extending ajaxSettings - ajaxExtend( jQuery.ajaxSettings, target ); - }, - - ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), - ajaxTransport: addToPrefiltersOrTransports( transports ), - - // Main method - ajax: function( url, options ) { - - // If url is an object, simulate pre-1.5 signature - if ( typeof url === "object" ) { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var transport, - - // URL without anti-cache param - cacheURL, - - // Response headers - responseHeadersString, - responseHeaders, - - // timeout handle - timeoutTimer, - - // Url cleanup var - urlAnchor, - - // Request state (becomes false upon send and true upon completion) - completed, - - // To know if global events are to be dispatched - fireGlobals, - - // Loop variable - i, - - // uncached part of the url - uncached, - - // Create the final options object - s = jQuery.ajaxSetup( {}, options ), - - // Callbacks context - callbackContext = s.context || s, - - // Context for global events is callbackContext if it is a DOM node or jQuery collection - globalEventContext = s.context && - ( callbackContext.nodeType || callbackContext.jquery ) ? - jQuery( callbackContext ) : - jQuery.event, - - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks( "once memory" ), - - // Status-dependent callbacks - statusCode = s.statusCode || {}, - - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - - // Default abort message - strAbort = "canceled", - - // Fake xhr - jqXHR = { - readyState: 0, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( completed ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while ( ( match = rheaders.exec( responseHeadersString ) ) ) { - responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; - } - } - match = responseHeaders[ key.toLowerCase() ]; - } - return match == null ? null : match; - }, - - // Raw string - getAllResponseHeaders: function() { - return completed ? responseHeadersString : null; - }, - - // Caches the header - setRequestHeader: function( name, value ) { - if ( completed == null ) { - name = requestHeadersNames[ name.toLowerCase() ] = - requestHeadersNames[ name.toLowerCase() ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( completed == null ) { - s.mimeType = type; - } - return this; - }, - - // Status-dependent callbacks - statusCode: function( map ) { - var code; - if ( map ) { - if ( completed ) { - - // Execute the appropriate callbacks - jqXHR.always( map[ jqXHR.status ] ); - } else { - - // Lazy-add the new callbacks in a way that preserves old ones - for ( code in map ) { - statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; - } - } - } - return this; - }, - - // Cancel the request - abort: function( statusText ) { - var finalText = statusText || strAbort; - if ( transport ) { - transport.abort( finalText ); - } - done( 0, finalText ); - return this; - } - }; - - // Attach deferreds - deferred.promise( jqXHR ); - - // Add protocol if not provided (prefilters might expect it) - // Handle falsy url in the settings object (#10093: consistency with old signature) - // We also use the url parameter if available - s.url = ( ( url || s.url || location.href ) + "" ) - .replace( rprotocol, location.protocol + "//" ); - - // Alias method option to type as per ticket #12004 - s.type = options.method || options.type || s.method || s.type; - - // Extract dataTypes list - s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; - - // A cross-domain request is in order when the origin doesn't match the current origin. - if ( s.crossDomain == null ) { - urlAnchor = document.createElement( "a" ); - - // Support: IE <=8 - 11, Edge 12 - 15 - // IE throws exception on accessing the href property if url is malformed, - // e.g. http://example.com:80x/ - try { - urlAnchor.href = s.url; - - // Support: IE <=8 - 11 only - // Anchor's host property isn't correctly set when s.url is relative - urlAnchor.href = urlAnchor.href; - s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== - urlAnchor.protocol + "//" + urlAnchor.host; - } catch ( e ) { - - // If there is an error parsing the URL, assume it is crossDomain, - // it can be rejected by the transport if it is invalid - s.crossDomain = true; - } - } - - // Convert data if not already a string - if ( s.data && s.processData && typeof s.data !== "string" ) { - s.data = jQuery.param( s.data, s.traditional ); - } - - // Apply prefilters - inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); - - // If request was aborted inside a prefilter, stop there - if ( completed ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) - fireGlobals = jQuery.event && s.global; - - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger( "ajaxStart" ); - } - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test( s.type ); - - // Save the URL in case we're toying with the If-Modified-Since - // and/or If-None-Match header later on - // Remove hash to simplify url manipulation - cacheURL = s.url.replace( rhash, "" ); - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // Remember the hash so we can put it back - uncached = s.url.slice( cacheURL.length ); - - // If data is available and should be processed, append data to url - if ( s.data && ( s.processData || typeof s.data === "string" ) ) { - cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; - - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Add or update anti-cache param if needed - if ( s.cache === false ) { - cacheURL = cacheURL.replace( rantiCache, "$1" ); - uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; - } - - // Put hash and anti-cache on the URL that will be requested (gh-1732) - s.url = cacheURL + uncached; - - // Change '%20' to '+' if this is encoded form body content (gh-2658) - } else if ( s.data && s.processData && - ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { - s.data = s.data.replace( r20, "+" ); - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - if ( jQuery.lastModified[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); - } - if ( jQuery.etag[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); - } - } - - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? - s.accepts[ s.dataTypes[ 0 ] ] + - ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : - s.accepts[ "*" ] - ); - - // Check for headers option - for ( i in s.headers ) { - jqXHR.setRequestHeader( i, s.headers[ i ] ); - } - - // Allow custom headers/mimetypes and early abort - if ( s.beforeSend && - ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { - - // Abort if not done already and return - return jqXHR.abort(); - } - - // Aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - completeDeferred.add( s.complete ); - jqXHR.done( s.success ); - jqXHR.fail( s.error ); - - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - jqXHR.readyState = 1; - - // Send global event - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - - // If request was aborted inside ajaxSend, stop there - if ( completed ) { - return jqXHR; - } - - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = window.setTimeout( function() { - jqXHR.abort( "timeout" ); - }, s.timeout ); - } - - try { - completed = false; - transport.send( requestHeaders, done ); - } catch ( e ) { - - // Rethrow post-completion exceptions - if ( completed ) { - throw e; - } - - // Propagate others as results - done( -1, e ); - } - } - - // Callback for when everything is done - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Ignore repeat invocations - if ( completed ) { - return; - } - - completed = true; - - // Clear timeout if it exists - if ( timeoutTimer ) { - window.clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Determine if successful - isSuccess = status >= 200 && status < 300 || status === 304; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // Convert no matter what (that way responseXXX fields are always set) - response = ajaxConvert( s, response, jqXHR, isSuccess ); - - // If successful, handle type chaining - if ( isSuccess ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - modified = jqXHR.getResponseHeader( "Last-Modified" ); - if ( modified ) { - jQuery.lastModified[ cacheURL ] = modified; - } - modified = jqXHR.getResponseHeader( "etag" ); - if ( modified ) { - jQuery.etag[ cacheURL ] = modified; - } - } - - // if no content - if ( status === 204 || s.type === "HEAD" ) { - statusText = "nocontent"; - - // if not modified - } else if ( status === 304 ) { - statusText = "notmodified"; - - // If we have data, let's convert it - } else { - statusText = response.state; - success = response.data; - error = response.error; - isSuccess = !error; - } - } else { - - // Extract error from statusText and normalize for non-aborts - error = statusText; - if ( status || !statusText ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger( "ajaxStop" ); - } - } - } - - return jqXHR; - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, - - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - } -} ); - -jQuery.each( [ "get", "post" ], function( i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - - // Shift arguments if data argument was omitted - if ( isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - // The url can be an options object (which then must have .url) - return jQuery.ajax( jQuery.extend( { - url: url, - type: method, - dataType: type, - data: data, - success: callback - }, jQuery.isPlainObject( url ) && url ) ); - }; -} ); - - -jQuery._evalUrl = function( url ) { - return jQuery.ajax( { - url: url, - - // Make this explicit, since user can override this through ajaxSetup (#11264) - type: "GET", - dataType: "script", - cache: true, - async: false, - global: false, - "throws": true - } ); -}; - - -jQuery.fn.extend( { - wrapAll: function( html ) { - var wrap; - - if ( this[ 0 ] ) { - if ( isFunction( html ) ) { - html = html.call( this[ 0 ] ); - } - - // The elements to wrap the target around - wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); - - if ( this[ 0 ].parentNode ) { - wrap.insertBefore( this[ 0 ] ); - } - - wrap.map( function() { - var elem = this; - - while ( elem.firstElementChild ) { - elem = elem.firstElementChild; - } - - return elem; - } ).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( isFunction( html ) ) { - return this.each( function( i ) { - jQuery( this ).wrapInner( html.call( this, i ) ); - } ); - } - - return this.each( function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - } ); - }, - - wrap: function( html ) { - var htmlIsFunction = isFunction( html ); - - return this.each( function( i ) { - jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); - } ); - }, - - unwrap: function( selector ) { - this.parent( selector ).not( "body" ).each( function() { - jQuery( this ).replaceWith( this.childNodes ); - } ); - return this; - } -} ); - - -jQuery.expr.pseudos.hidden = function( elem ) { - return !jQuery.expr.pseudos.visible( elem ); -}; -jQuery.expr.pseudos.visible = function( elem ) { - return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); -}; - - - - -jQuery.ajaxSettings.xhr = function() { - try { - return new window.XMLHttpRequest(); - } catch ( e ) {} -}; - -var xhrSuccessStatus = { - - // File protocol always yields status code 0, assume 200 - 0: 200, - - // Support: IE <=9 only - // #1450: sometimes IE returns 1223 when it should be 204 - 1223: 204 - }, - xhrSupported = jQuery.ajaxSettings.xhr(); - -support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); -support.ajax = xhrSupported = !!xhrSupported; - -jQuery.ajaxTransport( function( options ) { - var callback, errorCallback; - - // Cross domain only allowed if supported through XMLHttpRequest - if ( support.cors || xhrSupported && !options.crossDomain ) { - return { - send: function( headers, complete ) { - var i, - xhr = options.xhr(); - - xhr.open( - options.type, - options.url, - options.async, - options.username, - options.password - ); - - // Apply custom fields if provided - if ( options.xhrFields ) { - for ( i in options.xhrFields ) { - xhr[ i ] = options.xhrFields[ i ]; - } - } - - // Override mime type if needed - if ( options.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( options.mimeType ); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { - headers[ "X-Requested-With" ] = "XMLHttpRequest"; - } - - // Set headers - for ( i in headers ) { - xhr.setRequestHeader( i, headers[ i ] ); - } - - // Callback - callback = function( type ) { - return function() { - if ( callback ) { - callback = errorCallback = xhr.onload = - xhr.onerror = xhr.onabort = xhr.ontimeout = - xhr.onreadystatechange = null; - - if ( type === "abort" ) { - xhr.abort(); - } else if ( type === "error" ) { - - // Support: IE <=9 only - // On a manual native abort, IE9 throws - // errors on any property access that is not readyState - if ( typeof xhr.status !== "number" ) { - complete( 0, "error" ); - } else { - complete( - - // File: protocol always yields status 0; see #8605, #14207 - xhr.status, - xhr.statusText - ); - } - } else { - complete( - xhrSuccessStatus[ xhr.status ] || xhr.status, - xhr.statusText, - - // Support: IE <=9 only - // IE9 has no XHR2 but throws on binary (trac-11426) - // For XHR2 non-text, let the caller handle it (gh-2498) - ( xhr.responseType || "text" ) !== "text" || - typeof xhr.responseText !== "string" ? - { binary: xhr.response } : - { text: xhr.responseText }, - xhr.getAllResponseHeaders() - ); - } - } - }; - }; - - // Listen to events - xhr.onload = callback(); - errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); - - // Support: IE 9 only - // Use onreadystatechange to replace onabort - // to handle uncaught aborts - if ( xhr.onabort !== undefined ) { - xhr.onabort = errorCallback; - } else { - xhr.onreadystatechange = function() { - - // Check readyState before timeout as it changes - if ( xhr.readyState === 4 ) { - - // Allow onerror to be called first, - // but that will not handle a native abort - // Also, save errorCallback to a variable - // as xhr.onerror cannot be accessed - window.setTimeout( function() { - if ( callback ) { - errorCallback(); - } - } ); - } - }; - } - - // Create the abort callback - callback = callback( "abort" ); - - try { - - // Do send the request (this may raise an exception) - xhr.send( options.hasContent && options.data || null ); - } catch ( e ) { - - // #14683: Only rethrow if this hasn't been notified as an error yet - if ( callback ) { - throw e; - } - } - }, - - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -} ); - - - - -// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) -jQuery.ajaxPrefilter( function( s ) { - if ( s.crossDomain ) { - s.contents.script = false; - } -} ); - -// Install script dataType -jQuery.ajaxSetup( { - accepts: { - script: "text/javascript, application/javascript, " + - "application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /\b(?:java|ecma)script\b/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } -} ); - -// Handle cache's special case and crossDomain -jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - } -} ); - -// Bind script tag hack transport -jQuery.ajaxTransport( "script", function( s ) { - - // This transport only deals with cross domain requests - if ( s.crossDomain ) { - var script, callback; - return { - send: function( _, complete ) { - script = jQuery( " - - - - - - - - - - {% for js_file in js_3rdparty %} - - {% endfor %} -{% endblock %} - - -{% block head_js_cvat %} - {{ block.super }} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -{% endblock %} - - -{% block content %} -
-
-
-
- - - - - - - - - - - - - - - -
    -
  • Copy Object URL
  • -
  • Change Color
  • -
  • Remove Shape
  • -
  • Switch Occluded
  • -
  • Switch Lock
  • -
  • Split
  • -
  • Enable Dragging
  • -
  • Reset Perspective
  • -
  • Switch Perspective Orientation
  • - -
- -
    -
  • Copy Job URL
  • -
  • Copy Frame URL
  • -
- -
    -
  • Remove
  • -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - -
- - -
-
- - - - - - - -
-
-
-
-
-
-
-
-
-
-
-
- - -
-
- - -
-
- - -
-
- -
-
-
-
- - - - - - -
- - -
- - -
-
-
- -
- - - - - - -
- - -
-
- -
-{% endblock %} diff --git a/cvat/apps/engine/templates/engine/base.html b/cvat/apps/engine/templates/engine/base.html deleted file mode 100644 index 56415d88..00000000 --- a/cvat/apps/engine/templates/engine/base.html +++ /dev/null @@ -1,90 +0,0 @@ - - -{% load static compress %} - - - - - - {% block head_title %} - Computer Vision Annotation Tool (CVAT) - {% endblock %} - - - {% compress css %} - {% block head_css %} - - {% endblock %} - {% endcompress %} - - {% compress js file platformchecker %} - - - {% endcompress %} - - {% compress js file thirdparty %} - {% block head_js_3rdparty %} - - - - {% endblock %} - {% endcompress %} - - {% compress js file cvat %} - {% block head_js_cvat %} - - - {% endblock %} - {% endcompress %} - - - {% block header %} - {% endblock %} - - {% block content %} - {% endblock %} - - {% block footer %} - {% endblock %} - - - LOADING - - - - - - - - - - diff --git a/cvat/apps/engine/urls.py b/cvat/apps/engine/urls.py index bb547753..699ea1db 100644 --- a/cvat/apps/engine/urls.py +++ b/cvat/apps/engine/urls.py @@ -9,7 +9,10 @@ from rest_framework import routers from rest_framework import permissions from drf_yasg.views import get_schema_view from drf_yasg import openapi +from django.views.generic import RedirectView +from django.conf import settings from cvat.apps.restrictions.views import RestrictionsViewSet +from cvat.apps.authentication.decorators import login_required schema_view = get_schema_view( openapi.Info( @@ -24,6 +27,22 @@ schema_view = get_schema_view( permission_classes=(permissions.IsAuthenticated,), ) +# drf-yasg component doesn't handle correctly URL_FORMAT_OVERRIDE and +# send requests with ?format=openapi suffix instead of ?scheme=openapi. +# We map the required paramater explicitly and add it into query arguments +# on the server side. +def wrap_swagger(view): + @login_required + def _map_format_to_schema(request, scheme=None): + if 'format' in request.GET: + request.GET = request.GET.copy() + format_alias = settings.REST_FRAMEWORK['URL_FORMAT_OVERRIDE'] + request.GET[format_alias] = request.GET['format'] + + return view(request, format=scheme) + + return _map_format_to_schema + router = routers.DefaultRouter(trailing_slash=False) router.register('projects', views.ProjectViewSet) router.register('tasks', views.TaskViewSet) @@ -34,18 +53,18 @@ router.register('restrictions', RestrictionsViewSet, basename='restrictions') urlpatterns = [ # Entry point for a client - path('', views.dispatch_request), - path('dashboard/', views.dispatch_request), + path('', RedirectView.as_view(url=settings.UI_URL, permanent=True, + query_string=True)), # documentation for API - path('api/swagger', views.wrap_swagger( + path('api/swagger', wrap_swagger( schema_view.without_ui(cache_timeout=0)), name='schema-json'), - path('api/swagger/', views.wrap_swagger( + path('api/swagger/', wrap_swagger( schema_view.with_ui('swagger', cache_timeout=0)), name='schema-swagger-ui'), - path('api/docs/', views.wrap_swagger( + path('api/docs/', wrap_swagger( schema_view.with_ui('redoc', cache_timeout=0)), name='schema-redoc'), # entry point for API - path('api/v1/auth/', include('cvat.apps.authentication.api_urls')), + path('api/v1/auth/', include('cvat.apps.authentication.urls')), path('api/v1/', include((router.urls, 'cvat'), namespace='v1')) ] diff --git a/cvat/apps/engine/views.py b/cvat/apps/engine/views.py index 13a9fdbe..1ee9abc5 100644 --- a/cvat/apps/engine/views.py +++ b/cvat/apps/engine/views.py @@ -13,11 +13,9 @@ import django_rq from django.conf import settings from django.contrib.auth.models import User from django.db import IntegrityError -from django.http import HttpResponse, HttpResponseNotFound -from django.shortcuts import render +from django.http import HttpResponse from django.utils import timezone from django.utils.decorators import method_decorator -from django.views.generic import RedirectView from django_filters import rest_framework as filters from django_filters.rest_framework import DjangoFilterBackend from drf_yasg import openapi @@ -34,7 +32,6 @@ from sendfile import sendfile import cvat.apps.dataset_manager as dm import cvat.apps.dataset_manager.views # pylint: disable=unused-import from cvat.apps.authentication import auth -from cvat.apps.authentication.decorators import login_required from cvat.apps.dataset_manager.serializers import DatasetFormatsSerializer from cvat.apps.engine.frame_provider import FrameProvider from cvat.apps.engine.models import Job, StatusChoice, Task @@ -44,50 +41,12 @@ from cvat.apps.engine.serializers import ( FileInfoSerializer, JobSerializer, LabeledDataSerializer, LogEventSerializer, ProjectSerializer, RqStatusSerializer, TaskSerializer, UserSerializer) -from cvat.settings.base import CSS_3RDPARTY, JS_3RDPARTY from cvat.apps.engine.utils import av_scan_paths from . import models, task from .log import clogger, slogger -# drf-yasg component doesn't handle correctly URL_FORMAT_OVERRIDE and -# send requests with ?format=openapi suffix instead of ?scheme=openapi. -# We map the required paramater explicitly and add it into query arguments -# on the server side. -def wrap_swagger(view): - @login_required - def _map_format_to_schema(request, scheme=None): - if 'format' in request.GET: - request.GET = request.GET.copy() - format_alias = settings.REST_FRAMEWORK['URL_FORMAT_OVERRIDE'] - request.GET[format_alias] = request.GET['format'] - - return view(request, format=scheme) - - return _map_format_to_schema - -# Server REST API -@login_required -def dispatch_request(request): - """An entry point to dispatch legacy requests""" - if 'dashboard' in request.path or (request.path == '/' and 'id' not in request.GET): - return RedirectView.as_view( - url=settings.UI_URL, - permanent=True, - query_string=True - )(request) - elif request.method == 'GET' and 'id' in request.GET and request.path == '/': - return render(request, 'engine/annotation.html', { - 'css_3rdparty': CSS_3RDPARTY.get('engine', []), - 'js_3rdparty': JS_3RDPARTY.get('engine', []), - 'status_list': [str(i) for i in StatusChoice], - 'ui_url': settings.UI_URL - }) - else: - return HttpResponseNotFound() - - class ServerViewSet(viewsets.ViewSet): serializer_class = None diff --git a/cvat/apps/git/admin.py b/cvat/apps/git/admin.py deleted file mode 100644 index b66dde17..00000000 --- a/cvat/apps/git/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT diff --git a/cvat/apps/log_viewer/migrations/__init__.py b/cvat/apps/log_viewer/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/cvat/apps/restrictions/migrations/__init__.py b/cvat/apps/restrictions/migrations/__init__.py deleted file mode 100644 index f19d9bef..00000000 --- a/cvat/apps/restrictions/migrations/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright (C) 2020 Intel Corporation -# -# SPDX-License-Identifier: MIT diff --git a/cvat/settings/base.py b/cvat/settings/base.py index 15fe3264..5b373c58 100644 --- a/cvat/settings/base.py +++ b/cvat/settings/base.py @@ -82,10 +82,6 @@ try: except Exception: pass -# Application definition -JS_3RDPARTY = {} -CSS_3RDPARTY = {} - INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', @@ -209,7 +205,7 @@ WSGI_APPLICATION = 'cvat.wsgi.application' # Django Auth DJANGO_AUTH_TYPE = 'BASIC' DJANGO_AUTH_DEFAULT_GROUPS = [] -LOGIN_URL = 'login' +LOGIN_URL = 'rest_login' LOGIN_REDIRECT_URL = '/' AUTH_LOGIN_NOTE = '

Have not registered yet? Register here.

' diff --git a/tests/eslintrc.conf.js b/tests/eslintrc.conf.js deleted file mode 100644 index cd04f937..00000000 --- a/tests/eslintrc.conf.js +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2018 Intel Corporation - * - * SPDX-License-Identifier: MIT - */ - -module.exports = { - 'env': { - 'browser': true, - 'es6': true, - 'jquery': true, - 'qunit': true, - }, - "extends": "eslint:recommended", - 'rules': { - 'indent': [ - 'warn', - 4 - ], - 'linebreak-style': [ - 'error', - 'unix' - ], - 'semi': [ - 'warn' - ], - 'no-extra-semi': [ - 'warn' - ], - 'no-console': [ - 'warn' - ], - }, - 'globals': { - // from attributeAnnotationMode.js - 'AAMController': true, - 'AAMModel': true, - 'AAMView': true, - 'AAMUndefinedKeyword': true, - // from annotationParser.js - 'AnnotationParser': true, - // from annotationUI.js - 'callAnnotationUI': true, - 'blurAllElements': true, - 'drawBoxSize': true, - 'copyToClipboard': true, - // from base.js - 'showMessage': true, - 'showOverlay': true, - 'confirm': true, - 'dumpAnnotationRequest': true, - 'createExportContainer': true, - 'ExportType': true, - 'getExportTargetContainer': true, - // from idGenerator.js - 'IncrementIdGenerator': true, - 'ConstIdGenerator': true, - // from shapeCollection.js - 'ShapeCollectionModel': true, - 'ShapeCollectionController': true, - 'ShapeCollectionView': true, - // from shapeCreator.js - 'ShapeCreatorModel': true, - 'ShapeCreatorController': true, - 'ShapeCreatorView': true, - // from shapeGrouper.js - 'ShapeGrouperModel': true, - 'ShapeGrouperController': true, - 'ShapeGrouperView': true, - // from labelsInfo.js - 'LabelsInfo': true, - // from listener.js - 'Listener': true, - // from logger.js - 'Logger': true, - // from shapeMerger.js - 'ShapeMergerModel': true, - 'ShapeMergerController': true, - 'ShapeMergerView': true, - // from shapes.js - 'PolyShapeModel': true, - 'PolyShapeView': true, - 'buildShapeModel': true, - 'buildShapeController': true, - 'buildShapeView': true, - 'STROKE_WIDTH': true, - 'POINT_RADIUS': true, - 'AREA_TRESHOLD': true, - 'SELECT_POINT_STROKE_WIDTH': true, - // from mousetrap.js - 'Mousetrap': true, - // from platform.js - 'platform': true, - // from player.js - 'PlayerController': true, - 'PlayerModel': true, - 'PlayerView': true, - // from server.js - 'serverRequest': true, - 'saveJobRequest': true, - // from shapeBuffer.js - 'ShapeBufferController': true, - 'ShapeBufferModel': true, - 'ShapeBufferView': true, - // from trackFilter.js - 'FilterModel': true, - 'FilterController': true, - 'FilterView': true, - // from shapeSplitter.js - 'ShapeSplitter': true, - // from userConfig.js - 'Config': true, - // from cookies.js - 'Cookies': true, - // from dashboard django template - 'maxUploadCount': true, - 'maxUploadSize': true, - // from SVG.js - 'SVG': true, - // from history.js - 'HistoryModel': true, - 'HistoryController': true, - 'HistoryView': true, - // from polyshapeEditor.js - 'PolyshapeEditorModel': true, - 'PolyshapeEditorController': true, - 'PolyshapeEditorView': true, - // from coordinateTranslator - 'CoordinateTranslator': true, - }, -}; diff --git a/tests/karma.conf.js b/tests/karma.conf.js deleted file mode 100644 index 8e28f656..00000000 --- a/tests/karma.conf.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2018 Intel Corporation - * - * SPDX-License-Identifier: MIT - */ - -const path = require('path'); -module.exports = function(config) { - config.set({ - basePath: path.join(process.env.HOME, 'cvat/apps/'), - frameworks: ['qunit'], - files: [ - 'engine/static/engine/js/labelsInfo.js', - 'engine/static/engine/js/annotationParser.js', - 'engine/static/engine/js/listener.js', - 'engine/static/engine/js/player.js', - 'engine/static/engine/js/shapes.js', - 'engine/static/engine/js/qunitTests.js', - ], - port: 9876, - colors: true, - autoWatch: false, - browsers: ['ChromeNoSandbox'], - - // Continuous Integration mode - // if true, Karma captures browsers, runs the tests and exits - singleRun: true, - - // Concurrency level - // how many browser should be started simultanous - concurrency: Infinity, - - preprocessors: { - '**/!(qunitTests).js': ['coverage'] - }, - - reporters: ['progress', 'junit', 'coverage', 'coveralls'], - - coverageReporter: { - dir: path.join(process.env.HOME, 'media/coverage'), - reporters: [ - { type: 'html', subdir: '.' }, { type: 'lcov', subdir: '.' } - ], - instrumenterOptions: { - istanbul: { noCompact: true } - } - }, - - junitReporter: { - outputDir: path.join(process.env.HOME, 'media/junit'), - outputFile: undefined, - useBrowserName: true, - nameFormatter: undefined, - classNameFormatter: undefined, - properties: {}, - xmlVersion: null - }, - - customLaunchers: { - ChromeNoSandbox: { - base: 'ChromeHeadless', - flags: ['--no-sandbox'] - } - }, - - logLevel: config.LOG_DEBUG - }); -} diff --git a/tests/run_js_linter.sh b/tests/run_js_linter.sh deleted file mode 100644 index a0685185..00000000 --- a/tests/run_js_linter.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2018 Intel Corporation -# -# SPDX-License-Identifier: MIT -# - -eslint -c ~/tests/eslintrc.conf.js -f ~/tests/node_modules/eslint-detailed-reporter/lib/detailed-multi.js \ - ~/cvat/apps/**/static/**/js/*.js -o ./report.html -ret_code=$? - -mkdir -p ~/media/eslint -mv -t ~/media/eslint main.js styles.css report.html - -exit $ret_code From b6bea11c8b5a98a379ca440dac655c6044be8143 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Mon, 3 Aug 2020 16:33:21 +0300 Subject: [PATCH 15/53] Update CHANGELOG.md (beta release) --- CHANGELOG.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f51fc05..89e2840c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.1.0-beta] - Unreleased +## [1.1.0-beta] - 2020-08-03 ### Added - DL models as serverless functions () - Source type support for tags, shapes and tracks () @@ -20,9 +20,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - It is impossible to submit a DL model in OpenVINO format using UI. Now you can deploy new models on the server using serverless functions () - Files and folders under share path are now alphabetically sorted -### Deprecated -- - ### Removed - Removed OpenVINO and CUDA components because they are not necessary anymore () - Removed the old UI code () @@ -46,9 +43,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed toolip closing issue () - Clearing frame cache when close a task () -### Security -- - ## [1.1.0-alpha] - 2020-06-30 ### Added - Throttling policy for unauthenticated users () From 2c5e306f80567dd014720cf1a1a672d7419408a4 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Mon, 3 Aug 2020 16:38:21 +0300 Subject: [PATCH 16/53] Increment the development version till rc.0. --- CHANGELOG.md | 19 +++++++++++++++++++ cvat/__init__.py | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89e2840c..f85497f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.1.0] - Unreleased +### Added +- + +### Changed +- + +### Deprecated +- + +### Removed +- + +### Fixed +- + +### Security +- + ## [1.1.0-beta] - 2020-08-03 ### Added - DL models as serverless functions () diff --git a/cvat/__init__.py b/cvat/__init__.py index e9d49047..36c99d3d 100644 --- a/cvat/__init__.py +++ b/cvat/__init__.py @@ -4,6 +4,6 @@ from cvat.utils.version import get_version -VERSION = (1, 1, 0, 'beta', 0) +VERSION = (1, 1, 0, 'rc', 0) __version__ = get_version(VERSION) From 4403369a547375f147d17ca7554884b238f37841 Mon Sep 17 00:00:00 2001 From: Nikita Manovich <40690625+nmanovic@users.noreply.github.com> Date: Mon, 3 Aug 2020 17:57:57 +0300 Subject: [PATCH 17/53] Remove codebeat badge (we don't use the tool). (#1980) --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index fb77e0ca..df70c2dc 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/840351da141e4eaeac6476fd19ec0a33)](https://app.codacy.com/app/cvat/cvat?utm_source=github.com&utm_medium=referral&utm_content=opencv/cvat&utm_campaign=Badge_Grade_Dashboard) [![Gitter chat](https://badges.gitter.im/opencv-cvat/gitter.png)](https://gitter.im/opencv-cvat) [![Coverage Status](https://coveralls.io/repos/github/opencv/cvat/badge.svg?branch=)](https://coveralls.io/github/opencv/cvat?branch=develop) -[![codebeat badge](https://codebeat.co/badges/53cd0d16-fddc-46f8-903c-f43ed9abb6dd)](https://codebeat.co/projects/github-com-opencv-cvat-develop) [![DOI](https://zenodo.org/badge/139156354.svg)](https://zenodo.org/badge/latestdoi/139156354) CVAT is free, online, interactive video and image annotation From 92625369272a8528055b3f063acb9c145e8e5a69 Mon Sep 17 00:00:00 2001 From: TOsmanov <54434686+TOsmanov@users.noreply.github.com> Date: Mon, 3 Aug 2020 20:23:29 +0300 Subject: [PATCH 18/53] Update item Annotation with tag in User Guide (#1957) * Update userguide.md and images * add link in userguide.md --- .../static/documentation/images/image067.jpg | Bin 34423 -> 44469 bytes .../static/documentation/images/image155.jpg | Bin 39756 -> 27109 bytes .../static/documentation/images/image181.jpg | Bin 7822 -> 54342 bytes .../static/documentation/images/image183.jpg | Bin 0 -> 12245 bytes cvat/apps/documentation/user_guide.md | 23 +++++++++++------- 5 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 cvat/apps/documentation/static/documentation/images/image183.jpg diff --git a/cvat/apps/documentation/static/documentation/images/image067.jpg b/cvat/apps/documentation/static/documentation/images/image067.jpg index ce8cba2b234957079638f19608ef5435907813d0..25161e070d1e45730983ff970cf22000a4ffdce2 100644 GIT binary patch literal 44469 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 H@{8$L+dKfa literal 34423 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 CmNp3h diff --git a/cvat/apps/documentation/static/documentation/images/image155.jpg b/cvat/apps/documentation/static/documentation/images/image155.jpg index 5081f66de0301e53d631ae1a777c4d1863ff3eb6..5efa220bcd8976cf11323cb52d2274e7cc190901 100644 GIT binary patch literal 27109 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 literal 39756 zcmeFY1z23mwl3NPf-EdRa1D@<1lI-{Nq`_BKmx&?#-))48rLAfB{ad40KwfgxVuB+ z(rDwZkG0o6XP>*zdH3w~-u>S9-n*;%n^mJ~j;b-{KdZ+ab5zZ{sk=qMqqov>(f~9x zG=RbV4{*2i=<kg_}+8Kj>7nNx;`fQZ#23PHvkY5^AGwT-UW8@?+E_oUHtDjkN&#m zzYzEffxi&=3xU57_y+q=B z4qFE^PHrI~Ax2^*I z)_;?24CXYkHnA~*I708y;O1oH{6p#gRWk1(`gfuKCH(i-c+Vp&>0n~$Xd-ogi2Z(> z*}3@GxdlG{+pXsi;^q9CHM{;l2G>9QT@%Q?lMB1|X73OHNx*~qq$9RbK02}B2 zwC*DS8V1?}bPRNSbWB`yEc|=+``SZHA}r!3*d&j+8DB?}lJW3=Q2wZD=n(T|gvovw zhgm|!ca)rxSKTN!?t977KA&Vc#Zv*n^yb!QU}LDGle3?Hz>l(n`{Aj7$K`M7-^Jex zdx(XBeScDr=w7P_0E`Fss60S>_&W#M10rST~s~r2|ZU%sde&3M@od_TfxapF5b4k-C^-4+#~S_(qj8jjUB-lf(Q zqU$qdB?(PEK?L|GAO#t~sf)woZTNvJ(6JY#t2f`yX>$dA^UKdj&L!J&YoWTEmX%4L zg{T||phIdLxw^_?bR0_9hZF10WPCG#=#`w9vPBDLu)ve+(wstJ7eBLa+ zDSOK2k=f)n**U9$Qt4FWHawR3tyuVNBeghuSwLIfO6&Z_{uvJ?3Y;t49GI#Qx8|Yn z^)O1xCMuAkH*u*p)H!*vlQz%!~Lbett>MvozP%+!{vOD#O=A>|;+y)x-O& zWBA;r@WL#_Sz9X7`At%ECB_kn@|;02jf&&1wRv$V+4=+3rP=tncQIcG5E{f*YD{ zXX+W3Cc;)uE4xPqHg)C1RB&^g0`k8&$m3i707Y02LMsWNmFCA(s0)AyqM%IFqw2gj zeq%y;g{9NYQ*S}`fvA`M$xYBy=vr!5nUxr|{SP{_)2O8-h8c#Yx6e#q)E$kw+5gU!Hm~q(1v~vUB|!h*kcPSXz64*_PwV_LstBB)Q5a z_bpeF-!iKgN7e}V+E7GSDWmhe1%ew~a9*1x7kTjMz)38Yeg&tRgRyFP%k!Cd2TA+b zIKHlXp;;-UHdM%&(bq(&7l!JA|m=Ddv!iM9qCK^ z-MDjl1&d${$z~MV&|kOwtjMU?c@||nBpQQRXV^DylTtiO`{jV7+GiESe(Kh}4<~qt zSb9c3pDBk?!A+#Ti_kMzzP$yO2bDsMl-wqF?pdotxeW4xDFoVd99X8qpnq= z)5)GS%*pfa7qA!$6KF<^((5GA0S=n*sfhPk*(r6*vGJ;dMW>pJ0!q}G2MPEX(@8&8 zp~qu~#?}d&N1z1MUfsZZwP>DgE<=|rQKI- z^&Mt%*2JjZS+g%Evu1?-Oh?U zmv<%DE3?4RCQX|�<$}Bmvz(JnT+%7_Xyjqv&?2;1dg}y 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 apFf8*$@<1QCkdCELE#ge4NX8>6aNF(E?!Rn diff --git a/cvat/apps/documentation/static/documentation/images/image183.jpg b/cvat/apps/documentation/static/documentation/images/image183.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0f0cffd234dff0ddb616673e53cd1401ababeefc GIT binary patch literal 12245 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 literal 0 HcmV?d00001 diff --git a/cvat/apps/documentation/user_guide.md b/cvat/apps/documentation/user_guide.md index fd0e09e0..f135b671 100644 --- a/cvat/apps/documentation/user_guide.md +++ b/cvat/apps/documentation/user_guide.md @@ -639,6 +639,7 @@ To open the settings open the user menu in the header and select the settings it In tab ``Player`` you can: - Control step of ``C`` and ``V`` shortcuts. - Control speed of ``Space``/``Play`` button. +- Select canvas background color. You can choose a background color or enter manually (in RGB or HEX format). - Show ``Grid``, change grid size, choose color and transparency: ![](static/documentation/images/image068_mapillary_vistas.jpg) @@ -799,7 +800,7 @@ Switching between user interface modes. |Icon |Description |Links to section | |-- |-- |-- | |![](static/documentation/images/image167.jpg)|``Rectangle``|[Shape mode](#shape-mode-basics); [Track mode](#track-mode-basics);
[Drawing by 4 points](#annotation-with-rectangle-by-4-points)| -|![](static/documentation/images/image168.jpg)|``Polygon`` |[Annotation with polygons](#annotation-with-polygons) | +|![](static/documentation/images/image168.jpg)|``Polygon`` |[Annotation with polygons](#annotation-with-polygons); [Track mode with polygons](#track-mode-with-polygons) | |![](static/documentation/images/image169.jpg)|``Polyline`` |[Annotation with polylines](#annotation-with-polylines)| |![](static/documentation/images/image170.jpg)|``Points`` |[Annotation with points](#annotation-with-points) | |![](static/documentation/images/image176.jpg)|``Cuboid`` |[Annotation with cuboids](#annotation-with-cuboids) | @@ -1271,20 +1272,23 @@ Simply drag the faces to move them independently from the rest of the cuboid. ![](static/documentation/images/gif020_mapillary_vistas.gif) -You can also use cuboids in track mode, similar to rectangles in track mode ([basics](#track-mode-basics) and [advanced](#track-mode-advanced)) +You can also use cuboids in track mode, similar to rectangles in track mode ([basics](#track-mode-basics) and [advanced](#track-mode-advanced)) or [Track mode with polygons](#track-mode-with-polygons) ## Annotation with Tags -Used to annotate frames, does not have a shape in the workspace. -Before you start, you have to make sure that Tag is selected. +It is used to annotate frames, tags are not displayed in the workspace. +Before you start, open the drop-down list in the top panel and select ``Tag annotation``. -![](static/documentation/images/image181.jpg) +![](static/documentation/images/image183.jpg) + +The objects sidebar will be replaced with a special panel for working with tags. +Here you can select a label for a tag and add it by clicking on the ``Add tag`` button. +You can also customize hotkeys for each label. -Click tag to create. You can work with Tag only on the sidebar. -You can use the lock function and change label and attribute. -Other functions such as propagate, make a copy and remove are available in the action menu. +![](static/documentation/images/image181.jpg) -![](static/documentation/images/image135.jpg) +If you need to use only one label for one frame, then enable the ``Automatically go to the next frame`` +checkbox, then after you add the tag the frame will automatically switch to the next. ## Track mode with polygons @@ -1491,6 +1495,7 @@ Many UI elements have shortcut hints. Put your pointer to a required element to | | _Modes_ | | ``N`` | Repeat the latest procedure of drawing with the same parameters | | ``M`` | Activate or deactivate mode to merging shapes | +| ``Alt+M`` | Activate or deactivate mode to spliting shapes | | ``G`` | Activate or deactivate mode to grouping shapes | | ``Shift+G`` | Reset group for selected shapes (in group mode) | | ``Esc`` | Cancel any active canvas mode | From 737e94828e24632d1c5cae84bbae0da8ac633c55 Mon Sep 17 00:00:00 2001 From: Mike Peven Date: Tue, 4 Aug 2020 04:07:08 -0400 Subject: [PATCH 19/53] Increase the rate of allowed requests (#1969) * Increase the rate of allowed requests * Update CHANGELOG.md --- CHANGELOG.md | 1 + cvat/settings/base.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f85497f7..99de8a72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Stylelint filetype scans () - Fixed toolip closing issue () - Clearing frame cache when close a task () +- Increase rate of throttling policy for unauthenticated users () ## [1.1.0-alpha] - 2020-06-30 ### Added diff --git a/cvat/settings/base.py b/cvat/settings/base.py index 5b373c58..a224ff04 100644 --- a/cvat/settings/base.py +++ b/cvat/settings/base.py @@ -149,7 +149,7 @@ REST_FRAMEWORK = { 'rest_framework.throttling.AnonRateThrottle', ], 'DEFAULT_THROTTLE_RATES': { - 'anon': '100/hour', + 'anon': '100/minute', }, } From 18d04ff0f4f85c425cf76e0ca6f028da040136a3 Mon Sep 17 00:00:00 2001 From: Nikita Manovich <40690625+nmanovic@users.noreply.github.com> Date: Tue, 4 Aug 2020 11:22:50 +0300 Subject: [PATCH 20/53] Add a table with serverless functions into README. (#1981) --- CONTRIBUTING.md | 6 ++++-- README.md | 25 +++++++++++++++++------ cvat/apps/documentation/installation.md | 18 ++++------------- serverless/deploy.sh | 27 ++++++++++++++++--------- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6fa845c8..08c3cfd0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -121,7 +121,8 @@ nuctl create project cvat ```bash nuctl deploy --project-name cvat \ --path serverless/openvino/dextr/nuclio \ - --volume `pwd`/serverless/openvino/common:/opt/nuclio/common + --volume `pwd`/serverless/openvino/common:/opt/nuclio/common \ + --platform local ```
@@ -148,7 +149,8 @@ nuctl deploy --project-name cvat \ ```bash nuctl deploy --project-name cvat \ --path serverless/openvino/omz/public/yolo-v3-tf/nuclio \ - --volume `pwd`/serverless/openvino/common:/opt/nuclio/common + --volume `pwd`/serverless/openvino/common:/opt/nuclio/common \ + --platform local ```
diff --git a/README.md b/README.md index df70c2dc..c02bbb5d 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ CVAT is free, online, interactive video and image annotation tool for computer vision. It is being used by our team to annotate million of objects with different properties. Many UI -and UX decisions are based on feedbacks from professional data annotation team. -Try it online [cvat.org](https://cvat.org). +and UX decisions are based on feedbacks from professional data +annotation team. Try it online [cvat.org](https://cvat.org). ![CVAT screenshot](cvat/apps/documentation/static/documentation/images/cvat.jpg) @@ -57,10 +57,18 @@ via its command line tool and Python library. | [MOT](https://motchallenge.net/) | X | X | | [LabelMe 3.0](http://labelme.csail.mit.edu/Release3.0) | X | X | -## Links -- [Intel AI blog: New Computer Vision Tool Accelerates Annotation of Digital Images and Video](https://www.intel.ai/introducing-cvat) -- [Intel Software: Computer Vision Annotation Tool: A Universal Approach to Data Annotation](https://software.intel.com/en-us/articles/computer-vision-annotation-tool-a-universal-approach-to-data-annotation) -- [VentureBeat: Intel open-sources CVAT, a toolkit for data labeling](https://venturebeat.com/2019/03/05/intel-open-sources-cvat-a-toolkit-for-data-labeling/) +## Deep learning models for automatic labeling + +| Name | Type | Framework | +| ------------------------------------------------------------------------------------------------------- | ---------- | ---------- | +| [Deep Extreme Cut](/serverless/openvino/dextr/nuclio) | interactor | OpenVINO | +| [Faster RCNN](/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio) | detector | TensorFlow | +| [Mask RCNN](/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio) | detector | OpenVINO | +| [YOLO v3](/serverless/openvino/omz/public/yolo-v3-tf/nuclio) | detector | OpenVINO | +| [Text detection v4](/serverless/openvino/omz/intel/text-detection-0004/nuclio) | detector | OpenVINO | +| [Semantic segmentation for ADAS](/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio) | detector | OpenVINO | +| [Mask RCNN](/serverless/tensorflow/matterport/mask_rcnn/nuclio) | detector | TensorFlow | +| [Object reidentification](/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio) | reid | OpenVINO | ## Online demo: [cvat.org](https://cvat.org) @@ -103,3 +111,8 @@ If you are not sure or just want to browse other users common questions, Other ways to ask questions and get our support: * [\#cvat](https://stackoverflow.com/search?q=%23cvat) tag on StackOverflow* * [Forum on Intel Developer Zone](https://software.intel.com/en-us/forums/computer-vision) + +## Links +- [Intel AI blog: New Computer Vision Tool Accelerates Annotation of Digital Images and Video](https://www.intel.ai/introducing-cvat) +- [Intel Software: Computer Vision Annotation Tool: A Universal Approach to Data Annotation](https://software.intel.com/en-us/articles/computer-vision-annotation-tool-a-universal-approach-to-data-annotation) +- [VentureBeat: Intel open-sources CVAT, a toolkit for data labeling](https://venturebeat.com/2019/03/05/intel-open-sources-cvat-a-toolkit-for-data-labeling/) diff --git a/cvat/apps/documentation/installation.md b/cvat/apps/documentation/installation.md index 286c7392..9bff3930 100644 --- a/cvat/apps/documentation/installation.md +++ b/cvat/apps/documentation/installation.md @@ -270,29 +270,19 @@ nuctl create project cvat ```bash nuctl deploy --project-name cvat \ --path serverless/openvino/dextr/nuclio \ - --volume `pwd`/serverless/openvino/common:/opt/nuclio/common + --volume `pwd`/serverless/openvino/common:/opt/nuclio/common \ + --platform local ``` ```bash nuctl deploy --project-name cvat \ --path serverless/openvino/omz/public/yolo-v3-tf/nuclio \ - --volume `pwd`/serverless/openvino/common:/opt/nuclio/common + --volume `pwd`/serverless/openvino/common:/opt/nuclio/common \ + --platform local ``` Note: see [deploy.sh](/serverless/deploy.sh) script for more examples. -List of DL models as serverless functions: - -- [Deep Extreme Cut (OpenVINO)](/serverless/openvino/dextr/nuclio) -- [Faster RCNN (TensorFlow)](/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio) -- [Mask RCNN (OpenVINO)](/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio) -- [YOLO v3 (OpenVINO)](/serverless/openvino/omz/public/yolo-v3-tf/nuclio) -- [Faster RCNN (OpenVINO)](/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio) -- [Text detection v4 (OpenVINO)](/serverless/openvino/omz/intel/text-detection-0004/nuclio) -- [Semantic segmentation for ADAS (OpenVINO)](/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio) -- [Mask RCNN (TensorFlow)](/serverless/tensorflow/matterport/mask_rcnn/nuclio) -- [Person ReID (OpenVINO)](/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio) - ### Stop all containers The command below stops and removes containers, networks, volumes, and images diff --git a/serverless/deploy.sh b/serverless/deploy.sh index 556f1d3e..74b58519 100755 --- a/serverless/deploy.sh +++ b/serverless/deploy.sh @@ -5,36 +5,45 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" nuctl create project cvat nuctl deploy --project-name cvat \ --path $SCRIPT_DIR/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio \ - --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common \ + --platform local nuctl deploy --project-name cvat \ --path $SCRIPT_DIR/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio \ - --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common \ + --platform local nuctl deploy --project-name cvat \ --path $SCRIPT_DIR/openvino/omz/public/yolo-v3-tf/nuclio \ - --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common \ + --platform local nuctl deploy --project-name cvat \ --path $SCRIPT_DIR/openvino/omz/intel/text-detection-0004/nuclio \ - --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common \ + --platform local nuctl deploy --project-name cvat \ --path $SCRIPT_DIR/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio \ - --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common \ + --platform local nuctl deploy --project-name cvat \ --path $SCRIPT_DIR/openvino/omz/intel/person-reidentification-retail-300/nuclio \ - --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common \ + --platform local nuctl deploy --project-name cvat \ --path $SCRIPT_DIR/openvino/dextr/nuclio \ - --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common + --volume $SCRIPT_DIR/openvino/common:/opt/nuclio/common \ + --platform local nuctl deploy --project-name cvat \ - --path $SCRIPT_DIR/tensorflow/matterport/mask_rcnn/nuclio + --path $SCRIPT_DIR/tensorflow/matterport/mask_rcnn/nuclio \ + --platform local nuctl deploy --project-name cvat \ - --path $SCRIPT_DIR/tensorflow/faster_rcnn_inception_v2_coco/nuclio + --path $SCRIPT_DIR/tensorflow/faster_rcnn_inception_v2_coco/nuclio \ + --platform local nuctl get function From 2c38cb49673df0f18c6203ffd0e27f4808b48c20 Mon Sep 17 00:00:00 2001 From: zhiltsov-max Date: Tue, 4 Aug 2020 17:26:37 +0300 Subject: [PATCH 21/53] [Datumaro] Add rounding for coordinates (#1970) * Add rounding for annotation coordinates * Fix polygon area computation * update changelog --- CHANGELOG.md | 3 ++- datumaro/datumaro/components/extractor.py | 13 ++++++++----- datumaro/datumaro/plugins/coco_format/converter.py | 8 +++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99de8a72..870bd7ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ### Changed -- +- Shape coordinates are rounded to 2 digits in dumped annotations () +- COCO format does not produce polygon points for bbox annotations () ### Deprecated - diff --git a/datumaro/datumaro/components/extractor.py b/datumaro/datumaro/components/extractor.py index ae0c1fae..1df3c287 100644 --- a/datumaro/datumaro/components/extractor.py +++ b/datumaro/datumaro/components/extractor.py @@ -20,6 +20,9 @@ AnnotationType = Enum('AnnotationType', 'caption', ]) +_COORDINATE_ROUNDING_DIGITS = 2 + + class Annotation: # pylint: disable=redefined-builtin def __init__(self, id=None, type=None, attributes=None, group=None): @@ -378,9 +381,9 @@ class _Shape(Annotation): id=None, attributes=None, group=None): super().__init__(id=id, type=type, attributes=attributes, group=group) - if points is None: - points = [] - self._points = list(points) + if points is not None: + points = [round(p, _COORDINATE_ROUNDING_DIGITS) for p in points] + self._points = points if label is not None: label = int(label) @@ -460,8 +463,8 @@ class Polygon(_Shape): def get_area(self): import pycocotools.mask as mask_utils - _, _, w, h = self.get_bbox() - rle = mask_utils.frPyObjects([self.points], h, w) + x, y, w, h = self.get_bbox() + rle = mask_utils.frPyObjects([self.points], y + h, x + w) area = mask_utils.area(rle)[0] return area diff --git a/datumaro/datumaro/plugins/coco_format/converter.py b/datumaro/datumaro/plugins/coco_format/converter.py index 478e6599..392f0261 100644 --- a/datumaro/datumaro/plugins/coco_format/converter.py +++ b/datumaro/datumaro/plugins/coco_format/converter.py @@ -15,13 +15,12 @@ import pycocotools.mask as mask_utils import datumaro.util.annotation_tools as anno_tools import datumaro.util.mask_tools as mask_tools from datumaro.components.converter import Converter -from datumaro.components.extractor import (DEFAULT_SUBSET_NAME, AnnotationType, - Points) +from datumaro.components.extractor import (_COORDINATE_ROUNDING_DIGITS, + DEFAULT_SUBSET_NAME, AnnotationType, Points) from datumaro.util import cast, find, str_to_bool from .format import CocoPath, CocoTask - SegmentationMode = Enum('SegmentationMode', ['guess', 'polygons', 'mask']) class _TaskConverter: @@ -308,7 +307,7 @@ class _InstancesConverter(_TaskConverter): 'category_id': cast(ann.label, int, -1) + 1, 'segmentation': segmentation, 'area': float(area), - 'bbox': list(map(float, bbox)), + 'bbox': [round(float(n), _COORDINATE_ROUNDING_DIGITS) for n in bbox], 'iscrowd': int(is_crowd), } if 'score' in ann.attributes: @@ -336,7 +335,6 @@ class _KeypointsConverter(_InstancesConverter): 'supercategory': cast(label_cat.parent, str, ''), 'keypoints': [], 'skeleton': [], - } if point_categories is not None: From c36faa7db1df9069fcdc8f05e80b39b16c5f0278 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2020 21:44:11 +0300 Subject: [PATCH 22/53] Bump fakeredis from 1.4.1 to 1.4.2 in /cvat/requirements (#1987) Bumps [fakeredis](https://github.com/jamesls/fakeredis) from 1.4.1 to 1.4.2. - [Release notes](https://github.com/jamesls/fakeredis/releases) - [Commits](https://github.com/jamesls/fakeredis/compare/1.4.1...1.4.2) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- cvat/requirements/testing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/requirements/testing.txt b/cvat/requirements/testing.txt index 25e85bb3..dd142aab 100644 --- a/cvat/requirements/testing.txt +++ b/cvat/requirements/testing.txt @@ -1,5 +1,5 @@ -r development.txt -fakeredis==1.4.1 +fakeredis==1.4.2 # Fix dependencies for fakeredis 1.1.0 # Pip will not reinstall six package if it is installed already six==1.15.0 From 953e3da4c96909ae436f0169da4b3fcf4020df76 Mon Sep 17 00:00:00 2001 From: zhiltsov-max Date: Wed, 5 Aug 2020 21:48:21 +0300 Subject: [PATCH 23/53] Fix rest api task extractor, add job export function (#1972) * Fix rest api extractor * Add job export server function * t * fix field check --- .../plugins/cvat_rest_api_task_images.py | 35 ++++++------------- cvat/apps/dataset_manager/task.py | 26 ++++++++++++-- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/cvat/apps/dataset_manager/formats/datumaro/export_templates/plugins/cvat_rest_api_task_images.py b/cvat/apps/dataset_manager/formats/datumaro/export_templates/plugins/cvat_rest_api_task_images.py index 2af31fcc..9a7a9f06 100644 --- a/cvat/apps/dataset_manager/formats/datumaro/export_templates/plugins/cvat_rest_api_task_images.py +++ b/cvat/apps/dataset_manager/formats/datumaro/export_templates/plugins/cvat_rest_api_task_images.py @@ -42,32 +42,19 @@ class cvat_rest_api_task_images(SourceExtractor): frame_ids=[item_id], outdir=self._cache_dir, quality='original') def _connect(self): - if self._session is not None: + if self._cvat_cli is not None: return - session = None - try: - print("Enter credentials for '%s' to read task data:" % \ - (self._config.server_url)) - username = input('User: ') - password = getpass.getpass() + print("Enter credentials for '%s' to read task data:" % \ + (self._config.server_url)) + username = input('User: ') + password = getpass.getpass() - session = requests.Session() - session.auth = (username, password) + session = requests.Session() - api = CVAT_API_V1(self._config.server_url) - cli = CVAT_CLI(session, api) - - self._session = session - self._cvat_cli = cli - except Exception: - if session is not None: - session.close() - - def __del__(self): - if hasattr(self, '_session'): - if self._session is not None: - self._session.close() + api = CVAT_API_V1(self._config.server_url) + cli = CVAT_CLI(session, api, credentials=(username, password)) + self._cvat_cli = cli @staticmethod def _image_loader(item_id, extractor): @@ -101,15 +88,13 @@ class cvat_rest_api_task_images(SourceExtractor): size = (entry['height'], entry['width']) image = Image(data=self._make_image_loader(item_id), path=self._image_local_path(item_id), size=size) - item = DatasetItem(id=item_id, image=image) + item = DatasetItem(id=osp.splitext(item_filename)[0], image=image) items.append((item.id, item)) - items = sorted(items, key=lambda e: int(e[0])) items = OrderedDict(items) self._items = items self._cvat_cli = None - self._session = None def __iter__(self): for item in self._items.values(): diff --git a/cvat/apps/dataset_manager/task.py b/cvat/apps/dataset_manager/task.py index f2c40dfd..246d2ef0 100644 --- a/cvat/apps/dataset_manager/task.py +++ b/cvat/apps/dataset_manager/task.py @@ -536,6 +536,14 @@ class JobAnnotation: def data(self): return self.ir_data.data + def export(self, dst_file, exporter, host='', **options): + task_data = TaskData( + annotation_ir=self.ir_data, + db_task=self.db_job.segment.task, + host=host, + ) + exporter(dst_file, task_data, **options) + def import_annotations(self, src_file, importer): task_data = TaskData( annotation_ir=AnnotationIR(), @@ -674,6 +682,21 @@ def delete_job_data(pk): annotation = JobAnnotation(pk) annotation.delete() +def export_job(job_id, dst_file, format_name, + server_url=None, save_images=False): + # For big tasks dump function may run for a long time and + # we dont need to acquire lock after the task has been initialized from DB. + # But there is the bug with corrupted dump file in case 2 or + # more dump request received at the same time: + # https://github.com/opencv/cvat/issues/217 + with transaction.atomic(): + job = JobAnnotation(job_id) + job.init_from_db() + + exporter = make_exporter(format_name) + with open(dst_file, 'wb') as f: + job.export(f, exporter, host=server_url, save_images=save_images) + @silk_profile(name="GET task data") @transaction.atomic def get_task_data(pk): @@ -722,8 +745,7 @@ def export_task(task_id, dst_file, format_name, exporter = make_exporter(format_name) with open(dst_file, 'wb') as f: - task.export(f, exporter, host=server_url, - save_images=save_images) + task.export(f, exporter, host=server_url, save_images=save_images) @transaction.atomic def import_task_annotations(task_id, src_file, format_name): From 344b817b80d74be9b5e9fbb6513529e6b7bb4ad5 Mon Sep 17 00:00:00 2001 From: zhiltsov-max Date: Wed, 5 Aug 2020 21:51:32 +0300 Subject: [PATCH 24/53] [Datumaro] Add model info and source info commands (#1973) * Add model info and source info commands * update changelog * adjust cli output --- CHANGELOG.md | 2 +- .../datumaro/cli/contexts/model/__init__.py | 25 ++++++++++++++++ .../datumaro/cli/contexts/project/__init__.py | 29 ++++++++++--------- .../datumaro/cli/contexts/source/__init__.py | 26 +++++++++++++++++ 4 files changed, 67 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 870bd7ab..86fa5353 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.1.0] - Unreleased ### Added -- +- [Datumaro] Added model info and source info commands () ### Changed - Shape coordinates are rounded to 2 digits in dumped annotations () diff --git a/datumaro/datumaro/cli/contexts/model/__init__.py b/datumaro/datumaro/cli/contexts/model/__init__.py index a10f5c0d..0c4f2018 100644 --- a/datumaro/datumaro/cli/contexts/model/__init__.py +++ b/datumaro/datumaro/cli/contexts/model/__init__.py @@ -146,6 +146,30 @@ def run_command(args): return 0 +def build_info_parser(parser_ctor=argparse.ArgumentParser): + parser = parser_ctor() + + parser.add_argument('-n', '--name', + help="Model name") + parser.add_argument('-v', '--verbose', action='store_true', + help="Show details") + parser.add_argument('-p', '--project', dest='project_dir', default='.', + help="Directory of the project to operate on (default: current dir)") + parser.set_defaults(command=info_command) + + return parser + +def info_command(args): + project = load_project(args.project_dir) + + if args.name: + model = project.get_model(args.name) + print(model) + else: + for name, conf in project.config.models.items(): + print(name) + if args.verbose: + print(dict(conf)) def build_parser(parser_ctor=argparse.ArgumentParser): parser = parser_ctor() @@ -154,5 +178,6 @@ def build_parser(parser_ctor=argparse.ArgumentParser): add_subparser(subparsers, 'add', build_add_parser) add_subparser(subparsers, 'remove', build_remove_parser) add_subparser(subparsers, 'run', build_run_parser) + add_subparser(subparsers, 'info', build_info_parser) return parser diff --git a/datumaro/datumaro/cli/contexts/project/__init__.py b/datumaro/datumaro/cli/contexts/project/__init__.py index 65f81886..92d5a81f 100644 --- a/datumaro/datumaro/cli/contexts/project/__init__.py +++ b/datumaro/datumaro/cli/contexts/project/__init__.py @@ -55,7 +55,7 @@ def create_command(args): if osp.isdir(project_env_dir) and os.listdir(project_env_dir): if not args.overwrite: raise CliException("Directory '%s' already exists " - "(pass --overwrite to force creation)" % project_env_dir) + "(pass --overwrite to overwrite)" % project_env_dir) else: shutil.rmtree(project_env_dir, ignore_errors=True) @@ -63,7 +63,7 @@ def create_command(args): if osp.isdir(own_dataset_dir) and os.listdir(own_dataset_dir): if not args.overwrite: raise CliException("Directory '%s' already exists " - "(pass --overwrite to force creation)" % own_dataset_dir) + "(pass --overwrite to overwrite)" % own_dataset_dir) else: # NOTE: remove the dir to avoid using data from previous project shutil.rmtree(own_dataset_dir) @@ -149,7 +149,7 @@ def import_command(args): if osp.isdir(project_env_dir) and os.listdir(project_env_dir): if not args.overwrite: raise CliException("Directory '%s' already exists " - "(pass --overwrite to force creation)" % project_env_dir) + "(pass --overwrite to overwrite)" % project_env_dir) else: shutil.rmtree(project_env_dir, ignore_errors=True) @@ -157,7 +157,7 @@ def import_command(args): if osp.isdir(own_dataset_dir) and os.listdir(own_dataset_dir): if not args.overwrite: raise CliException("Directory '%s' already exists " - "(pass --overwrite to force creation)" % own_dataset_dir) + "(pass --overwrite to overwrite)" % own_dataset_dir) else: # NOTE: remove the dir to avoid using data from previous project shutil.rmtree(own_dataset_dir) @@ -328,7 +328,7 @@ def export_command(args): if dst_dir: if not args.overwrite and osp.isdir(dst_dir) and os.listdir(dst_dir): raise CliException("Directory '%s' already exists " - "(pass --overwrite to force creation)" % dst_dir) + "(pass --overwrite to overwrite)" % dst_dir) else: dst_dir = generate_next_file_name('%s-%s' % \ (project.config.project_name, make_file_name(args.format))) @@ -424,7 +424,7 @@ def extract_command(args): if dst_dir: if not args.overwrite and osp.isdir(dst_dir) and os.listdir(dst_dir): raise CliException("Directory '%s' already exists " - "(pass --overwrite to force creation)" % dst_dir) + "(pass --overwrite to overwrite)" % dst_dir) else: dst_dir = generate_next_file_name('%s-filter' % \ project.config.project_name) @@ -453,10 +453,10 @@ def extract_command(args): return 0 def build_merge_parser(parser_ctor=argparse.ArgumentParser): - parser = parser_ctor(help="Merge projects", + parser = parser_ctor(help="Merge two projects", description=""" Updates items of the current project with items - from the other project.|n + from other project.|n |n Examples:|n - Update a project with items from other project:|n @@ -464,8 +464,8 @@ def build_merge_parser(parser_ctor=argparse.ArgumentParser): """, formatter_class=MultilineFormatter) - parser.add_argument('other_project_dir', - help="Directory of the project to get data updates from") + parser.add_argument('other_project', + help="Path to a project") parser.add_argument('-o', '--output-dir', dest='dst_dir', default=None, help="Output directory (default: current project's dir)") parser.add_argument('--overwrite', action='store_true', @@ -484,11 +484,12 @@ def merge_command(args): if dst_dir: if not args.overwrite and osp.isdir(dst_dir) and os.listdir(dst_dir): raise CliException("Directory '%s' already exists " - "(pass --overwrite to force creation)" % dst_dir) + "(pass --overwrite to overwrite)" % dst_dir) first_dataset = first_project.make_dataset() - first_dataset.update(second_project.make_dataset()) + second_dataset = second_project.make_dataset() + first_dataset.update(second_dataset) first_dataset.save(save_dir=dst_dir) if dst_dir is None: @@ -542,7 +543,7 @@ def diff_command(args): if dst_dir: if not args.overwrite and osp.isdir(dst_dir) and os.listdir(dst_dir): raise CliException("Directory '%s' already exists " - "(pass --overwrite to force creation)" % dst_dir) + "(pass --overwrite to overwrite)" % dst_dir) else: dst_dir = generate_next_file_name('%s-%s-diff' % ( first_project.config.project_name, @@ -602,7 +603,7 @@ def transform_command(args): if dst_dir: if not args.overwrite and osp.isdir(dst_dir) and os.listdir(dst_dir): raise CliException("Directory '%s' already exists " - "(pass --overwrite to force creation)" % dst_dir) + "(pass --overwrite to overwrite)" % dst_dir) else: dst_dir = generate_next_file_name('%s-%s' % \ (project.config.project_name, make_file_name(args.transform))) diff --git a/datumaro/datumaro/cli/contexts/source/__init__.py b/datumaro/datumaro/cli/contexts/source/__init__.py index 94734265..ef9edafb 100644 --- a/datumaro/datumaro/cli/contexts/source/__init__.py +++ b/datumaro/datumaro/cli/contexts/source/__init__.py @@ -225,6 +225,31 @@ def remove_command(args): return 0 +def build_info_parser(parser_ctor=argparse.ArgumentParser): + parser = parser_ctor() + + parser.add_argument('-n', '--name', + help="Source name") + parser.add_argument('-v', '--verbose', action='store_true', + help="Show details") + parser.add_argument('-p', '--project', dest='project_dir', default='.', + help="Directory of the project to operate on (default: current dir)") + parser.set_defaults(command=info_command) + + return parser + +def info_command(args): + project = load_project(args.project_dir) + + if args.name: + source = project.get_source(args.name) + print(source) + else: + for name, conf in project.config.sources.items(): + print(name) + if args.verbose: + print(dict(conf)) + def build_parser(parser_ctor=argparse.ArgumentParser): parser = parser_ctor(description=""" Manipulate data sources inside of a project.|n @@ -243,5 +268,6 @@ def build_parser(parser_ctor=argparse.ArgumentParser): subparsers = parser.add_subparsers() add_subparser(subparsers, 'add', build_add_parser) add_subparser(subparsers, 'remove', build_remove_parser) + add_subparser(subparsers, 'info', build_info_parser) return parser From b5d5f1cbef7a2567377c9ca8b7a343936e0f41a6 Mon Sep 17 00:00:00 2001 From: Nikita Manovich <40690625+nmanovic@users.noreply.github.com> Date: Fri, 7 Aug 2020 06:32:51 +0300 Subject: [PATCH 25/53] Siammask tracker as DL serverless function (#1988) * Implement SiamMask serverless function (cannot be deployed yet) * Fix deployment (need to test the function itself). * Removed mask from state in SiamMask serverless function. * Update CHANGELOG.md * Add support of the tracker serverless function into lambda manager. * Add an example how to deploy siammask serverless function. --- CHANGELOG.md | 1 + cvat/apps/lambda_manager/views.py | 7 ++- serverless/deploy.sh | 4 ++ .../foolwood/siammask/nuclio/function.yaml | 11 +++-- .../foolwood/siammask/nuclio/model_handler.py | 44 +++++++++++++++---- 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86fa5353..99018445 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.1.0] - Unreleased ### Added +- Siammask tracker as DL serverless function () - [Datumaro] Added model info and source info commands () ### Changed diff --git a/cvat/apps/lambda_manager/views.py b/cvat/apps/lambda_manager/views.py index 43ec2e18..d307ca51 100644 --- a/cvat/apps/lambda_manager/views.py +++ b/cvat/apps/lambda_manager/views.py @@ -155,6 +155,12 @@ class LambdaFunction: payload.update({ "max_distance": max_distance }) + elif self.kind == LambdaType.TRACKER: + payload.update({ + "image": self._get_image(db_task, data["frame"], quality), + "shape": data.get("shape", None), + "state": data.get("state", None) + }) else: raise ValidationError( '`{}` lambda function has incorrect type: {}' @@ -469,7 +475,6 @@ class LambdaJob: LambdaJob._call_reid(function, db_task, quality, kwargs.get("threshold"), kwargs.get("max_distance")) - def return_response(success_code=status.HTTP_200_OK): def wrap_response(func): @wraps(func) diff --git a/serverless/deploy.sh b/serverless/deploy.sh index 74b58519..9b150a02 100755 --- a/serverless/deploy.sh +++ b/serverless/deploy.sh @@ -46,4 +46,8 @@ nuctl deploy --project-name cvat \ --path $SCRIPT_DIR/tensorflow/faster_rcnn_inception_v2_coco/nuclio \ --platform local +nuctl deploy --project-name cvat \ + --path $SCRIPT_DIR/pytorch/foolwood/siammask/nuclio \ + --platform local + nuctl get function diff --git a/serverless/pytorch/foolwood/siammask/nuclio/function.yaml b/serverless/pytorch/foolwood/siammask/nuclio/function.yaml index efdb0ca8..bb165c79 100644 --- a/serverless/pytorch/foolwood/siammask/nuclio/function.yaml +++ b/serverless/pytorch/foolwood/siammask/nuclio/function.yaml @@ -26,21 +26,20 @@ spec: value: /opt/nuclio - kind: RUN value: conda create -y -n siammask python=3.6 - - kind: RUN - value: source activate siammask + - kind: SHELL + value: '["conda", "run", "-n", "siammask", "/bin/bash", "-c"]' - kind: RUN value: git clone https://github.com/foolwood/SiamMask.git - kind: RUN - value: pip install -r SiamMask/requirements.txt + value: pip install -r SiamMask/requirements.txt jsonpickle - kind: RUN value: conda install -y gcc_linux-64 - kind: RUN value: cd SiamMask && bash make.sh && cd - - kind: RUN value: wget -P SiamMask/experiments/siammask_sharp http://www.robots.ox.ac.uk/~qwang/SiamMask_DAVIS.pth - - - kind: WORKDIR - value: /opt/nuclio/pysot + - kind: ENTRYPOINT + value: '["conda", "run", "-n", "siammask"]' triggers: myHttpTrigger: diff --git a/serverless/pytorch/foolwood/siammask/nuclio/model_handler.py b/serverless/pytorch/foolwood/siammask/nuclio/model_handler.py index de79c16d..826c7922 100644 --- a/serverless/pytorch/foolwood/siammask/nuclio/model_handler.py +++ b/serverless/pytorch/foolwood/siammask/nuclio/model_handler.py @@ -4,6 +4,9 @@ from tools.test import * import os +from copy import copy +import jsonpickle +import numpy as np class ModelHandler: def __init__(self): @@ -11,7 +14,8 @@ class ModelHandler: self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') torch.backends.cudnn.benchmark = True - base_dir = "/opt/nuclio/SiamMask/experiments/siammask_sharp" + base_dir = os.environ.get("MODEL_PATH", + "/opt/nuclio/SiamMask/experiments/siammask_sharp") class configPath: config = os.path.join(base_dir, "config_davis.json") @@ -21,18 +25,42 @@ class ModelHandler: self.siammask = load_pretrain(siammask, os.path.join(base_dir, "SiamMask_DAVIS.pth")) self.siammask.eval().to(self.device) + def encode_state(self, state): + state['net.zf'] = state['net'].zf + state.pop('net', None) + state.pop('mask', None) + + for k,v in state.items(): + state[k] = jsonpickle.encode(v) + + return state + + def decode_state(self, state): + for k,v in state.items(): + state[k] = jsonpickle.decode(v) + + state['net'] = copy(self.siammask) + state['net'].zf = state['net.zf'] + del state['net.zf'] + + return state def infer(self, image, shape, state): + image = np.array(image) if state is None: # init tracking - x, y, w, h = shape - target_pos = np.array([x + w / 2, y + h / 2]) - target_sz = np.array([w, h]) - state = siamese_init(image, target_pos, target_sz, self.siammask, + xtl, ytl, xbr, ybr = shape + target_pos = np.array([(xtl + xbr) / 2, (ytl + ybr) / 2]) + target_sz = np.array([xbr - xtl, ybr - ytl]) + siammask = copy(self.siammask) # don't modify self.siammask + state = siamese_init(image, target_pos, target_sz, siammask, self.config['hp'], device=self.device) + state = self.encode_state(state) else: # track - state = siamese_track(state, image, mask_enable=True, refine_enable=True, - device=self.device) - shape = state['ploygon'].flatten() + state = self.decode_state(state) + state = siamese_track(state, image, mask_enable=True, + refine_enable=True, device=self.device) + shape = state['ploygon'].flatten().tolist() + state = self.encode_state(state) return {"shape": shape, "state": state} From 71b9745697d79bc216d2241e262c92a6b5412870 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2020 06:33:29 +0300 Subject: [PATCH 26/53] Bump djangorestframework from 3.11.0 to 3.11.1 in /cvat/requirements (#1994) Bumps [djangorestframework](https://github.com/encode/django-rest-framework) from 3.11.0 to 3.11.1. - [Release notes](https://github.com/encode/django-rest-framework/releases) - [Commits](https://github.com/encode/django-rest-framework/compare/3.11.0...3.11.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- cvat/requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/requirements/base.txt b/cvat/requirements/base.txt index aa6afd90..864e79e2 100644 --- a/cvat/requirements/base.txt +++ b/cvat/requirements/base.txt @@ -28,7 +28,7 @@ GitPython==3.1.3 coreapi==2.3.3 django-filter==2.3.0 Markdown==3.2.2 -djangorestframework==3.11.0 +djangorestframework==3.11.1 Pygments==2.6.1 drf-yasg==1.17.1 Shapely==1.7.0 From 5575d57a025c115f9c1426443d57a4c04e66d392 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2020 06:34:13 +0300 Subject: [PATCH 27/53] Bump django-extensions from 3.0.3 to 3.0.4 in /cvat/requirements (#1993) Bumps [django-extensions](https://github.com/django-extensions/django-extensions) from 3.0.3 to 3.0.4. - [Release notes](https://github.com/django-extensions/django-extensions/releases) - [Changelog](https://github.com/django-extensions/django-extensions/blob/master/CHANGELOG.md) - [Commits](https://github.com/django-extensions/django-extensions/compare/3.0.3...3.0.4) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- cvat/requirements/development.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/requirements/development.txt b/cvat/requirements/development.txt index 8efb546a..1beff9e8 100644 --- a/cvat/requirements/development.txt +++ b/cvat/requirements/development.txt @@ -8,6 +8,6 @@ pylint-django==2.2.0 pylint-plugin-utils==0.6 rope==0.17.0 wrapt==1.12.1 -django-extensions==3.0.3 +django-extensions==3.0.4 Werkzeug==1.0.1 snakeviz==2.1.0 From e452bc18b6a313c094b4cdab198b876d9616aae8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2020 06:34:46 +0300 Subject: [PATCH 28/53] Bump pylint-django from 2.2.0 to 2.3.0 in /cvat/requirements (#1992) Bumps [pylint-django](https://github.com/PyCQA/pylint-django) from 2.2.0 to 2.3.0. - [Release notes](https://github.com/PyCQA/pylint-django/releases) - [Changelog](https://github.com/PyCQA/pylint-django/blob/master/CHANGELOG.rst) - [Commits](https://github.com/PyCQA/pylint-django/compare/v2.2.0...v2.3.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- cvat/requirements/development.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/requirements/development.txt b/cvat/requirements/development.txt index 1beff9e8..c7e50071 100644 --- a/cvat/requirements/development.txt +++ b/cvat/requirements/development.txt @@ -4,7 +4,7 @@ isort==4.3.21 lazy-object-proxy==1.5.1 mccabe==0.6.1 pylint==2.5.3 -pylint-django==2.2.0 +pylint-django==2.3.0 pylint-plugin-utils==0.6 rope==0.17.0 wrapt==1.12.1 From 5da7d5ddfc81d00148a418c73a17f4393c099e80 Mon Sep 17 00:00:00 2001 From: Andrey Zhavoronkov <41117609+azhavoro@users.noreply.github.com> Date: Fri, 7 Aug 2020 06:55:23 +0300 Subject: [PATCH 29/53] Added package-lock.json to cvat-core. (#1995) * added package-lock for cvat-core * updated nodejs version --- Dockerfile.ci | 2 +- cvat-core/.gitignore | 1 - cvat-core/package-lock.json | 15508 ++++++++++++++++++++++++++++++++++ 3 files changed, 15509 insertions(+), 2 deletions(-) create mode 100644 cvat-core/package-lock.json diff --git a/Dockerfile.ci b/Dockerfile.ci index 3c4807b4..b0dd7293 100644 --- a/Dockerfile.ci +++ b/Dockerfile.ci @@ -5,7 +5,7 @@ USER root RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list && \ - curl https://deb.nodesource.com/setup_9.x | bash - && \ + curl https://deb.nodesource.com/setup_12.x | bash - && \ apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -yq \ apt-utils \ diff --git a/cvat-core/.gitignore b/cvat-core/.gitignore index 80b08369..b9d6abb3 100644 --- a/cvat-core/.gitignore +++ b/cvat-core/.gitignore @@ -1,6 +1,5 @@ docs node_modules reports -package-lock.json yarn.lock dist diff --git a/cvat-core/package-lock.json b/cvat-core/package-lock.json new file mode 100644 index 00000000..d79d54d0 --- /dev/null +++ b/cvat-core/package-lock.json @@ -0,0 +1,15508 @@ +{ + "name": "cvat-core", + "version": "3.3.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/cli": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.10.5.tgz", + "integrity": "sha512-j9H9qSf3kLdM0Ao3aGPbGZ73mEA9XazuupcS6cDGWuiyAcANoguhP0r2Lx32H5JGw4sSSoHG3x/mxVnHgvOoyA==", + "dev": true, + "requires": { + "chokidar": "^2.1.8", + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.19", + "make-dir": "^2.1.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + } + }, + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz", + "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "semver": "^5.5.0" + } + }, + "@babel/core": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.1.tgz", + "integrity": "sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-module-transforms": "^7.11.0", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.11.1", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.11.0", + "@babel/types": "^7.11.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "@babel/generator": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz", + "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==", + "requires": { + "@babel/types": "^7.11.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", + "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", + "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.10.4", + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", + "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.10.5", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", + "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-regex": "^7.10.4", + "regexpu-core": "^4.7.0" + } + }, + "@babel/helper-define-map": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz", + "integrity": "sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A==", + "dev": true, + "requires": { + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-module-transforms": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/template": "^7.10.4", + "@babel/types": "^7.11.0", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" + }, + "@babel/helper-regex": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", + "dev": true, + "requires": { + "lodash": "^4.17.19" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz", + "integrity": "sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-replace-supers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", + "requires": { + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-simple-access": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", + "requires": { + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", + "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" + }, + "@babel/helper-wrap-function": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", + "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helpers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.2.tgz", + "integrity": "sha512-Vuj/+7vLo6l1Vi7uuO+1ngCDNeVmNbTngcJFKCR/oEtz8tKz0CJxZEGmPt9KcIloZhOZ3Zit6xbpXT2MDlS9Vw==" + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", + "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz", + "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", + "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz", + "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", + "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz", + "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", + "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", + "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz", + "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.10.4" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", + "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", + "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz", + "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", + "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", + "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", + "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", + "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", + "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", + "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz", + "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", + "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", + "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", + "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", + "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", + "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", + "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", + "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", + "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", + "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", + "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", + "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", + "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", + "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", + "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", + "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", + "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", + "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", + "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", + "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", + "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", + "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", + "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", + "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", + "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", + "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", + "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz", + "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", + "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/preset-env": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.0.tgz", + "integrity": "sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.11.0", + "@babel/helper-compilation-targets": "^7.10.4", + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-proposal-async-generator-functions": "^7.10.4", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-dynamic-import": "^7.10.4", + "@babel/plugin-proposal-export-namespace-from": "^7.10.4", + "@babel/plugin-proposal-json-strings": "^7.10.4", + "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", + "@babel/plugin-proposal-numeric-separator": "^7.10.4", + "@babel/plugin-proposal-object-rest-spread": "^7.11.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", + "@babel/plugin-proposal-optional-chaining": "^7.11.0", + "@babel/plugin-proposal-private-methods": "^7.10.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.10.4", + "@babel/plugin-transform-arrow-functions": "^7.10.4", + "@babel/plugin-transform-async-to-generator": "^7.10.4", + "@babel/plugin-transform-block-scoped-functions": "^7.10.4", + "@babel/plugin-transform-block-scoping": "^7.10.4", + "@babel/plugin-transform-classes": "^7.10.4", + "@babel/plugin-transform-computed-properties": "^7.10.4", + "@babel/plugin-transform-destructuring": "^7.10.4", + "@babel/plugin-transform-dotall-regex": "^7.10.4", + "@babel/plugin-transform-duplicate-keys": "^7.10.4", + "@babel/plugin-transform-exponentiation-operator": "^7.10.4", + "@babel/plugin-transform-for-of": "^7.10.4", + "@babel/plugin-transform-function-name": "^7.10.4", + "@babel/plugin-transform-literals": "^7.10.4", + "@babel/plugin-transform-member-expression-literals": "^7.10.4", + "@babel/plugin-transform-modules-amd": "^7.10.4", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-modules-systemjs": "^7.10.4", + "@babel/plugin-transform-modules-umd": "^7.10.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", + "@babel/plugin-transform-new-target": "^7.10.4", + "@babel/plugin-transform-object-super": "^7.10.4", + "@babel/plugin-transform-parameters": "^7.10.4", + "@babel/plugin-transform-property-literals": "^7.10.4", + "@babel/plugin-transform-regenerator": "^7.10.4", + "@babel/plugin-transform-reserved-words": "^7.10.4", + "@babel/plugin-transform-shorthand-properties": "^7.10.4", + "@babel/plugin-transform-spread": "^7.11.0", + "@babel/plugin-transform-sticky-regex": "^7.10.4", + "@babel/plugin-transform-template-literals": "^7.10.4", + "@babel/plugin-transform-typeof-symbol": "^7.10.4", + "@babel/plugin-transform-unicode-escapes": "^7.10.4", + "@babel/plugin-transform-unicode-regex": "^7.10.4", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.11.0", + "browserslist": "^4.12.0", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/preset-modules": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz", + "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", + "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.0", + "@babel/types": "^7.11.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "@babel/types": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", + "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "@cnakazawa/watch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", + "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + } + }, + "@jest/core": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", + "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", + "dev": true, + "requires": { + "@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": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/reporters": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", + "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", + "dev": true, + "requires": { + "@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" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", + "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", + "requires": { + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "requires": { + "@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" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/babel__core": { + "version": "7.1.9", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.9.tgz", + "integrity": "sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw==", + "requires": { + "@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.1", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz", + "integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.13.tgz", + "integrity": "sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ==", + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==" + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/json-schema": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", + "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", + "dev": true + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==" + }, + "@types/yargs": { + "version": "13.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.9.tgz", + "integrity": "sha512-xrvhZ4DZewMDhoH1utLtOAwYQy60eYFoXeje30TzM3VOvQlBwQaEpKFq5m34k1wOw2AKIi2pwtiAjdmhvlBUzg==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", + "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==" + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "abab": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz", + "integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==" + }, + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==" + }, + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" + } + } + }, + "acorn-jsx": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", + "dev": true + }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==" + }, + "airbnb": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/airbnb/-/airbnb-0.0.2.tgz", + "integrity": "sha512-eC+7zzGrcM///BKt04V23v+W3b9dWDUltOzo0j5lzjhvvMc4EiSxh55k2vlVnHTZ0igqA8/i/1j2j+m7UlZ54w==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" + }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true, + "optional": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", + "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==" + }, + "axios": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", + "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "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" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-eslint": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + } + }, + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", + "requires": { + "@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-loader": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", + "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", + "dev": true, + "requires": { + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "requires": { + "@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": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bn.js": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", + "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-or-node": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.3.0.tgz", + "integrity": "sha512-0F2z/VSnLbmEeBcUrSuDH5l0HxTXdQQzLjkmBR4cYfvg1zJrKSlmIZFqyFR8oX0NrwPhy3c3HQ6i3OxMbew4Tg==" + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.13.0.tgz", + "integrity": "sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001093", + "electron-to-chromium": "^1.3.488", + "escalade": "^3.0.1", + "node-releases": "^1.1.58" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "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": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + }, + "dependencies": { + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + } + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "caniuse-lite": { + "version": "1.0.30001111", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001111.tgz", + "integrity": "sha512-xnDje2wchd/8mlJu8sXvWxOGvMgv+uT3iZ3bkIAynKOzToCssWCmkz/ZIkQBs/2pUB4uwnJKVORWQ31UkbVjOg==", + "dev": true + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "requires": { + "rsvp": "^4.8.4" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "catharsis": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", + "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "optional": true + } + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "confusing-browser-globals": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", + "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==", + "dev": true + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "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": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-js-compat": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", + "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", + "dev": true, + "requires": { + "browserslist": "^4.8.5", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "coveralls": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.0.tgz", + "integrity": "sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ==", + "dev": true, + "requires": { + "js-yaml": "^3.13.1", + "lcov-parse": "^1.0.0", + "log-driver": "^1.2.7", + "minimist": "^1.2.5", + "request": "^2.88.2" + } + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "requires": { + "cssom": "0.3.x" + } + }, + "cvat-data": { + "version": "file:../cvat-data", + "requires": { + "async-mutex": "^0.1.4", + "jszip": "3.1.5" + }, + "dependencies": { + "@babel/cli": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.6.4.tgz", + "integrity": "sha512-tqrDyvPryBM6xjIyKKUwr3s8CzmmYidwgdswd7Uc/Cv0ogZcuS1TYQTLx/eWKP3UbJ6JxZAiYlBZabXm/rtRsQ==", + "requires": { + "chokidar": "^2.1.8", + "commander": "^2.8.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.13", + "mkdirp": "^0.5.1", + "output-file-sync": "^2.0.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + } + }, + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.6.4.tgz", + "integrity": "sha512-Rm0HGw101GY8FTzpWSyRbki/jzq+/PkNQJ+nSulrdY6gFGOsNseCqD6KHRYe2E+EdzuBdr2pxCp6s4Uk6eJ+XQ==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.6.4", + "@babel/helpers": "^7.6.2", + "@babel/parser": "^7.6.4", + "@babel/template": "^7.6.0", + "@babel/traverse": "^7.6.3", + "@babel/types": "^7.6.3", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "@babel/generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.4.tgz", + "integrity": "sha512-jsBuXkFoZxk0yWLyGI9llT9oiQ2FeTASmRFE32U+aaDTfoE92t78eroO7PTpU/OrYq38hlcDM6vbfLDaOLy+7w==", + "requires": { + "@babel/types": "^7.6.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", + "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", + "requires": { + "@babel/helper-explode-assignable-expression": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-call-delegate": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", + "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-define-map": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", + "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", + "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", + "requires": { + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", + "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", + "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", + "requires": { + "@babel/types": "^7.5.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", + "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==" + }, + "@babel/helper-regex": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", + "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "requires": { + "lodash": "^4.17.13" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", + "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-replace-supers": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", + "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", + "requires": { + "@babel/helper-member-expression-to-functions": "^7.5.5", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" + } + }, + "@babel/helper-simple-access": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", + "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-wrap-function": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", + "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.2.0" + } + }, + "@babel/helpers": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.2.tgz", + "integrity": "sha512-3/bAUL8zZxYs1cdX2ilEE0WobqbCmKWr/889lf2SS0PpDcpEIY8pb1CCyz0pEcX3pEb+MCbks1jIokz2xLtGTA==", + "requires": { + "@babel/template": "^7.6.0", + "@babel/traverse": "^7.6.2", + "@babel/types": "^7.6.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.4.tgz", + "integrity": "sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A==" + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", + "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.2.0" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", + "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", + "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.2.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz", + "integrity": "sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz", + "integrity": "sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.6.0" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", + "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", + "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", + "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", + "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", + "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", + "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz", + "integrity": "sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.13" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", + "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5", + "@babel/helper-split-export-declaration": "^7.4.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", + "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz", + "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz", + "integrity": "sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.6.0" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", + "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", + "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", + "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", + "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", + "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", + "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", + "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz", + "integrity": "sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g==", + "requires": { + "@babel/helper-module-transforms": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", + "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", + "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.3.tgz", + "integrity": "sha512-jTkk7/uE6H2s5w6VlMHeWuH+Pcy2lmdwFoeWCVnvIrDUnB5gQqTVI8WfmEAhF2CDEarGrknZcmSFg1+bkfCoSw==", + "requires": { + "regexpu-core": "^4.6.0" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", + "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", + "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", + "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", + "requires": { + "@babel/helper-call-delegate": "^7.4.4", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", + "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", + "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", + "requires": { + "regenerator-transform": "^0.14.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", + "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", + "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz", + "integrity": "sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", + "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", + "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", + "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz", + "integrity": "sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.6.0" + } + }, + "@babel/preset-env": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.6.3.tgz", + "integrity": "sha512-CWQkn7EVnwzlOdR5NOm2+pfgSNEZmvGjOhlCHBDq0J8/EStr+G+FvPEiz9B56dR6MoiUFjXhfE4hjLoAKKJtIQ==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-dynamic-import": "^7.5.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.6.2", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.6.2", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.5.0", + "@babel/plugin-transform-block-scoped-functions": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.6.3", + "@babel/plugin-transform-classes": "^7.5.5", + "@babel/plugin-transform-computed-properties": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.6.0", + "@babel/plugin-transform-dotall-regex": "^7.6.2", + "@babel/plugin-transform-duplicate-keys": "^7.5.0", + "@babel/plugin-transform-exponentiation-operator": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.4.4", + "@babel/plugin-transform-function-name": "^7.4.4", + "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-member-expression-literals": "^7.2.0", + "@babel/plugin-transform-modules-amd": "^7.5.0", + "@babel/plugin-transform-modules-commonjs": "^7.6.0", + "@babel/plugin-transform-modules-systemjs": "^7.5.0", + "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.6.3", + "@babel/plugin-transform-new-target": "^7.4.4", + "@babel/plugin-transform-object-super": "^7.5.5", + "@babel/plugin-transform-parameters": "^7.4.4", + "@babel/plugin-transform-property-literals": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.4.5", + "@babel/plugin-transform-reserved-words": "^7.2.0", + "@babel/plugin-transform-shorthand-properties": "^7.2.0", + "@babel/plugin-transform-spread": "^7.6.2", + "@babel/plugin-transform-sticky-regex": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.4.4", + "@babel/plugin-transform-typeof-symbol": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.6.2", + "@babel/types": "^7.6.3", + "browserslist": "^4.6.0", + "core-js-compat": "^3.1.1", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "semver": "^5.5.0" + } + }, + "@babel/template": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", + "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0" + } + }, + "@babel/traverse": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.3.tgz", + "integrity": "sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.6.3", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.6.3", + "@babel/types": "^7.6.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "@babel/types": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.3.tgz", + "integrity": "sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "requires": { + "@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": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==" + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==" + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "requires": { + "@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": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "requires": { + "@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": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "requires": { + "@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": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "requires": { + "@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": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "requires": { + "@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": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "requires": { + "@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": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==" + }, + "ajv": { + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", + "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==" + }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "requires": { + "string-width": "^2.0.0" + } + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==" + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" + }, + "async-mutex": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.1.4.tgz", + "integrity": "sha512-zVWTmAnxxHaeB2B1te84oecI8zTDJ/8G49aVBblRX6be0oq6pAybNcUSxwfgVOmOjSCvN4aYZAqwtyNI8e1YGw==" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "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" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "babel-loader": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", + "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", + "requires": { + "find-cache-dir": "^2.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1", + "pify": "^4.0.1" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "requires": { + "object.assign": "^4.1.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.1.tgz", + "integrity": "sha512-QtULFqKIAtiyNx7NhZ/p4rB8m3xDozVo/pi5VgTlADLF2tNigz/QH+v0m5qhn7XfHT7u+607NcCNOnC0HZAlMg==", + "requires": { + "caniuse-lite": "^1.0.30000999", + "electron-to-chromium": "^1.3.284", + "node-releases": "^1.1.36" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "cacache": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "requires": { + "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" + }, + "dependencies": { + "bluebird": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", + "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==" + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "requires": { + "callsites": "^0.2.0" + }, + "dependencies": { + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" + } + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "caniuse-lite": { + "version": "1.0.30001002", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001002.tgz", + "integrity": "sha512-pRuxPE8wdrWmVPKcDmJJiGBxr6lFJq4ivdSeo9FTmGj5Rb8NX3Mby2pARG57MXF15hYAhZ0nHV5XxT2ig4bz3g==" + }, + "capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "chownr": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==" + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "confusing-browser-globals": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", + "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==" + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "requires": { + "date-now": "^0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=" + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "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": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "copy-webpack-plugin": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.5.tgz", + "integrity": "sha512-7N68eIoQTyudAuxkfPT7HzGoQ+TsmArN/I3HFwG+lVE3FNzqvZKIiaxtYh4o3BIznioxUvx9j26+Rtsc9htQUQ==", + "requires": { + "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", + "serialize-javascript": "^2.1.0", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "requires": { + "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" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + } + } + }, + "core-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", + "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=" + }, + "core-js-compat": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.3.2.tgz", + "integrity": "sha512-gfiK4QnNXhnnHVOIZst2XHdFfdMTPxtR0EGs0TdILMlGIft+087oH6/Sw2xTTIjpWXC9vEwsJA8VG3XTGcmO5g==", + "requires": { + "browserslist": "^4.7.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "requires": { + "path-type": "^3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "requires": { + "esutils": "^2.0.2" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "requires": { + "is-obj": "^1.0.0" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "electron-to-chromium": { + "version": "1.3.289", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.289.tgz", + "integrity": "sha512-39GEOWgTxtMDk/WjIQLg4W/l1s4FZdiMCqUBLjd92tAXsBPDFLwuwCba5OGhuTdVYm6E128TZIqSnMpeocUlCQ==" + }, + "elliptic": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", + "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", + "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", + "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", + "requires": { + "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": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.51", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.51.tgz", + "integrity": "sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "^1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-promise": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", + "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=" + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + }, + "dependencies": { + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } + } + }, + "es6-symbol": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.2.tgz", + "integrity": "sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ==", + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.51" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.5.1.tgz", + "integrity": "sha512-32h99BoLYStT1iq1v2P9uwpyznQ4M2jRiFB6acitKz52Gqn+vPaMDUTB1bYi1WN4Nquj2w+t+bimYUG83DC55A==", + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.2", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.4.1", + "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.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^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" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "eslint-config-airbnb-base": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.0.0.tgz", + "integrity": "sha512-2IDHobw97upExLmsebhtfoD3NAKhV4H0CJWP3Uprd/uk+cHuWYOczPVxQ8PxLFUAw7o3Th1RAU8u1DoUpr+cMA==", + "requires": { + "confusing-browser-globals": "^1.0.7", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + } + }, + "eslint-module-utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", + "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "requires": { + "find-up": "^2.1.0" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.18.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "requires": { + "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" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + } + } + }, + "eslint-plugin-no-unsafe-innerhtml": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsafe-innerhtml/-/eslint-plugin-no-unsafe-innerhtml-1.0.16.tgz", + "integrity": "sha1-fQKHjI6b95FriINtWsEitC8VGTI=", + "requires": { + "eslint": "^3.7.1" + }, + "dependencies": { + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "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" + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "requires": { + "babel-code-frame": "^6.16.0", + "chalk": "^1.1.3", + "concat-stream": "^1.5.2", + "debug": "^2.1.1", + "doctrine": "^2.0.0", + "escope": "^3.6.0", + "espree": "^3.4.0", + "esquery": "^1.0.0", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "glob": "^7.0.3", + "globals": "^9.14.0", + "ignore": "^3.2.0", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.7.5", + "strip-bom": "^3.0.0", + "strip-json-comments": "~2.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" + } + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "requires": { + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "requires": { + "once": "^1.3.0" + } + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "requires": { + "ajv": "^4.7.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", + "slice-ansi": "0.0.4", + "string-width": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "requires": { + "os-homedir": "^1.0.0" + } + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "requires": { + "mkdirp": "^0.5.1" + } + } + } + }, + "eslint-plugin-no-unsanitized": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.0.2.tgz", + "integrity": "sha512-JnwpoH8Sv4QOjrTDutENBHzSnyYtspdjtglYtqUtAHe6f6LLKqykJle+UwFPg23GGwt5hI3amS9CRDezW8GAww==" + }, + "eslint-plugin-security": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.4.0.tgz", + "integrity": "sha512-xlS7P2PLMXeqfhyf3NpqbvbnW04kN8M9NtmhpR3XGyOvt/vNKS7XPXT5EDbwKW9vCjWH4PpfQvgD/+JgN0VJKA==", + "requires": { + "safe-regex": "^1.1.0" + } + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==" + }, + "espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "requires": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" + } + } + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", + "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "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" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==" + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "requires": { + "flat-cache": "^2.0.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==" + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "requires": { + "is-property": "^1.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "requires": { + "ini": "^1.3.4" + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "requires": { + "global-prefix": "^3.0.0" + }, + "dependencies": { + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + } + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==" + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=" + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" + }, + "import-fresh": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.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", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==" + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "requires": { + "ci-info": "^1.5.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==" + }, + "is-my-json-valid": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz", + "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==", + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "^1.0.1" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" + }, + "is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=" + }, + "jszip": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz", + "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==", + "requires": { + "core-js": "~2.3.0", + "es6-promise": "~3.0.2", + "lie": "~3.1.0", + "pako": "~1.0.2", + "readable-stream": "~2.0.6" + }, + "dependencies": { + "core-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", + "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=" + } + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "requires": { + "package-json": "^4.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", + "requires": { + "immediate": "~3.0.5" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==" + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + } + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "requires": { + "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": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=" + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "requires": { + "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" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + } + } + } + } + }, + "node-releases": { + "version": "1.1.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.36.tgz", + "integrity": "sha512-ggXhX6QGyJSjj3r+6ml2LqqC28XOWmKtpb+a15/Zpr9V3yoNazxJNlcQDS9bYaid5FReEWHEgToH1mwoUceWwg==", + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "nodemon": { + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.4.tgz", + "integrity": "sha512-VGPaqQBNk193lrJFotBU8nvWZPqEZY2eIzymy2jjY0fJ9qIsxA0sxQ8ATPl0gZC645gijYEc1jtZvpS8QWzJGQ==", + "requires": { + "chokidar": "^2.1.8", + "debug": "^3.2.6", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.7", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.2", + "update-notifier": "^2.5.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + } + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "output-file-sync": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz", + "integrity": "sha512-mDho4qm7WgIXIGf4eYU1RHN2UU5tPfVYVSRwDJw0uTmj35DQUt/eNp19N7v6T3SrR0ESTEf2up2CGO73qI35zQ==", + "requires": { + "graceful-fs": "^4.1.11", + "is-plain-obj": "^1.1.0", + "mkdirp": "^0.5.1" + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-asn1": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + } + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "pstree.remy": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz", + "integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + } + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "mute-stream": "0.0.5" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=" + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "^1.1.6" + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + }, + "regenerate-unicode-properties": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", + "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-transform": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", + "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "requires": { + "private": "^0.1.6" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + }, + "regexpu-core": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", + "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.1.0", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } + }, + "registry-auth-token": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "requires": { + "rc": "^1.0.1" + } + }, + "regjsgen": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", + "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==" + }, + "regjsparser": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" + } + } + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "dependencies": { + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + } + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=" + }, + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==" + } + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "requires": { + "semver": "^5.0.3" + } + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "requires": { + "execa": "^0.7.0" + } + }, + "terser": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.6.tgz", + "integrity": "sha512-4lYPyeNmstjIIESr/ysHg2vUPRGf2tzF9z2yYwnowXVuVzLEamPN1Gfrz7f8I9uEPuHcbFlW4PLIAsJoxXyJ1g==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "requires": { + "nopt": "~1.0.10" + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "undefsafe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", + "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=", + "requires": { + "debug": "^2.2.0" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==" + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", + "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==" + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", + "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==" + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + } + } + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + }, + "update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "^1.0.1" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vm-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==" + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } + }, + "webpack": { + "version": "4.41.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz", + "integrity": "sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==", + "requires": { + "@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", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.1", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", + "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==" + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==" + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } + } + }, + "webpack-cli": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.9.tgz", + "integrity": "sha512-xwnSxWl8nZtBl/AFJCOn9pG7s5CYUYdZxmmukv+fAHLcBIHM36dImfpQg3WfShZXeArkWlf6QRw24Klcsv8a5A==", + "requires": { + "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", + "supports-color": "6.1.0", + "v8-compile-cache": "2.0.3", + "yargs": "13.2.4" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.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" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "requires": { + "invert-kv": "^2.0.0" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "v8-compile-cache": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz", + "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==" + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yargs": { + "version": "13.2.4", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", + "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", + "requires": { + "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" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "requires": { + "string-width": "^2.1.1" + } + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "requires": { + "errno": "~0.1.7" + } + }, + "worker-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz", + "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==", + "requires": { + "loader-utils": "^1.0.0", + "schema-utils": "^0.4.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==" + }, + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "requires": { + "mkdirp": "^0.5.1" + } + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + } + } + } + } + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-browser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.1.1.tgz", + "integrity": "sha512-5n2aWI57qC3kZaK4j2zYsG6L1LrxgLptGCNhMQgdKhVn6cSdcq43pp6xHPfTHG3TYM6myF4tIPWiZtfdVDgb9w==" + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "electron-to-chromium": { + "version": "1.3.520", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.520.tgz", + "integrity": "sha512-q6H9E1sXDCjRHP+X06vcP+N0ki8ZvYoRPZfKnDuiRX10WWXxEHzKFVf4O9rBFMpuPtR3M+2KAdJnugJoBBp3Rw==", + "dev": true + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "error-stack-parser": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", + "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==", + "requires": { + "stackframe": "^1.1.1" + } + }, + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + }, + "dependencies": { + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escalade": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", + "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + } + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.1.0.tgz", + "integrity": "sha512-QhrbdRD7ofuV09IuE2ySWBz0FyXCq0rriLTZXZqaWSI79CVtHVRdkFuFTViiqzZhkCgfOh9USpriuGN2gIpZDQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^6.0.0", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.4.1", + "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.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^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" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-config-airbnb-base": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.0.0.tgz", + "integrity": "sha512-2IDHobw97upExLmsebhtfoD3NAKhV4H0CJWP3Uprd/uk+cHuWYOczPVxQ8PxLFUAw7o3Th1RAU8u1DoUpr+cMA==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.7", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.18.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + } + } + }, + "eslint-plugin-no-unsafe-innerhtml": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsafe-innerhtml/-/eslint-plugin-no-unsafe-innerhtml-1.0.16.tgz", + "integrity": "sha1-fQKHjI6b95FriINtWsEitC8VGTI=", + "dev": true, + "requires": { + "eslint": "^3.7.1" + }, + "dependencies": { + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "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" + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "dev": true, + "requires": { + "babel-code-frame": "^6.16.0", + "chalk": "^1.1.3", + "concat-stream": "^1.5.2", + "debug": "^2.1.1", + "doctrine": "^2.0.0", + "escope": "^3.6.0", + "espree": "^3.4.0", + "esquery": "^1.0.0", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "glob": "^7.0.3", + "globals": "^9.14.0", + "ignore": "^3.2.0", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.7.5", + "strip-bom": "^3.0.0", + "strip-json-comments": "~2.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" + } + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "^1.3.0" + } + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", + "slice-ansi": "0.0.4", + "string-width": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + } + } + }, + "eslint-plugin-no-unsanitized": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.1.2.tgz", + "integrity": "sha512-KPShfliA3Uy9qqwQx35P1fwIOeJjZkb0FbMMUFztRYRposzaynsM8JCEb952fqkidROl1kpqY80uSvn+TcWkQQ==", + "dev": true + }, + "eslint-plugin-security": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.4.0.tgz", + "integrity": "sha512-xlS7P2PLMXeqfhyf3NpqbvbnW04kN8M9NtmhpR3XGyOvt/vNKS7XPXT5EDbwKW9vCjWH4PpfQvgD/+JgN0VJKA==", + "dev": true, + "requires": { + "safe-regex": "^1.1.0" + } + }, + "eslint-scope": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", + "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exec-sh": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", + "integrity": "sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==" + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.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" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "requires": { + "@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" + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "requires": { + "bser": "2.1.1" + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "^1.0.0" + } + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + }, + "dependencies": { + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + } + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.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", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + } + } + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==" + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.20.5", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.5.tgz", + "integrity": "sha512-VTPuvvGQtxvCeghwspQu1rBgjYUT6FGxPlvFKbYuFtgc4ADsX3U5ihZOYN0qyU6u+d4X9xXb0IT5O6QpXKt87A==", + "dev": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==" + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "requires": { + "@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" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0" + } + }, + "jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", + "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", + "dev": true, + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.9.0" + }, + "dependencies": { + "jest-cli": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", + "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", + "dev": true, + "requires": { + "@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-changed-files": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", + "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "requires": { + "@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": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-docblock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", + "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", + "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", + "requires": { + "@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": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", + "requires": { + "@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": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", + "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", + "requires": { + "@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": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==" + }, + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "requires": { + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "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" + } + }, + "jest-jasmine2": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", + "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", + "requires": { + "@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-junit": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-6.4.0.tgz", + "integrity": "sha512-GXEZA5WBeUich94BARoEUccJumhCgCerg7mXDFLxWwI2P7wL3Z7sGWk+53x343YdBLjiMR9aD/gYMVKO+0pE4Q==", + "dev": true, + "requires": { + "jest-validate": "^24.0.0", + "mkdirp": "^0.5.1", + "strip-ansi": "^4.0.0", + "xml": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "jest-leak-detector": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", + "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", + "requires": { + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "requires": { + "@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": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "requires": { + "@jest/types": "^24.9.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==" + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==" + }, + "jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "requires": { + "@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-resolve-dependencies": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", + "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.9.0" + } + }, + "jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", + "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", + "requires": { + "@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": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", + "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", + "requires": { + "@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": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==" + }, + "jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", + "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "requires": { + "@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" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "requires": { + "@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" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "requires": { + "@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": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", + "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", + "dev": true, + "requires": { + "@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": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "js2xmlparser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", + "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", + "dev": true, + "requires": { + "xmlcreate": "^2.0.3" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "jsdoc": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.5.tgz", + "integrity": "sha512-SbY+i9ONuxSK35cgVHaI8O9senTE4CDYAmGSDJ5l3+sfe62Ff4gy96osy6OW84t4K4A8iGnMrlRrsSItSNp3RQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.9.4", + "bluebird": "^3.7.2", + "catharsis": "^0.8.11", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.1", + "klaw": "^3.0.0", + "markdown-it": "^10.0.0", + "markdown-it-anchor": "^5.2.7", + "marked": "^0.8.2", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.10.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", + "dev": true + } + } + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "requires": { + "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": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.0.2.tgz", + "integrity": "sha512-rmzlgFZiQPc6q4HDyK8s9Qb4oxBnI5sF61y/Co5PV0lc3q2bIuRsNdueVbhoSHdKM4fxeimphOAtfz47yjCfeA==", + "requires": { + "esprima": "1.2.2", + "static-eval": "2.0.2", + "underscore": "1.7.0" + }, + "dependencies": { + "esprima": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", + "integrity": "sha1-dqD9Zvz+FU/SkmZ9wmQBl1CxZXs=" + } + } + }, + "jsonpointer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.1.0.tgz", + "integrity": "sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg==", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "lcov-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", + "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", + "dev": true + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==" + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + }, + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", + "dev": true, + "requires": { + "leven": "^3.1.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "requires": { + "tmpl": "1.0.x" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-it": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true + }, + "marked": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", + "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "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": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=" + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", + "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + } + }, + "node-releases": { + "version": "1.1.60", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", + "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.entries": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", + "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "has": "^1.0.3" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-asn1": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true, + "optional": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "^3.0.0" + } + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "optional": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "prompts": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.2.tgz", + "integrity": "sha512-Q06uKs2CkNYVID0VqwfAl9mipo99zkBv/n2JtWY89Yxa3ZabWSrs0e2KTudKVa3peLUvYXMefDqIleLPVUBZMA==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.4" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "mute-stream": "0.0.5" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + } + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "requires": { + "util.promisify": "^1.0.0" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "regenerate": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", + "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "regexpu-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", + "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "regjsparser": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + } + } + }, + "request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "requires": { + "lodash": "^4.17.19" + } + }, + "request-promise-native": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", + "requires": { + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + } + } + }, + "requizzle": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "dependencies": { + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + } + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==" + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "rxjs": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz", + "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "requires": { + "@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" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==" + }, + "stackframe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", + "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==" + }, + "static-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", + "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", + "requires": { + "escodegen": "^1.8.1" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "store": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/store/-/store-2.0.12.tgz", + "integrity": "sha1-jFNOKguDH3K3X8XxEZhXxE711ZM=" + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz", + "integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^3.1.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "requires": { + "punycode": "^2.1.0" + } + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "optional": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "requires": { + "makeerror": "1.0.x" + } + }, + "watchpack": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", + "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true, + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.1.tgz", + "integrity": "sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "webpack": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz", + "integrity": "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.3.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.3", + "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.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "webpack-cli": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", + "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.1", + "findup-sync": "^3.0.0", + "global-modules": "^2.0.0", + "import-local": "^2.0.0", + "interpret": "^1.4.0", + "loader-utils": "^1.4.0", + "supports-color": "^6.1.0", + "v8-compile-cache": "^2.1.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "worker-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz", + "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==", + "requires": { + "loader-utils": "^1.0.0", + "schema-utils": "^0.4.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", + "dev": true + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "xmlcreate": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", + "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "requires": { + "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.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} From 4cb75a6a7f9fc508730fb14ea85fa09784bdf05b Mon Sep 17 00:00:00 2001 From: Andrey Zhavoronkov <41117609+azhavoro@users.noreply.github.com> Date: Fri, 7 Aug 2020 07:09:18 +0300 Subject: [PATCH 30/53] Added ability to change user password (#1954) * added ability to change user password * Update CHANGELOG.md * fixed comments * fixed linter warnings * updated version of cvat-ui and cvat-core --- CHANGELOG.md | 1 + cvat-core/package.json | 2 +- cvat-core/src/api-implementation.js | 4 + cvat-core/src/api.js | 13 ++ cvat-core/src/server-proxy.js | 19 ++ cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- cvat-ui/src/actions/auth-actions.ts | 52 +++++- .../change-password-form.tsx | 166 ++++++++++++++++++ .../change-password-modal.tsx | 84 +++++++++ cvat-ui/src/components/cvat-app.tsx | 11 ++ cvat-ui/src/components/header/header.tsx | 25 +++ cvat-ui/src/containers/header/header.tsx | 15 +- cvat-ui/src/index.tsx | 14 +- cvat-ui/src/reducers/auth-reducer.ts | 47 +++++ cvat-ui/src/reducers/interfaces.ts | 9 + cvat-ui/src/reducers/notifications-reducer.ts | 47 +++++ cvat-ui/src/utils/plugin-checker.ts | 11 +- cvat-ui/src/utils/url-checker.ts | 18 ++ cvat/settings/base.py | 1 + 20 files changed, 527 insertions(+), 16 deletions(-) create mode 100644 cvat-ui/src/components/change-password-modal/change-password-form.tsx create mode 100644 cvat-ui/src/components/change-password-modal/change-password-modal.tsx create mode 100644 cvat-ui/src/utils/url-checker.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 99018445..a4cd6e41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support creating multiple jobs for each task through python cli (https://github.com/opencv/cvat/pull/1950) - python cli over https () - Error message when plugins weren't able to initialize instead of infinite loading () +- Ability to change user password () ### Changed - Smaller object details () diff --git a/cvat-core/package.json b/cvat-core/package.json index a34f53d0..7d75dbc5 100644 --- a/cvat-core/package.json +++ b/cvat-core/package.json @@ -1,6 +1,6 @@ { "name": "cvat-core", - "version": "3.3.1", + "version": "3.4.0", "description": "Part of Computer Vision Tool which presents an interface for client-side integration", "main": "babel.config.js", "scripts": { diff --git a/cvat-core/src/api-implementation.js b/cvat-core/src/api-implementation.js index 7372ed3b..32dd6c5b 100644 --- a/cvat-core/src/api-implementation.js +++ b/cvat-core/src/api-implementation.js @@ -93,6 +93,10 @@ await serverProxy.server.logout(); }; + cvat.server.changePassword.implementation = async (oldPassword, newPassword1, newPassword2) => { + await serverProxy.server.changePassword(oldPassword, newPassword1, newPassword2); + }; + cvat.server.authorized.implementation = async () => { const result = await serverProxy.server.authorized(); return result; diff --git a/cvat-core/src/api.js b/cvat-core/src/api.js index 53c30d0d..ab5ba39b 100644 --- a/cvat-core/src/api.js +++ b/cvat-core/src/api.js @@ -193,6 +193,19 @@ function build() { .apiWrapper(cvat.server.logout); return result; }, + /** + * Method allows to change user password + * @method changePassword + * @async + * @memberof module:API.cvat.server + * @throws {module:API.cvat.exceptions.PluginError} + * @throws {module:API.cvat.exceptions.ServerError} + */ + async changePassword(oldPassword, newPassword1, newPassword2) { + const result = await PluginRegistry + .apiWrapper(cvat.server.changePassword, oldPassword, newPassword1, newPassword2); + return result; + }, /** * Method allows to know whether you are authorized on the server * @method authorized diff --git a/cvat-core/src/server-proxy.js b/cvat-core/src/server-proxy.js index 00f06d77..4a0c9ebd 100644 --- a/cvat-core/src/server-proxy.js +++ b/cvat-core/src/server-proxy.js @@ -246,6 +246,24 @@ Axios.defaults.headers.common.Authorization = ''; } + async function changePassword(oldPassword, newPassword1, newPassword2) { + try { + const data = JSON.stringify({ + old_password: oldPassword, + new_password1: newPassword1, + new_password2:newPassword2, + }); + await Axios.post(`${config.backendAPI}/auth/password/change`, data, { + proxy: config.proxy, + headers: { + 'Content-Type': 'application/json', + }, + }); + } catch (errorData) { + throw generateError(errorData); + } + } + async function authorized() { try { await module.exports.users.getSelf(); @@ -768,6 +786,7 @@ exception, login, logout, + changePassword, authorized, register, request: serverRequest, diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 0f2ece18..256a48e6 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.6.7", + "version": "1.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index b97d19fe..1ec122bd 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.6.7", + "version": "1.7.0", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { diff --git a/cvat-ui/src/actions/auth-actions.ts b/cvat-ui/src/actions/auth-actions.ts index f7a0f3e9..3aff6ef3 100644 --- a/cvat-ui/src/actions/auth-actions.ts +++ b/cvat-ui/src/actions/auth-actions.ts @@ -5,6 +5,7 @@ import { ActionUnion, createAction, ThunkAction } from 'utils/redux'; import { UserConfirmation } from 'components/register-page/register-form'; import getCore from 'cvat-core-wrapper'; +import isReachable from 'utils/url-checker'; const cvat = getCore(); @@ -20,9 +21,16 @@ export enum AuthActionTypes { LOGOUT = 'LOGOUT', LOGOUT_SUCCESS = 'LOGOUT_SUCCESS', LOGOUT_FAILED = 'LOGOUT_FAILED', + CHANGE_PASSWORD = 'CHANGE_PASSWORD', + CHANGE_PASSWORD_SUCCESS = 'CHANGE_PASSWORD_SUCCESS', + CHANGE_PASSWORD_FAILED = 'CHANGE_PASSWORD_FAILED', + SWITCH_CHANGE_PASSWORD_DIALOG = 'SWITCH_CHANGE_PASSWORD_DIALOG', + LOAD_AUTH_ACTIONS = 'LOAD_AUTH_ACTIONS', + LOAD_AUTH_ACTIONS_SUCCESS = 'LOAD_AUTH_ACTIONS_SUCCESS', + LOAD_AUTH_ACTIONS_FAILED = 'LOAD_AUTH_ACTIONS_FAILED', } -const authActions = { +export const authActions = { authorizeSuccess: (user: any) => createAction(AuthActionTypes.AUTHORIZED_SUCCESS, { user }), authorizeFailed: (error: any) => createAction(AuthActionTypes.AUTHORIZED_FAILED, { error }), login: () => createAction(AuthActionTypes.LOGIN), @@ -34,6 +42,21 @@ const authActions = { logout: () => createAction(AuthActionTypes.LOGOUT), logoutSuccess: () => createAction(AuthActionTypes.LOGOUT_SUCCESS), logoutFailed: (error: any) => createAction(AuthActionTypes.LOGOUT_FAILED, { error }), + changePassword: () => createAction(AuthActionTypes.CHANGE_PASSWORD), + changePasswordSuccess: () => createAction(AuthActionTypes.CHANGE_PASSWORD_SUCCESS), + changePasswordFailed: (error: any) => ( + createAction(AuthActionTypes.CHANGE_PASSWORD_FAILED, { error }) + ), + switchChangePasswordDialog: (showChangePasswordDialog: boolean) => ( + createAction(AuthActionTypes.SWITCH_CHANGE_PASSWORD_DIALOG, { showChangePasswordDialog }) + ), + loadServerAuthActions: () => createAction(AuthActionTypes.LOAD_AUTH_ACTIONS), + loadServerAuthActionsSuccess: (allowChangePassword: boolean) => ( + createAction(AuthActionTypes.LOAD_AUTH_ACTIONS_SUCCESS, { allowChangePassword }) + ), + loadServerAuthActionsFailed: (error: any) => ( + createAction(AuthActionTypes.LOAD_AUTH_ACTIONS_FAILED, { error }) + ), }; export type AuthActions = ActionUnion; @@ -100,3 +123,30 @@ export const authorizedAsync = (): ThunkAction => async (dispatch) => { dispatch(authActions.authorizeFailed(error)); } }; + +export const changePasswordAsync = (oldPassword: string, + newPassword1: string, newPassword2: string): ThunkAction => async (dispatch) => { + dispatch(authActions.changePassword()); + + try { + await cvat.server.changePassword(oldPassword, newPassword1, newPassword2); + dispatch(authActions.changePasswordSuccess()); + } catch (error) { + dispatch(authActions.changePasswordFailed(error)); + } +}; + +export const loadAuthActionsAsync = (): ThunkAction => async (dispatch) => { + dispatch(authActions.loadServerAuthActions()); + + try { + const promises: Promise[] = [ + isReachable(`${cvat.config.backendAPI}/auth/password/change`, 'OPTIONS'), + ]; + const [allowChangePassword] = await Promise.all(promises); + + dispatch(authActions.loadServerAuthActionsSuccess(allowChangePassword)); + } catch (error) { + dispatch(authActions.loadServerAuthActionsFailed(error)); + } +}; diff --git a/cvat-ui/src/components/change-password-modal/change-password-form.tsx b/cvat-ui/src/components/change-password-modal/change-password-form.tsx new file mode 100644 index 00000000..f1548daa --- /dev/null +++ b/cvat-ui/src/components/change-password-modal/change-password-form.tsx @@ -0,0 +1,166 @@ +// Copyright (C) 2020 Intel Corporation +// +// SPDX-License-Identifier: MIT + +import React from 'react'; +import Form, { FormComponentProps } from 'antd/lib/form/Form'; +import Button from 'antd/lib/button'; +import Icon from 'antd/lib/icon'; +import Input from 'antd/lib/input'; + +import patterns from 'utils/validation-patterns'; + +export interface ChangePasswordData { + oldPassword: string; + newPassword1: string; + newPassword2: string; +} + +type ChangePasswordFormProps = { + fetching: boolean; + onSubmit(loginData: ChangePasswordData): void; +} & FormComponentProps; + +class ChangePasswordFormComponent extends React.PureComponent { + private validateConfirmation = (_: any, value: string, callback: Function): void => { + const { form } = this.props; + if (value && value !== form.getFieldValue('newPassword1')) { + callback('Two passwords that you enter is inconsistent!'); + } else { + callback(); + } + }; + + private validatePassword = (_: any, value: string, callback: Function): void => { + const { form } = this.props; + if (!patterns.validatePasswordLength.pattern.test(value)) { + callback(patterns.validatePasswordLength.message); + } + + if (!patterns.passwordContainsNumericCharacters.pattern.test(value)) { + callback(patterns.passwordContainsNumericCharacters.message); + } + + if (!patterns.passwordContainsUpperCaseCharacter.pattern.test(value)) { + callback(patterns.passwordContainsUpperCaseCharacter.message); + } + + if (!patterns.passwordContainsLowerCaseCharacter.pattern.test(value)) { + callback(patterns.passwordContainsLowerCaseCharacter.message); + } + + if (value) { + form.validateFields(['newPassword2'], { force: true }); + } + callback(); + }; + + private handleSubmit = (e: React.FormEvent): void => { + e.preventDefault(); + const { + form, + onSubmit, + } = this.props; + + form.validateFields((error, values): void => { + if (!error) { + const validatedFields = { + ...values, + confirmations: [], + }; + + onSubmit(validatedFields); + } + }); + }; + + private renderOldPasswordField(): JSX.Element { + const { form } = this.props; + + return ( + + {form.getFieldDecorator('oldPassword', { + rules: [{ + required: true, + message: 'Please input your current password!', + }], + })(} + placeholder='Current password' + />)} + + ); + } + + private renderNewPasswordField(): JSX.Element { + const { form } = this.props; + + return ( + + {form.getFieldDecorator('newPassword1', { + rules: [{ + required: true, + message: 'Please input new password!', + }, { + validator: this.validatePassword, + }], + })(} + placeholder='New password' + />)} + + ); + } + + private renderNewPasswordConfirmationField(): JSX.Element { + const { form } = this.props; + + return ( + + {form.getFieldDecorator('newPassword2', { + rules: [{ + required: true, + message: 'Please confirm your new password!', + }, { + validator: this.validateConfirmation, + }], + })(} + placeholder='Confirm new password' + />)} + + ); + } + + public render(): JSX.Element { + const { fetching } = this.props; + + return ( +
+ {this.renderOldPasswordField()} + {this.renderNewPasswordField()} + {this.renderNewPasswordConfirmationField()} + + + + +
+ ); + } +} + +export default Form.create()(ChangePasswordFormComponent); diff --git a/cvat-ui/src/components/change-password-modal/change-password-modal.tsx b/cvat-ui/src/components/change-password-modal/change-password-modal.tsx new file mode 100644 index 00000000..2f4f538b --- /dev/null +++ b/cvat-ui/src/components/change-password-modal/change-password-modal.tsx @@ -0,0 +1,84 @@ +// Copyright (C) 2020 Intel Corporation +// +// SPDX-License-Identifier: MIT + +import React from 'react'; +import { connect } from 'react-redux'; +import Modal from 'antd/lib/modal'; +import Title from 'antd/lib/typography/Title'; + +import { changePasswordAsync } from 'actions/auth-actions'; +import { CombinedState } from 'reducers/interfaces'; +import ChangePasswordForm, { ChangePasswordData } from './change-password-form'; + + +interface StateToProps { + fetching: boolean; + visible: boolean; +} + +interface DispatchToProps { + onChangePassword( + oldPassword: string, + newPassword1: string, + newPassword2: string): void; +} + +interface ChangePasswordPageComponentProps { + fetching: boolean; + visible: boolean; + onChangePassword: (oldPassword: string, newPassword1: string, newPassword2: string) => void; + onClose(): void; +} + +function mapStateToProps(state: CombinedState): StateToProps { + return { + fetching: state.auth.fetching, + visible: state.auth.showChangePasswordDialog, + }; +} + +function mapDispatchToProps(dispatch: any): DispatchToProps { + return ({ + onChangePassword(oldPassword: string, newPassword1: string, newPassword2: string): void { + dispatch(changePasswordAsync(oldPassword, newPassword1, newPassword2)); + }, + }); +} + +function ChangePasswordComponent(props: ChangePasswordPageComponentProps): JSX.Element { + const { + fetching, + onChangePassword, + visible, + onClose, + } = props; + + return ( + Change password} + okType='primary' + okText='Submit' + footer={null} + visible={visible} + destroyOnClose + onCancel={onClose} + > + { + onChangePassword( + changePasswordData.oldPassword, + changePasswordData.newPassword1, + changePasswordData.newPassword2, + ); + }} + fetching={fetching} + /> + + ); +} + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(ChangePasswordComponent); diff --git a/cvat-ui/src/components/cvat-app.tsx b/cvat-ui/src/components/cvat-app.tsx index 19c26f66..3417b4b4 100644 --- a/cvat-ui/src/components/cvat-app.tsx +++ b/cvat-ui/src/components/cvat-app.tsx @@ -38,6 +38,7 @@ interface CVATAppProps { resetMessages: () => void; switchShortcutsDialog: () => void; switchSettingsDialog: () => void; + loadAuthActions: () => void; keyMap: Record; userInitialized: boolean; userFetching: boolean; @@ -51,6 +52,9 @@ interface CVATAppProps { aboutFetching: boolean; userAgreementsFetching: boolean; userAgreementsInitialized: boolean; + authActionsFetching: boolean; + authActionsInitialized: boolean; + allowChangePassword: boolean; notifications: NotificationsState; user: any; } @@ -84,6 +88,7 @@ class CVATApplication extends React.PureComponent void; switchSettingsDialog: (show: boolean) => void; + switchChangePasswordDialog: (show: boolean) => void; logoutFetching: boolean; + changePasswordFetching: boolean; installedAnalytics: boolean; serverHost: string; username: string; @@ -34,6 +37,8 @@ interface HeaderContainerProps { uiVersion: string; switchSettingsShortcut: string; settingsDialogShown: boolean; + changePasswordDialogShown: boolean; + renderChangePasswordItem: boolean; } type Props = HeaderContainerProps & RouteComponentProps; @@ -51,9 +56,12 @@ function HeaderContainer(props: Props): JSX.Element { uiVersion, onLogout, logoutFetching, + changePasswordFetching, settingsDialogShown, switchSettingsShortcut, switchSettingsDialog, + switchChangePasswordDialog, + renderChangePasswordItem, } = props; const { @@ -136,6 +144,16 @@ function HeaderContainer(props: Props): JSX.Element { About + {renderChangePasswordItem && ( + switchChangePasswordDialog(true)} + disabled={changePasswordFetching} + > + {changePasswordFetching ? : } + Change password + + )} + switchSettingsDialog(false)} /> + { renderChangePasswordItem + && ( + switchChangePasswordDialog(false)} + /> + )} + ); } diff --git a/cvat-ui/src/containers/header/header.tsx b/cvat-ui/src/containers/header/header.tsx index abda8b46..ec20a624 100644 --- a/cvat-ui/src/containers/header/header.tsx +++ b/cvat-ui/src/containers/header/header.tsx @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import getCore from 'cvat-core-wrapper'; import HeaderComponent from 'components/header/header'; import { SupportedPlugins, CombinedState } from 'reducers/interfaces'; -import { logoutAsync } from 'actions/auth-actions'; +import { logoutAsync, authActions } from 'actions/auth-actions'; import { switchSettingsDialog } from 'actions/settings-actions'; const core = getCore(); @@ -25,20 +25,27 @@ interface StateToProps { uiVersion: string; switchSettingsShortcut: string; settingsDialogShown: boolean; + changePasswordDialogShown: boolean; + changePasswordFetching: boolean; + renderChangePasswordItem: boolean; } interface DispatchToProps { onLogout: () => void; switchSettingsDialog: (show: boolean) => void; + switchChangePasswordDialog: (show: boolean) => void; } function mapStateToProps(state: CombinedState): StateToProps { const { auth: { fetching: logoutFetching, + fetching: changePasswordFetching, user: { username, }, + showChangePasswordDialog: changePasswordDialogShown, + allowChangePassword: renderChangePasswordItem, }, plugins: { list, @@ -68,6 +75,9 @@ function mapStateToProps(state: CombinedState): StateToProps { uiVersion: packageVersion.ui, switchSettingsShortcut: normalizedKeyMap.SWITCH_SETTINGS, settingsDialogShown, + changePasswordFetching, + changePasswordDialogShown, + renderChangePasswordItem, }; } @@ -75,6 +85,9 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { return { onLogout: (): void => dispatch(logoutAsync()), switchSettingsDialog: (show: boolean): void => dispatch(switchSettingsDialog(show)), + switchChangePasswordDialog: (show: boolean): void => ( + dispatch(authActions.switchChangePasswordDialog(show)) + ), }; } diff --git a/cvat-ui/src/index.tsx b/cvat-ui/src/index.tsx index 6d614837..d246dc0e 100644 --- a/cvat-ui/src/index.tsx +++ b/cvat-ui/src/index.tsx @@ -14,7 +14,10 @@ import createRootReducer from 'reducers/root-reducer'; import createCVATStore, { getCVATStore } from 'cvat-store'; import logger, { LogType } from 'cvat-logger'; -import { authorizedAsync } from 'actions/auth-actions'; +import { + authorizedAsync, + loadAuthActionsAsync, +} from 'actions/auth-actions'; import { getFormatsAsync } from 'actions/formats-actions'; import { checkPluginsAsync } from 'actions/plugins-actions'; import { getUsersAsync } from 'actions/users-actions'; @@ -27,6 +30,7 @@ import { resetMessages, } from './actions/notification-actions'; + import { CombinedState, NotificationsState, @@ -48,6 +52,9 @@ interface StateToProps { formatsFetching: boolean; userAgreementsInitialized: boolean; userAgreementsFetching: boolean; + authActionsFetching: boolean; + authActionsInitialized: boolean; + allowChangePassword: boolean; notifications: NotificationsState; user: any; keyMap: Record; @@ -64,6 +71,7 @@ interface DispatchToProps { switchShortcutsDialog: () => void; loadUserAgreements: () => void; switchSettingsDialog: () => void; + loadAuthActions: () => void; } function mapStateToProps(state: CombinedState): StateToProps { @@ -88,6 +96,9 @@ function mapStateToProps(state: CombinedState): StateToProps { formatsFetching: formats.fetching, userAgreementsInitialized: userAgreements.initialized, userAgreementsFetching: userAgreements.fetching, + authActionsFetching: auth.authActionsFetching, + authActionsInitialized: auth.authActionsInitialized, + allowChangePassword: auth.allowChangePassword, notifications: state.notifications, user: auth.user, keyMap: shortcuts.keyMap, @@ -106,6 +117,7 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { resetMessages: (): void => dispatch(resetMessages()), switchShortcutsDialog: (): void => dispatch(shortcutsActions.switchShortcutsDialog()), switchSettingsDialog: (): void => dispatch(switchSettingsDialog()), + loadAuthActions: (): void => dispatch(loadAuthActionsAsync()), }; } diff --git a/cvat-ui/src/reducers/auth-reducer.ts b/cvat-ui/src/reducers/auth-reducer.ts index b679d4b1..d433e7d5 100644 --- a/cvat-ui/src/reducers/auth-reducer.ts +++ b/cvat-ui/src/reducers/auth-reducer.ts @@ -10,6 +10,10 @@ const defaultState: AuthState = { initialized: false, fetching: false, user: null, + authActionsFetching: false, + authActionsInitialized: false, + allowChangePassword: false, + showChangePasswordDialog: false, }; export default function (state = defaultState, action: AuthActions | boundariesActions): AuthState { @@ -69,6 +73,49 @@ export default function (state = defaultState, action: AuthActions | boundariesA ...state, fetching: false, }; + case AuthActionTypes.CHANGE_PASSWORD: + return { + ...state, + fetching: true, + }; + case AuthActionTypes.CHANGE_PASSWORD_SUCCESS: + return { + ...state, + fetching: false, + showChangePasswordDialog: false, + + }; + case AuthActionTypes.CHANGE_PASSWORD_FAILED: + return { + ...state, + fetching: false, + }; + case AuthActionTypes.SWITCH_CHANGE_PASSWORD_DIALOG: + return { + ...state, + showChangePasswordDialog: typeof action.payload.showChangePasswordDialog === 'undefined' + ? !state.showChangePasswordDialog + : action.payload.showChangePasswordDialog, + }; + case AuthActionTypes.LOAD_AUTH_ACTIONS: + return { + ...state, + authActionsFetching: true, + }; + case AuthActionTypes.LOAD_AUTH_ACTIONS_SUCCESS: + return { + ...state, + authActionsFetching: false, + authActionsInitialized: true, + allowChangePassword: action.payload.allowChangePassword, + }; + case AuthActionTypes.LOAD_AUTH_ACTIONS_FAILED: + return { + ...state, + authActionsFetching: false, + authActionsInitialized: true, + allowChangePassword: false, + }; case BoundariesActionTypes.RESET_AFTER_ERROR: { return { ...defaultState }; } diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts index 5e7961c7..b7cf3cd4 100644 --- a/cvat-ui/src/reducers/interfaces.ts +++ b/cvat-ui/src/reducers/interfaces.ts @@ -13,6 +13,10 @@ export interface AuthState { initialized: boolean; fetching: boolean; user: any; + authActionsFetching: boolean; + authActionsInitialized: boolean; + showChangePasswordDialog: boolean; + allowChangePassword: boolean; } export interface TasksQuery { @@ -176,6 +180,8 @@ export interface NotificationsState { login: null | ErrorState; logout: null | ErrorState; register: null | ErrorState; + changePassword: null | ErrorState; + loadAuthActions: null | ErrorState; }; tasks: { fetching: null | ErrorState; @@ -246,6 +252,9 @@ export interface NotificationsState { models: { inferenceDone: string; }; + auth: { + changePasswordDone: string; + }; }; } diff --git a/cvat-ui/src/reducers/notifications-reducer.ts b/cvat-ui/src/reducers/notifications-reducer.ts index ee08de33..d9b39153 100644 --- a/cvat-ui/src/reducers/notifications-reducer.ts +++ b/cvat-ui/src/reducers/notifications-reducer.ts @@ -27,6 +27,8 @@ const defaultState: NotificationsState = { login: null, logout: null, register: null, + changePassword: null, + loadAuthActions: null, }, tasks: { fetching: null, @@ -97,6 +99,9 @@ const defaultState: NotificationsState = { models: { inferenceDone: '', }, + auth: { + changePasswordDone: '', + }, }, }; @@ -162,6 +167,48 @@ export default function (state = defaultState, action: AnyAction): Notifications }, }; } + case AuthActionTypes.CHANGE_PASSWORD_SUCCESS: { + return { + ...state, + messages: { + ...state.messages, + auth: { + ...state.messages.auth, + changePasswordDone: 'New password has been saved.', + }, + }, + }; + } + case AuthActionTypes.CHANGE_PASSWORD_FAILED: { + return { + ...state, + errors: { + ...state.errors, + auth: { + ...state.errors.auth, + changePassword: { + message: 'Could not change password', + reason: action.payload.error.toString(), + }, + }, + }, + }; + } + case AuthActionTypes.LOAD_AUTH_ACTIONS_FAILED: { + return { + ...state, + errors: { + ...state.errors, + auth: { + ...state.errors.auth, + loadAuthActions: { + message: 'Could not check available auth actions', + reason: action.payload.error.toString(), + }, + }, + }, + }; + } case TasksActionTypes.EXPORT_DATASET_FAILED: { const taskID = action.payload.task.id; return { diff --git a/cvat-ui/src/utils/plugin-checker.ts b/cvat-ui/src/utils/plugin-checker.ts index eb9f7a5d..7bb016ae 100644 --- a/cvat-ui/src/utils/plugin-checker.ts +++ b/cvat-ui/src/utils/plugin-checker.ts @@ -4,6 +4,7 @@ import getCore from 'cvat-core-wrapper'; import { SupportedPlugins } from 'reducers/interfaces'; +import isReachable from './url-checker'; const core = getCore(); @@ -11,16 +12,6 @@ const core = getCore(); class PluginChecker { public static async check(plugin: SupportedPlugins): Promise { const serverHost = core.config.backendAPI.slice(0, -7); - const isReachable = async (url: string, method: string): Promise => { - try { - await core.server.request(url, { - method, - }); - return true; - } catch (error) { - return ![0, 404].includes(error.code); - } - }; switch (plugin) { case SupportedPlugins.GIT_INTEGRATION: { diff --git a/cvat-ui/src/utils/url-checker.ts b/cvat-ui/src/utils/url-checker.ts new file mode 100644 index 00000000..3909f3fe --- /dev/null +++ b/cvat-ui/src/utils/url-checker.ts @@ -0,0 +1,18 @@ +// Copyright (C) 2020 Intel Corporation +// +// SPDX-License-Identifier: MIT + +import getCore from 'cvat-core-wrapper'; + +const core = getCore(); + +export default async (url: string, method: string): Promise => { + try { + await core.server.request(url, { + method, + }); + return true; + } catch (error) { + return ![0, 404].includes(error.code); + } +}; diff --git a/cvat/settings/base.py b/cvat/settings/base.py index a224ff04..fb0d2913 100644 --- a/cvat/settings/base.py +++ b/cvat/settings/base.py @@ -216,6 +216,7 @@ AUTHENTICATION_BACKENDS = [ # https://github.com/pennersr/django-allauth ACCOUNT_EMAIL_VERIFICATION = 'none' +OLD_PASSWORD_FIELD_ENABLED = True # Django-RQ # https://github.com/rq/django-rq From 5a8d7196e87e9c5a9ccfc6c14cf8b007808e23e5 Mon Sep 17 00:00:00 2001 From: Nikita Manovich <40690625+nmanovic@users.noreply.github.com> Date: Fri, 7 Aug 2020 18:56:50 +0300 Subject: [PATCH 31/53] Workaround a problem with deployment openvino serverless functions (#1996) * Fix a problem with permission. * Update CHANGELOG.md --- CHANGELOG.md | 2 +- serverless/openvino/dextr/nuclio/function.yaml | 2 -- .../person-reidentification-retail-300/nuclio/function.yaml | 4 ---- .../semantic-segmentation-adas-0001/nuclio/function.yaml | 2 -- .../omz/intel/text-detection-0004/nuclio/function.yaml | 4 ---- .../public/faster_rcnn_inception_v2_coco/nuclio/function.yaml | 4 ---- .../nuclio/function.yaml | 2 -- .../openvino/omz/public/yolo-v3-tf/nuclio/function.yaml | 3 --- 8 files changed, 1 insertion(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4cd6e41..6934e93f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ### Fixed -- +- Issue loading openvino models for semi-automatic and automatic annotation () ### Security - diff --git a/serverless/openvino/dextr/nuclio/function.yaml b/serverless/openvino/dextr/nuclio/function.yaml index 08fbf14f..14b6db3e 100644 --- a/serverless/openvino/dextr/nuclio/function.yaml +++ b/serverless/openvino/dextr/nuclio/function.yaml @@ -36,8 +36,6 @@ spec: value: unzip dextr_model_v1.zip - kind: RUN value: pip3 install Pillow - - kind: USER - value: openvino triggers: myHttpTrigger: diff --git a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml index 1057efb0..f4a5d2fb 100644 --- a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml @@ -33,10 +33,6 @@ spec: - kind: RUN value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/converter.py --name person-reidentification-retail-0300 --precisions FP32 -d /opt/nuclio/open_model_zoo -o /opt/nuclio/open_model_zoo - postCopy: - - kind: USER - value: openvino - triggers: myHttpTrigger: maxWorkers: 2 diff --git a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml index 0f3f4454..03a1f3c1 100644 --- a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml @@ -60,8 +60,6 @@ spec: value: apt update && DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends -y python3-skimage - kind: RUN value: pip3 install "numpy<1.16.0" # workaround for skimage - - kind: USER - value: openvino triggers: myHttpTrigger: diff --git a/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml index 864ed2d1..66317007 100644 --- a/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml @@ -34,10 +34,6 @@ spec: - kind: RUN value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/downloader.py --name text-detection-0004 -o /opt/nuclio/open_model_zoo - postCopy: - - kind: USER - value: openvino - triggers: myHttpTrigger: maxWorkers: 2 diff --git a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml index b8ea9f53..9cb8b6bf 100644 --- a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml +++ b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml @@ -115,10 +115,6 @@ spec: - kind: RUN value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/converter.py --name faster_rcnn_inception_v2_coco --precisions FP32 -d /opt/nuclio/open_model_zoo -o /opt/nuclio/open_model_zoo - postCopy: - - kind: USER - value: openvino - triggers: myHttpTrigger: maxWorkers: 2 diff --git a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml index 5b94d954..f08ef796 100644 --- a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml +++ b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml @@ -123,8 +123,6 @@ spec: value: apt update && DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends -y python3-skimage - kind: RUN value: pip3 install "numpy<1.16.0" # workaround for skimage - - kind: USER - value: openvino triggers: myHttpTrigger: diff --git a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml index 3ec733b7..31ea02b4 100644 --- a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml +++ b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml @@ -115,9 +115,6 @@ spec: - kind: RUN value: /opt/intel/openvino/deployment_tools/open_model_zoo/tools/downloader/converter.py --name yolo-v3-tf --precisions FP32 -d /opt/nuclio/open_model_zoo -o /opt/nuclio/open_model_zoo - postCopy: - - kind: USER - value: openvino triggers: myHttpTrigger: From eaeb67dc1dfa6f0242afc842aae6c5363996989a Mon Sep 17 00:00:00 2001 From: zhiltsov-max Date: Fri, 7 Aug 2020 22:18:43 +0300 Subject: [PATCH 32/53] [Datumaro] Add dataset statistics (#1668) * Add statistics command * Add tests * Update changelog * fix test * handle image absence Co-authored-by: Nikita Manovich <40690625+nmanovic@users.noreply.github.com> --- CHANGELOG.md | 1 + .../datumaro/cli/contexts/project/__init__.py | 27 ++- datumaro/datumaro/components/operations.py | 155 ++++++++++++++++++ datumaro/tests/test_ops.py | 109 +++++++++++- 4 files changed, 273 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6934e93f..48c0d0ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Siammask tracker as DL serverless function () - [Datumaro] Added model info and source info commands () +- [Datumaro] Dataset statistics () ### Changed - Shape coordinates are rounded to 2 digits in dumped annotations () diff --git a/datumaro/datumaro/cli/contexts/project/__init__.py b/datumaro/datumaro/cli/contexts/project/__init__.py index 92d5a81f..9731d48b 100644 --- a/datumaro/datumaro/cli/contexts/project/__init__.py +++ b/datumaro/datumaro/cli/contexts/project/__init__.py @@ -17,7 +17,8 @@ from datumaro.components.comparator import Comparator from datumaro.components.dataset_filter import DatasetItemEncoder from datumaro.components.extractor import AnnotationType from datumaro.components.cli_plugin import CliPlugin -from datumaro.components.operations import mean_std +from datumaro.components.operations import \ + compute_image_statistics, compute_ann_statistics from .diff import DiffVisualizer from ...util import add_subparser, CliException, MultilineFormatter, \ make_file_name @@ -648,22 +649,16 @@ def build_stats_parser(parser_ctor=argparse.ArgumentParser): def stats_command(args): project = load_project(args.project_dir) - dataset = project.make_dataset() - def print_extractor_info(extractor, indent=''): - mean, std = mean_std(dataset) - print("%sImage mean:" % indent, ', '.join('%.3f' % n for n in mean)) - print("%sImage std:" % indent, ', '.join('%.3f' % n for n in std)) - - print("Dataset: ") - print_extractor_info(dataset) - - if 1 < len(dataset.subsets()): - print("Subsets: ") - for subset_name in dataset.subsets(): - subset = dataset.get_subset(subset_name) - print(" %s:" % subset_name) - print_extractor_info(subset, " " * 4) + dataset = project.make_dataset() + stats = {} + stats.update(compute_image_statistics(dataset)) + stats.update(compute_ann_statistics(dataset)) + + dst_file = generate_next_file_name('statistics', ext='.json') + log.info("Writing project statistics to '%s'" % dst_file) + with open(dst_file, 'w') as f: + json.dump(stats, f, indent=4, sort_keys=True) def build_info_parser(parser_ctor=argparse.ArgumentParser): parser = parser_ctor(help="Get project info", diff --git a/datumaro/datumaro/components/operations.py b/datumaro/datumaro/components/operations.py index a049e267..7961775e 100644 --- a/datumaro/datumaro/components/operations.py +++ b/datumaro/datumaro/components/operations.py @@ -3,9 +3,14 @@ # # SPDX-License-Identifier: MIT +import logging as log +from copy import deepcopy + import cv2 import numpy as np +from datumaro.components.extractor import AnnotationType + def mean_std(dataset): """ @@ -14,6 +19,8 @@ def mean_std(dataset): # Use an online algorithm to: # - handle different image sizes # - avoid cancellation problem + if len(dataset) == 0: + return [0, 0, 0], [0, 0, 0] stats = np.empty((len(dataset), 2, 3), dtype=np.double) counts = np.empty(len(dataset), dtype=np.uint32) @@ -80,3 +87,151 @@ class StatsCounter: *__class__.compute_stats(stats[:h], counts[:h], m, v), *__class__.compute_stats(stats[h:], counts[h:], m, v) ) + +def compute_image_statistics(dataset): + stats = { + 'dataset': {}, + 'subsets': {} + } + + def _extractor_stats(extractor): + available = True + for item in extractor: + if not (item.has_image and item.image.has_data): + available = False + log.warn("Item %s has no image. Image stats won't be computed", + item.id) + break + + stats = { + 'images count': len(extractor), + } + + if available: + mean, std = mean_std(extractor) + stats.update({ + 'image mean': [float(n) for n in mean[::-1]], + 'image std': [float(n) for n in std[::-1]], + }) + else: + stats.update({ + 'image mean': 'n/a', + 'image std': 'n/a', + }) + return stats + + stats['dataset'].update(_extractor_stats(dataset)) + + subsets = dataset.subsets() or [None] + if subsets and 0 < len([s for s in subsets if s]): + for subset_name in subsets: + stats['subsets'][subset_name] = _extractor_stats( + dataset.get_subset(subset_name)) + + return stats + +def compute_ann_statistics(dataset): + labels = dataset.categories().get(AnnotationType.label) + def get_label(ann): + return labels.items[ann.label].name if ann.label is not None else None + + stats = { + 'images count': len(dataset), + 'annotations count': 0, + 'unannotated images count': 0, + 'unannotated images': [], + 'annotations by type': { t.name: { + 'count': 0, + } for t in AnnotationType }, + 'annotations': {}, + } + by_type = stats['annotations by type'] + + attr_template = { + 'count': 0, + 'values count': 0, + 'values present': set(), + 'distribution': {}, # value -> (count, total%) + } + label_stat = { + 'count': 0, + 'distribution': { l.name: [0, 0] for l in labels.items + }, # label -> (count, total%) + + 'attributes': {}, + } + stats['annotations']['labels'] = label_stat + segm_stat = { + 'avg. area': 0, + 'area distribution': [], # a histogram with 10 bins + # (min, min+10%), ..., (min+90%, max) -> (count, total%) + + 'pixel distribution': { l.name: [0, 0] for l in labels.items + }, # label -> (count, total%) + } + stats['annotations']['segments'] = segm_stat + segm_areas = [] + pixel_dist = segm_stat['pixel distribution'] + total_pixels = 0 + + for item in dataset: + if len(item.annotations) == 0: + stats['unannotated images'].append(item.id) + continue + + for ann in item.annotations: + by_type[ann.type.name]['count'] += 1 + + if not hasattr(ann, 'label') or ann.label is None: + continue + + if ann.type in {AnnotationType.mask, + AnnotationType.polygon, AnnotationType.bbox}: + area = ann.get_area() + segm_areas.append(area) + pixel_dist[get_label(ann)][0] += int(area) + + label_stat['count'] += 1 + label_stat['distribution'][get_label(ann)][0] += 1 + + for name, value in ann.attributes.items(): + if name.lower() in { 'occluded', 'visibility', 'score', + 'id', 'track_id' }: + continue + attrs_stat = label_stat['attributes'].setdefault(name, + deepcopy(attr_template)) + attrs_stat['count'] += 1 + attrs_stat['values present'].add(str(value)) + attrs_stat['distribution'] \ + .setdefault(str(value), [0, 0])[0] += 1 + + stats['annotations count'] = sum(t['count'] for t in + stats['annotations by type'].values()) + stats['unannotated images count'] = len(stats['unannotated images']) + + for label_info in label_stat['distribution'].values(): + label_info[1] = label_info[0] / label_stat['count'] + + for label_attr in label_stat['attributes'].values(): + label_attr['values count'] = len(label_attr['values present']) + label_attr['values present'] = sorted(label_attr['values present']) + for attr_info in label_attr['distribution'].values(): + attr_info[1] = attr_info[0] / label_attr['count'] + + # numpy.sum might be faster, but could overflow with large datasets. + # Python's int can transparently mutate to be of indefinite precision (long) + total_pixels = sum(int(a) for a in segm_areas) + + segm_stat['avg. area'] = total_pixels / (len(segm_areas) or 1.0) + + for label_info in segm_stat['pixel distribution'].values(): + label_info[1] = label_info[0] / total_pixels + + if len(segm_areas) != 0: + hist, bins = np.histogram(segm_areas) + segm_stat['area distribution'] = [{ + 'min': float(bin_min), 'max': float(bin_max), + 'count': int(c), 'percent': int(c) / len(segm_areas) + } for c, (bin_min, bin_max) in zip(hist, zip(bins[:-1], bins[1:]))] + + return stats diff --git a/datumaro/tests/test_ops.py b/datumaro/tests/test_ops.py index 24f32f35..ed165b2d 100644 --- a/datumaro/tests/test_ops.py +++ b/datumaro/tests/test_ops.py @@ -1,7 +1,9 @@ import numpy as np -from datumaro.components.extractor import Extractor, DatasetItem -from datumaro.components.operations import mean_std +from datumaro.components.extractor import (Extractor, DatasetItem, Label, + Mask, Bbox, Points, Caption) +from datumaro.components.project import Dataset +from datumaro.components.operations import mean_std, compute_ann_statistics from unittest import TestCase @@ -28,4 +30,105 @@ class TestOperations(TestCase): for em, am in zip(expected_mean, actual_mean): self.assertAlmostEqual(em, am, places=0) for estd, astd in zip(expected_std, actual_std): - self.assertAlmostEqual(estd, astd, places=0) \ No newline at end of file + self.assertAlmostEqual(estd, astd, places=0) + + def test_stats(self): + dataset = Dataset.from_iterable([ + DatasetItem(id=1, image=np.ones((5, 5, 3)), annotations=[ + Caption('hello'), + Caption('world'), + Label(2, attributes={ 'x': 1, 'y': '2', }), + Bbox(1, 2, 2, 2, label=2, attributes={ 'score': 0.5, }), + Bbox(5, 6, 2, 2, attributes={ + 'x': 1, 'y': '3', 'occluded': True, + }), + Points([1, 2, 2, 0, 1, 1], label=0), + Mask(label=3, image=np.array([ + [0, 0, 1, 1, 1], + [0, 0, 1, 1, 1], + [0, 0, 1, 1, 1], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + ])), + ]), + DatasetItem(id=2, image=np.ones((2, 4, 3)), annotations=[ + Label(2, attributes={ 'x': 2, 'y': '2', }), + Bbox(1, 2, 2, 2, label=3, attributes={ 'score': 0.5, }), + Bbox(5, 6, 2, 2, attributes={ + 'x': 2, 'y': '3', 'occluded': False, + }), + ]), + DatasetItem(id=3), + ], categories=['label_%s' % i for i in range(4)]) + + expected = { + 'images count': 3, + 'annotations count': 10, + 'unannotated images count': 1, + 'unannotated images': ['3'], + 'annotations by type': { + 'label': { 'count': 2, }, + 'polygon': { 'count': 0, }, + 'polyline': { 'count': 0, }, + 'bbox': { 'count': 4, }, + 'mask': { 'count': 1, }, + 'points': { 'count': 1, }, + 'caption': { 'count': 2, }, + }, + 'annotations': { + 'labels': { + 'count': 6, + 'distribution': { + 'label_0': [1, 1/6], + 'label_1': [0, 0.0], + 'label_2': [3, 3/6], + 'label_3': [2, 2/6], + }, + 'attributes': { + 'x': { + 'count': 2, # unnotations with no label are skipped + 'values count': 2, + 'values present': ['1', '2'], + 'distribution': { + '1': [1, 1/2], + '2': [1, 1/2], + }, + }, + 'y': { + 'count': 2, # unnotations with no label are skipped + 'values count': 1, + 'values present': ['2'], + 'distribution': { + '2': [2, 2/2], + }, + }, + # must not include "special" attributes like "occluded" + } + }, + 'segments': { + 'avg. area': (4 * 2 + 9 * 1) / 3, + 'area distribution': [ + {'min': 4.0, 'max': 4.5, 'count': 2, 'percent': 2/3}, + {'min': 4.5, 'max': 5.0, 'count': 0, 'percent': 0.0}, + {'min': 5.0, 'max': 5.5, 'count': 0, 'percent': 0.0}, + {'min': 5.5, 'max': 6.0, 'count': 0, 'percent': 0.0}, + {'min': 6.0, 'max': 6.5, 'count': 0, 'percent': 0.0}, + {'min': 6.5, 'max': 7.0, 'count': 0, 'percent': 0.0}, + {'min': 7.0, 'max': 7.5, 'count': 0, 'percent': 0.0}, + {'min': 7.5, 'max': 8.0, 'count': 0, 'percent': 0.0}, + {'min': 8.0, 'max': 8.5, 'count': 0, 'percent': 0.0}, + {'min': 8.5, 'max': 9.0, 'count': 1, 'percent': 1/3}, + ], + 'pixel distribution': { + 'label_0': [0, 0.0], + 'label_1': [0, 0.0], + 'label_2': [4, 4/17], + 'label_3': [13, 13/17], + }, + } + }, + } + + actual = compute_ann_statistics(dataset) + + self.assertEqual(expected, actual) \ No newline at end of file From 000e9c4dad8f3ddf8c822807b12ec9a93c37337d Mon Sep 17 00:00:00 2001 From: zhiltsov-max Date: Fri, 7 Aug 2020 22:29:47 +0300 Subject: [PATCH 33/53] [Datumaro] Use attrs for model declaration (#2000) * bandit fixes * t * refactor extractor to use attrs * Merge branch 'develop' into zm/extractor-with-attrs * update requirements * restore changelog * fix bindings --- cvat/apps/dataset_manager/bindings.py | 4 +- .../datumaro/components/dataset_filter.py | 2 +- datumaro/datumaro/components/extractor.py | 439 +++++------------- .../datumaro/plugins/cvat_format/extractor.py | 4 +- datumaro/datumaro/plugins/labelme_format.py | 2 +- datumaro/datumaro/plugins/transforms.py | 9 +- datumaro/datumaro/util/attrs_util.py | 26 ++ datumaro/datumaro/util/test_utils.py | 20 +- datumaro/requirements.txt | 1 + datumaro/setup.py | 1 + datumaro/tests/test_datumaro_format.py | 2 +- datumaro/tests/test_project.py | 13 +- datumaro/tests/test_transforms.py | 104 ++--- 13 files changed, 200 insertions(+), 427 deletions(-) create mode 100644 datumaro/datumaro/util/attrs_util.py diff --git a/cvat/apps/dataset_manager/bindings.py b/cvat/apps/dataset_manager/bindings.py index 7e20fc33..64921555 100644 --- a/cvat/apps/dataset_manager/bindings.py +++ b/cvat/apps/dataset_manager/bindings.py @@ -531,7 +531,7 @@ class CvatTaskDataExtractor(datumaro.SourceExtractor): return dm_attr for tag_obj in cvat_frame_anno.tags: - anno_group = tag_obj.group + anno_group = tag_obj.group or 0 anno_label = map_label(tag_obj.label) anno_attr = convert_attrs(tag_obj.label, tag_obj.attributes) @@ -540,7 +540,7 @@ class CvatTaskDataExtractor(datumaro.SourceExtractor): item_anno.append(anno) for shape_obj in cvat_frame_anno.labeled_shapes: - anno_group = shape_obj.group + anno_group = shape_obj.group or 0 anno_label = map_label(shape_obj.label) anno_attr = convert_attrs(shape_obj.label, shape_obj.attributes) anno_attr['occluded'] = shape_obj.occluded diff --git a/datumaro/datumaro/components/dataset_filter.py b/datumaro/datumaro/components/dataset_filter.py index 351cc6c8..e9fc5e35 100644 --- a/datumaro/datumaro/components/dataset_filter.py +++ b/datumaro/datumaro/components/dataset_filter.py @@ -4,7 +4,7 @@ # SPDX-License-Identifier: MIT import logging as log -from lxml import etree as ET # NOTE: lxml has proper XPath implementation +from lxml import etree as ET # lxml has proper XPath implementation from datumaro.components.extractor import (Transform, Annotation, AnnotationType, Label, Mask, Points, Polygon, PolyLine, Bbox, Caption, diff --git a/datumaro/datumaro/components/extractor.py b/datumaro/datumaro/components/extractor.py index 1df3c287..609c6e9e 100644 --- a/datumaro/datumaro/components/extractor.py +++ b/datumaro/datumaro/components/extractor.py @@ -7,7 +7,11 @@ from collections import namedtuple from enum import Enum import numpy as np +import attr +from attr import attrs, attrib + from datumaro.util.image import Image +from datumaro.util.attrs_util import not_empty, default_if_none AnnotationType = Enum('AnnotationType', [ @@ -22,59 +26,34 @@ AnnotationType = Enum('AnnotationType', _COORDINATE_ROUNDING_DIGITS = 2 - +@attrs class Annotation: - # pylint: disable=redefined-builtin - def __init__(self, id=None, type=None, attributes=None, group=None): - if id is not None: - id = int(id) - self.id = id + id = attrib(converter=int, default=0, kw_only=True) + attributes = attrib(converter=dict, factory=dict, kw_only=True) + group = attrib(converter=int, default=0, kw_only=True) - assert type in AnnotationType - self.type = type - - if attributes is None: - attributes = {} - else: - attributes = dict(attributes) - self.attributes = attributes + def __attrs_post_init__(self): + assert isinstance(self.type, AnnotationType) - if group is None: - group = 0 - else: - group = int(group) - self.group = group - # pylint: enable=redefined-builtin + @property + def type(self): + return self._type # must be set in subclasses - def __eq__(self, other): - if not isinstance(other, Annotation): - return False - return \ - (self.id == other.id) and \ - (self.type == other.type) and \ - (self.attributes == other.attributes) and \ - (self.group == other.group) + def wrap(item, **kwargs): + return attr.evolve(item, **kwargs) +@attrs class Categories: - def __init__(self, attributes=None): - if attributes is None: - attributes = set() - else: - if not isinstance(attributes, set): - attributes = set(attributes) - for attr in attributes: - assert isinstance(attr, str) - self.attributes = attributes - - def __eq__(self, other): - if not isinstance(other, Categories): - return False - return \ - (self.attributes == other.attributes) + attributes = attrib(factory=set, validator=default_if_none(set), + kw_only=True) +@attrs class LabelCategories(Categories): Category = namedtuple('Category', ['name', 'parent', 'attributes']) + items = attrib(factory=list, validator=default_if_none(list)) + _indices = attrib(factory=dict, init=False, eq=False) + @classmethod def from_iterable(cls, iterable): """Generation of LabelCategories from iterable object @@ -102,14 +81,7 @@ class LabelCategories(Categories): return temp_categories - def __init__(self, items=None, attributes=None): - super().__init__(attributes=attributes) - - if items is None: - items = [] - self.items = items - - self._indices = {} + def __attrs_post_init__(self): self._reindex() def _reindex(self): @@ -142,49 +114,23 @@ class LabelCategories(Categories): return index, self.items[index] return index, None - def __eq__(self, other): - if not super().__eq__(other): - return False - return \ - (self.items == other.items) - +@attrs class Label(Annotation): - # pylint: disable=redefined-builtin - def __init__(self, label=None, - id=None, attributes=None, group=None): - super().__init__(id=id, type=AnnotationType.label, - attributes=attributes, group=group) - - if label is not None: - label = int(label) - self.label = label - # pylint: enable=redefined-builtin - - def __eq__(self, other): - if not super().__eq__(other): - return False - return \ - (self.label == other.label) + _type = AnnotationType.label + label = attrib(converter=int) +@attrs(eq=False) class MaskCategories(Categories): - def __init__(self, colormap=None, inverse_colormap=None, attributes=None): - super().__init__(attributes=attributes) - - # colormap: label id -> color - if colormap is None: - colormap = {} - self.colormap = colormap - self._inverse_colormap = inverse_colormap + colormap = attrib(factory=dict, validator=default_if_none(dict)) + _inverse_colormap = attrib(default=None, + validator=attr.validators.optional(dict)) @property def inverse_colormap(self): from datumaro.util.mask_tools import invert_colormap if self._inverse_colormap is None: if self.colormap is not None: - try: - self._inverse_colormap = invert_colormap(self.colormap) - except Exception: - pass + self._inverse_colormap = invert_colormap(self.colormap) return self._inverse_colormap def __eq__(self, other): @@ -196,25 +142,13 @@ class MaskCategories(Categories): return False return True +@attrs(eq=False) class Mask(Annotation): - # pylint: disable=redefined-builtin - def __init__(self, image=None, label=None, z_order=None, - id=None, attributes=None, group=None): - super().__init__(type=AnnotationType.mask, - id=id, attributes=attributes, group=group) - - self._image = image - - if label is not None: - label = int(label) - self._label = label - - if z_order is None: - z_order = 0 - else: - z_order = int(z_order) - self._z_order = z_order - # pylint: enable=redefined-builtin + _type = AnnotationType.mask + _image = attrib() + label = attrib(converter=attr.converters.optional(int), + default=None, kw_only=True) + z_order = attrib(converter=int, default=0, kw_only=True) @property def image(self): @@ -222,14 +156,6 @@ class Mask(Annotation): return self._image() return self._image - @property - def label(self): - return self._label - - @property - def z_order(self): - return self._z_order - def as_class_mask(self, label_id=None): if label_id is None: label_id = self.label @@ -255,19 +181,14 @@ class Mask(Annotation): return \ (self.label == other.label) and \ (self.z_order == other.z_order) and \ - (self.image is not None and other.image is not None and \ - np.array_equal(self.image, other.image)) + (np.array_equal(self.image, other.image)) +@attrs(eq=False) class RleMask(Mask): - # pylint: disable=redefined-builtin - def __init__(self, rle=None, label=None, z_order=None, - id=None, attributes=None, group=None): - lazy_decode = self._lazy_decode(rle) - super().__init__(image=lazy_decode, label=label, z_order=z_order, - id=id, attributes=attributes, group=group) - - self._rle = rle - # pylint: enable=redefined-builtin + rle = attrib() + _image = attrib(default=attr.Factory( + lambda self: self._lazy_decode(self.rle), + takes_self=True), init=False) @staticmethod def _lazy_decode(rle): @@ -276,20 +197,16 @@ class RleMask(Mask): def get_area(self): from pycocotools import mask as mask_utils - return mask_utils.area(self._rle) + return mask_utils.area(self.rle) def get_bbox(self): from pycocotools import mask as mask_utils - return mask_utils.toBbox(self._rle) - - @property - def rle(self): - return self._rle + return mask_utils.toBbox(self.rle) def __eq__(self, other): if not isinstance(other, __class__): return super().__eq__(other) - return self._rle == other._rle + return self.rle == other.rle class CompiledMask: @staticmethod @@ -375,38 +292,13 @@ def compute_iou(bbox_a, bbox_b): return intersection / max(1.0, union) +@attrs class _Shape(Annotation): - # pylint: disable=redefined-builtin - def __init__(self, type, points=None, label=None, z_order=None, - id=None, attributes=None, group=None): - super().__init__(id=id, type=type, - attributes=attributes, group=group) - if points is not None: - points = [round(p, _COORDINATE_ROUNDING_DIGITS) for p in points] - self._points = points - - if label is not None: - label = int(label) - self._label = label - - if z_order is None: - z_order = 0 - else: - z_order = int(z_order) - self._z_order = z_order - # pylint: enable=redefined-builtin - - @property - def points(self): - return self._points - - @property - def label(self): - return self._label - - @property - def z_order(self): - return self._z_order + points = attrib(converter=lambda x: + [round(p, _COORDINATE_ROUNDING_DIGITS) for p in x]) + label = attrib(converter=attr.converters.optional(int), + default=None, kw_only=True) + z_order = attrib(converter=int, default=0, kw_only=True) def get_area(self): raise NotImplementedError() @@ -424,22 +316,9 @@ class _Shape(Annotation): y1 = max(ys) return [x0, y0, x1 - x0, y1 - y0] - def __eq__(self, other): - if not super().__eq__(other): - return False - return \ - (np.array_equal(self.points, other.points)) and \ - (self.z_order == other.z_order) and \ - (self.label == other.label) - +@attrs class PolyLine(_Shape): - # pylint: disable=redefined-builtin - def __init__(self, points=None, label=None, z_order=None, - id=None, attributes=None, group=None): - super().__init__(type=AnnotationType.polyline, - points=points, label=label, z_order=z_order, - id=id, attributes=attributes, group=group) - # pylint: enable=redefined-builtin + _type = AnnotationType.polyline def as_polygon(self): return self.points[:] @@ -447,18 +326,14 @@ class PolyLine(_Shape): def get_area(self): return 0 +@attrs class Polygon(_Shape): - # pylint: disable=redefined-builtin - def __init__(self, points=None, label=None, - z_order=None, id=None, attributes=None, group=None): - if points is not None: - # keep the message on the single line to produce - # informative output - assert len(points) % 2 == 0 and 3 <= len(points) // 2, "Wrong polygon points: %s" % points - super().__init__(type=AnnotationType.polygon, - points=points, label=label, z_order=z_order, - id=id, attributes=attributes, group=group) - # pylint: enable=redefined-builtin + _type = AnnotationType.polygon + + def __attrs_post_init__(self): + super().__attrs_post_init__() + # keep the message on a single line to produce informative output + assert len(self.points) % 2 == 0 and 3 <= len(self.points) // 2, "Wrong polygon points: %s" % self.points def get_area(self): import pycocotools.mask as mask_utils @@ -468,14 +343,16 @@ class Polygon(_Shape): area = mask_utils.area(rle)[0] return area +@attrs class Bbox(_Shape): - # pylint: disable=redefined-builtin - def __init__(self, x=0, y=0, w=0, h=0, label=None, z_order=None, - id=None, attributes=None, group=None): - super().__init__(type=AnnotationType.bbox, - points=[x, y, x + w, y + h], label=label, z_order=z_order, - id=id, attributes=attributes, group=group) - # pylint: enable=redefined-builtin + _type = AnnotationType.bbox + + # will be overridden by attrs, then will be overridden again by us + # attrs' method will be renamed to __attrs_init__ + def __init__(self, x, y, w, h, *args, **kwargs): + kwargs.pop('points', None) # comes from wrap() + self.__attrs_init__([x, y, x + w, y + h], *args, **kwargs) + __actual_init__ = __init__ # save pointer @property def x(self): @@ -511,9 +388,21 @@ class Bbox(_Shape): def iou(self, other): return compute_iou(self.get_bbox(), other.get_bbox()) + def wrap(item, **kwargs): + d = {'x': item.x, 'y': item.y, 'w': item.w, 'h': item.h} + d.update(kwargs) + return attr.evolve(item, **d) + +assert not hasattr(Bbox, '__attrs_init__') # hopefully, it will be supported +setattr(Bbox, '__attrs_init__', Bbox.__init__) +setattr(Bbox, '__init__', Bbox.__actual_init__) + +@attrs class PointsCategories(Categories): Category = namedtuple('Category', ['labels', 'joints']) + items = attrib(factory=dict, validator=default_if_none(dict)) + @classmethod def from_iterable(cls, iterable): """Generation of PointsCategories from iterable object @@ -539,13 +428,6 @@ class PointsCategories(Categories): temp_categories.add(*category) return temp_categories - def __init__(self, items=None, attributes=None): - super().__init__(attributes=attributes) - - if items is None: - items = {} - self.items = items - def add(self, label_id, labels=None, joints=None): if labels is None: labels = [] @@ -554,41 +436,30 @@ class PointsCategories(Categories): joints = set(map(tuple, joints)) self.items[label_id] = self.Category(labels, joints) - def __eq__(self, other): - if not super().__eq__(other): - return False - return \ - (self.items == other.items) - +@attrs class Points(_Shape): Visibility = Enum('Visibility', [ ('absent', 0), ('hidden', 1), ('visible', 2), ]) + _type = AnnotationType.points - # pylint: disable=redefined-builtin - def __init__(self, points=None, visibility=None, label=None, z_order=None, - id=None, attributes=None, group=None): - if points is not None: - assert len(points) % 2 == 0 - - if visibility is not None: - assert len(visibility) == len(points) // 2 - for i, v in enumerate(visibility): - if not isinstance(v, self.Visibility): - visibility[i] = self.Visibility(v) - else: - visibility = [] - for _ in range(len(points) // 2): - visibility.append(self.Visibility.visible) - - super().__init__(type=AnnotationType.points, - points=points, label=label, z_order=z_order, - id=id, attributes=attributes, group=group) - + visibility = attrib(type=list, default=None) + @visibility.validator + def _visibility_validator(self, attribute, visibility): + if visibility is None: + visibility = [self.Visibility.visible] * (len(self.points) // 2) + else: + for i, v in enumerate(visibility): + if not isinstance(v, self.Visibility): + visibility[i] = self.Visibility(v) + assert len(visibility) == len(self.points) // 2 self.visibility = visibility - # pylint: enable=redefined-builtin + + def __attrs_post_init__(self): + super().__attrs_post_init__() + assert len(self.points) % 2 == 0, self.points def get_area(self): return 0 @@ -604,117 +475,37 @@ class Points(_Shape): y1 = max(ys, default=0) return [x0, y0, x1 - x0, y1 - y0] - def __eq__(self, other): - if not super().__eq__(other): - return False - return \ - (self.visibility == other.visibility) - +@attrs class Caption(Annotation): - # pylint: disable=redefined-builtin - def __init__(self, caption=None, - id=None, attributes=None, group=None): - super().__init__(id=id, type=AnnotationType.caption, - attributes=attributes, group=group) - - if caption is None: - caption = '' - else: - caption = str(caption) - self.caption = caption - # pylint: enable=redefined-builtin - - def __eq__(self, other): - if not super().__eq__(other): - return False - return \ - (self.caption == other.caption) + _type = AnnotationType.caption + caption = attrib(converter=str) +@attrs class DatasetItem: - # pylint: disable=redefined-builtin - def __init__(self, id=None, annotations=None, - subset=None, path=None, image=None, attributes=None): - assert id is not None - self._id = str(id).replace('\\', '/') - - if subset is None: - subset = '' - else: - subset = str(subset) - self._subset = subset - - if path is None: - path = [] - else: - path = list(path) - self._path = path - - if annotations is None: - annotations = [] - else: - annotations = list(annotations) - self._annotations = annotations - + id = attrib(converter=lambda x: str(x).replace('\\', '/'), + type=str, validator=not_empty) + annotations = attrib(factory=list, validator=default_if_none(list)) + subset = attrib(default='', validator=default_if_none(str)) + path = attrib(factory=list, validator=default_if_none(list)) + + image = attrib(type=Image, default=None) + @image.validator + def _image_validator(self, attribute, image): if callable(image) or isinstance(image, np.ndarray): image = Image(data=image) elif isinstance(image, str): image = Image(path=image) assert image is None or isinstance(image, Image) - self._image = image + self.image = image - if attributes is None: - attributes = {} - else: - attributes = dict(attributes) - self._attributes = attributes - # pylint: enable=redefined-builtin - - @property - def id(self): - return self._id - - @property - def subset(self): - return self._subset - - @property - def path(self): - return self._path - - @property - def annotations(self): - return self._annotations - - @property - def image(self): - return self._image + attributes = attrib(factory=dict, validator=default_if_none(dict)) @property def has_image(self): - return self._image is not None - - @property - def attributes(self): - return self._attributes - - def __eq__(self, other): - if not isinstance(other, __class__): - return False - return \ - (self.id == other.id) and \ - (self.subset == other.subset) and \ - (self.path == other.path) and \ - (self.annotations == other.annotations) and \ - (self.image == other.image) and \ - (self.attributes == other.attributes) + return self.image is not None def wrap(item, **kwargs): - expected_args = {'id', 'annotations', 'subset', - 'path', 'image', 'attributes'} - for k in expected_args: - if k not in kwargs: - kwargs[k] = getattr(item, k) - return DatasetItem(**kwargs) + return attr.evolve(item, **kwargs) class IExtractor: def __iter__(self): diff --git a/datumaro/datumaro/plugins/cvat_format/extractor.py b/datumaro/datumaro/plugins/cvat_format/extractor.py index 2c63bd2e..75a3e5d8 100644 --- a/datumaro/datumaro/plugins/cvat_format/extractor.py +++ b/datumaro/datumaro/plugins/cvat_format/extractor.py @@ -102,7 +102,7 @@ class CvatExtractor(SourceExtractor): else: try: attr_value = float(attr_value) - except Exception: + except ValueError: pass attributes[el.attrib['name']] = attr_value elif el.tag in cls._SUPPORTED_SHAPES: @@ -251,7 +251,7 @@ class CvatExtractor(SourceExtractor): @classmethod def _parse_shape_ann(cls, ann, categories): - ann_id = ann.get('id') + ann_id = ann.get('id', 0) ann_type = ann['type'] attributes = ann.get('attributes') or {} diff --git a/datumaro/datumaro/plugins/labelme_format.py b/datumaro/datumaro/plugins/labelme_format.py index d8c71716..5218e36f 100644 --- a/datumaro/datumaro/plugins/labelme_format.py +++ b/datumaro/datumaro/plugins/labelme_format.py @@ -83,7 +83,7 @@ class LabelMeExtractor(SourceExtractor): else: try: value = float(value) - except Exception: + except ValueError: pass parsed.append((name, value)) else: diff --git a/datumaro/datumaro/plugins/transforms.py b/datumaro/datumaro/plugins/transforms.py index 79f0d3ae..b31b4762 100644 --- a/datumaro/datumaro/plugins/transforms.py +++ b/datumaro/datumaro/plugins/transforms.py @@ -504,7 +504,6 @@ class RemapLabels(Transform, CliPlugin): return self._categories def transform_item(self, item): - # TODO: provide non-inplace version annotations = [] for ann in item.annotations: if ann.type in { AnnotationType.label, AnnotationType.mask, @@ -513,9 +512,7 @@ class RemapLabels(Transform, CliPlugin): } and ann.label is not None: conv_label = self._map_id(ann.label) if conv_label is not None: - ann._label = conv_label - annotations.append(ann) + annotations.append(ann.wrap(label=conv_label)) else: - annotations.append(ann) - item._annotations = annotations - return item \ No newline at end of file + annotations.append(ann.wrap()) + return item.wrap(annotations=annotations) \ No newline at end of file diff --git a/datumaro/datumaro/util/attrs_util.py b/datumaro/datumaro/util/attrs_util.py new file mode 100644 index 00000000..af92c549 --- /dev/null +++ b/datumaro/datumaro/util/attrs_util.py @@ -0,0 +1,26 @@ + +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +import attr + +_NOTSET = object() + +def not_empty(inst, attribute, x): + assert len(x) != 0, x + +def default_if_none(conv): + def validator(inst, attribute, value): + default = attribute.default + if value is None: + if callable(default): + value = default() + elif isinstance(default, attr.Factory): + value = default.factory() + else: + value = default + elif not isinstance(value, attribute.type or conv): + value = conv(value) + setattr(inst, attribute.name, value) + return validator \ No newline at end of file diff --git a/datumaro/datumaro/util/test_utils.py b/datumaro/datumaro/util/test_utils.py index f9ce0369..cca95278 100644 --- a/datumaro/datumaro/util/test_utils.py +++ b/datumaro/datumaro/util/test_utils.py @@ -43,19 +43,6 @@ class TestDir(FileRemover): super().__init__(path, is_dir=True, ignore_errors=ignore_errors) -def ann_to_str(ann): - return vars(ann) - -def item_to_str(item): - return '\n'.join( - [ - '%s' % vars(item) - ] + [ - 'ann[%s]: %s' % (i, ann_to_str(a)) - for i, a in enumerate(item.annotations) - ] - ) - def compare_categories(test, expected, actual): test.assertEqual( sorted(expected, key=lambda t: t.value), @@ -92,12 +79,11 @@ def compare_datasets(test, expected, actual): for ann_a in item_a.annotations: # We might find few corresponding items, so check them all ann_b_matches = [x for x in item_b.annotations - if x.id == ann_a.id and \ - x.type == ann_a.type and x.group == ann_a.group] + if x.type == ann_a.type] test.assertFalse(len(ann_b_matches) == 0, 'ann id: %s' % ann_a.id) ann_b = find(ann_b_matches, lambda x: x == ann_a) - test.assertEqual(ann_a, ann_b, 'ann: %s' % ann_to_str(ann_a)) + test.assertEqual(ann_a, ann_b, 'ann %s, candidates %s' % (ann_a, ann_b_matches)) item_b.annotations.remove(ann_b) # avoid repeats def compare_datasets_strict(test, expected, actual): @@ -115,4 +101,4 @@ def compare_datasets_strict(test, expected, actual): for idx, (item_a, item_b) in enumerate(zip(e_subset, a_subset)): test.assertEqual(item_a, item_b, '%s:\n%s\nvs.\n%s\n' % \ - (idx, item_to_str(item_a), item_to_str(item_b))) \ No newline at end of file + (idx, item_a, item_b)) \ No newline at end of file diff --git a/datumaro/requirements.txt b/datumaro/requirements.txt index c75978fc..ce583783 100644 --- a/datumaro/requirements.txt +++ b/datumaro/requirements.txt @@ -1,3 +1,4 @@ +attrs>=19.3.0 Cython>=0.27.3 # include before pycocotools defusedxml>=0.6.0 GitPython>=3.0.8 diff --git a/datumaro/setup.py b/datumaro/setup.py index 90c39ce4..4ebf1119 100644 --- a/datumaro/setup.py +++ b/datumaro/setup.py @@ -48,6 +48,7 @@ setuptools.setup( ], python_requires='>=3.5', install_requires=[ + 'attrs', 'defusedxml', 'GitPython', 'lxml', diff --git a/datumaro/tests/test_datumaro_format.py b/datumaro/tests/test_datumaro_format.py index 421627a8..8faf5ef0 100644 --- a/datumaro/tests/test_datumaro_format.py +++ b/datumaro/tests/test_datumaro_format.py @@ -65,7 +65,7 @@ class DatumaroConverterTest(TestCase): annotations=[ Caption('test'), Label(2), - Bbox(1, 2, 3, 4, 5, id=42, group=42) + Bbox(1, 2, 3, 4, label=5, id=42, group=42) ]), DatasetItem(id=2, subset='val', diff --git a/datumaro/tests/test_project.py b/datumaro/tests/test_project.py index 023341c6..ed4ad976 100644 --- a/datumaro/tests/test_project.py +++ b/datumaro/tests/test_project.py @@ -133,15 +133,15 @@ class ProjectTest(TestCase): self.assertTrue('project1' in dataset.sources) def test_can_batch_launch_custom_model(self): - class TestExtractor(Extractor): - def __iter__(self): - for i in range(5): - yield DatasetItem(id=i, subset='train', image=np.array([i])) + dataset = Dataset.from_iterable([ + DatasetItem(id=i, subset='train', image=np.array([i])) + for i in range(5) + ], categories=['label']) class TestLauncher(Launcher): def launch(self, inputs): for i, inp in enumerate(inputs): - yield [ Label(attributes={'idx': i, 'data': inp.item()}) ] + yield [ Label(0, attributes={'idx': i, 'data': inp.item()}) ] model_name = 'model' launcher_name = 'custom_launcher' @@ -150,10 +150,9 @@ class ProjectTest(TestCase): project.env.launchers.register(launcher_name, TestLauncher) project.add_model(model_name, { 'launcher': launcher_name }) model = project.make_executable_model(model_name) - extractor = TestExtractor() batch_size = 3 - executor = ModelTransform(extractor, model, batch_size=batch_size) + executor = ModelTransform(dataset, model, batch_size=batch_size) for item in executor: self.assertEqual(1, len(item.annotations)) diff --git a/datumaro/tests/test_transforms.py b/datumaro/tests/test_transforms.py index a55a446e..ed072a67 100644 --- a/datumaro/tests/test_transforms.py +++ b/datumaro/tests/test_transforms.py @@ -356,86 +356,58 @@ class TransformsTest(TestCase): ]) def test_remap_labels(self): - class SrcExtractor(Extractor): - def __iter__(self): - return iter([ - DatasetItem(id=1, annotations=[ - # Should be remapped - Label(1), - Bbox(1, 2, 3, 4, label=2), - Mask(image=np.array([1]), label=3), - - # Should be kept - Polygon([1, 1, 2, 2, 3, 4], label=4), - PolyLine([1, 3, 4, 2, 5, 6], label=None) - ]), - ]) - - def categories(self): - label_cat = LabelCategories() - label_cat.add('label0') - label_cat.add('label1') - label_cat.add('label2') - label_cat.add('label3') - label_cat.add('label4') - - mask_cat = MaskCategories( - colormap=mask_tools.generate_colormap(5)) - - return { - AnnotationType.label: label_cat, - AnnotationType.mask: mask_cat, - } - - class DstExtractor(Extractor): - def __iter__(self): - return iter([ - DatasetItem(id=1, annotations=[ - Label(1), - Bbox(1, 2, 3, 4, label=0), - Mask(image=np.array([1]), label=1), - - Polygon([1, 1, 2, 2, 3, 4], label=2), - PolyLine([1, 3, 4, 2, 5, 6], label=None) - ]), - ]) - - def categories(self): - label_cat = LabelCategories() - label_cat.add('label0') - label_cat.add('label9') - label_cat.add('label4') + src_dataset = Dataset.from_iterable([ + DatasetItem(id=1, annotations=[ + # Should be remapped + Label(1), + Bbox(1, 2, 3, 4, label=2), + Mask(image=np.array([1]), label=3), + + # Should be kept + Polygon([1, 1, 2, 2, 3, 4], label=4), + PolyLine([1, 3, 4, 2, 5, 6]) + ]) + ], categories={ + AnnotationType.label: LabelCategories.from_iterable( + 'label%s' % i for i in range(5)), + AnnotationType.mask: MaskCategories( + colormap=mask_tools.generate_colormap(5)), + }) - mask_cat = MaskCategories(colormap={ - k: v for k, v in mask_tools.generate_colormap(5).items() - if k in { 0, 1, 3, 4 } - }) + dst_dataset = Dataset.from_iterable([ + DatasetItem(id=1, annotations=[ + Label(1), + Bbox(1, 2, 3, 4, label=0), + Mask(image=np.array([1]), label=1), - return { - AnnotationType.label: label_cat, - AnnotationType.mask: mask_cat, - } + Polygon([1, 1, 2, 2, 3, 4], label=2), + PolyLine([1, 3, 4, 2, 5, 6], label=None) + ]), + ], categories={ + AnnotationType.label: LabelCategories.from_iterable( + ['label0', 'label9', 'label4']), + AnnotationType.mask: MaskCategories(colormap={ + k: v for k, v in mask_tools.generate_colormap(5).items() + if k in { 0, 1, 3, 4 } + }) + }) - actual = transforms.RemapLabels(SrcExtractor(), mapping={ + actual = transforms.RemapLabels(src_dataset, mapping={ 'label1': 'label9', 'label2': 'label0', 'label3': 'label9', }, default='keep') - compare_datasets(self, DstExtractor(), actual) + compare_datasets(self, dst_dataset, actual) def test_remap_labels_delete_unspecified(self): source_dataset = Dataset.from_iterable([ DatasetItem(id=1, annotations=[ Label(0) ]) - ], categories={ - AnnotationType.label: LabelCategories.from_iterable('label0'), - }) + ], categories=['label0']) target_dataset = Dataset.from_iterable([ - DatasetItem(id=1, annotations=[]), - ], categories={ - AnnotationType.label: LabelCategories(), - }) + DatasetItem(id=1), + ], categories=[]) actual = transforms.RemapLabels(source_dataset, mapping={}, default='delete') From 87ce7cc3a41f188a7203a3ded083ffa6c791a450 Mon Sep 17 00:00:00 2001 From: RGring Date: Mon, 10 Aug 2020 12:49:19 +0200 Subject: [PATCH 34/53] Fix build with analytics (#2005) Co-authored-by: Ronja --- components/analytics/docker-compose.analytics.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/analytics/docker-compose.analytics.yml b/components/analytics/docker-compose.analytics.yml index fcb88272..eef11921 100644 --- a/components/analytics/docker-compose.analytics.yml +++ b/components/analytics/docker-compose.analytics.yml @@ -31,7 +31,7 @@ services: cvat_kibana_setup: container_name: cvat_kibana_setup - image: cvat + image: cvat/server volumes: ['./components/analytics/kibana:/home/django/kibana:ro'] depends_on: ['cvat'] working_dir: '/home/django' From 1b136296c54808d758aa10ad8f56c8589c4c2878 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2020 21:14:33 +0300 Subject: [PATCH 35/53] Bump opencv-python from 4.3.0.36 to 4.3.0.38 in /cvat/requirements (#2003) Bumps [opencv-python](https://github.com/skvark/opencv-python) from 4.3.0.36 to 4.3.0.38. - [Release notes](https://github.com/skvark/opencv-python/releases) - [Commits](https://github.com/skvark/opencv-python/commits) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- cvat/requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/requirements/base.txt b/cvat/requirements/base.txt index 864e79e2..33b84dfe 100644 --- a/cvat/requirements/base.txt +++ b/cvat/requirements/base.txt @@ -40,7 +40,7 @@ matplotlib==3.0.3 scikit-image==0.15.0 tensorflow==2.2.0 keras==2.4.2 -opencv-python==4.3.0.36 +opencv-python==4.3.0.38 h5py==2.10.0 imgaug==0.4.0 django-cors-headers==3.4.0 From 68e7288adeb8de0ca586cda85e5ab0d52bfdef57 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2020 21:14:55 +0300 Subject: [PATCH 36/53] Bump django-silk from 4.0.1 to 4.1.0 in /cvat/requirements (#2002) Bumps [django-silk](https://github.com/jazzband/django-silk) from 4.0.1 to 4.1.0. - [Release notes](https://github.com/jazzband/django-silk/releases) - [Changelog](https://github.com/jazzband/django-silk/blob/master/CHANGELOG.md) - [Commits](https://github.com/jazzband/django-silk/compare/4.0.1...4.1.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- cvat/requirements/staging.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/requirements/staging.txt b/cvat/requirements/staging.txt index 8af47209..bc8e8c2c 100644 --- a/cvat/requirements/staging.txt +++ b/cvat/requirements/staging.txt @@ -1,2 +1,2 @@ -r production.txt -django-silk==4.0.1 \ No newline at end of file +django-silk==4.1.0 \ No newline at end of file From c8964632a52a3d5a13ba27819592ec4ea0accaf1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2020 21:26:13 +0300 Subject: [PATCH 37/53] Bump django-extensions from 3.0.4 to 3.0.5 in /cvat/requirements (#2001) Bumps [django-extensions](https://github.com/django-extensions/django-extensions) from 3.0.4 to 3.0.5. - [Release notes](https://github.com/django-extensions/django-extensions/releases) - [Changelog](https://github.com/django-extensions/django-extensions/blob/master/CHANGELOG.md) - [Commits](https://github.com/django-extensions/django-extensions/compare/3.0.4...3.0.5) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- cvat/requirements/development.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/requirements/development.txt b/cvat/requirements/development.txt index c7e50071..92b2272d 100644 --- a/cvat/requirements/development.txt +++ b/cvat/requirements/development.txt @@ -8,6 +8,6 @@ pylint-django==2.3.0 pylint-plugin-utils==0.6 rope==0.17.0 wrapt==1.12.1 -django-extensions==3.0.4 +django-extensions==3.0.5 Werkzeug==1.0.1 snakeviz==2.1.0 From d6ca864d51573c77f81ffbe8acd140f2f85d398d Mon Sep 17 00:00:00 2001 From: Andrey Zhavoronkov <41117609+azhavoro@users.noreply.github.com> Date: Tue, 11 Aug 2020 05:37:27 +0300 Subject: [PATCH 38/53] Added instructions how to deploy CVAT behind a proxy (#2009) * added deploy behind a proxy instructions * fix * updated toc * fixed typo --- .../analytics/docker-compose.analytics.yml | 2 +- cvat/apps/documentation/installation.md | 23 +++++++++++++++++++ docker-compose.yml | 12 +++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/components/analytics/docker-compose.analytics.yml b/components/analytics/docker-compose.analytics.yml index eef11921..5edcd505 100644 --- a/components/analytics/docker-compose.analytics.yml +++ b/components/analytics/docker-compose.analytics.yml @@ -63,7 +63,7 @@ services: DJANGO_LOG_SERVER_PORT: 5000 DJANGO_LOG_VIEWER_HOST: kibana DJANGO_LOG_VIEWER_PORT: 5601 - no_proxy: kibana,logstash,${no_proxy} + no_proxy: kibana,logstash,nuclio,${no_proxy} volumes: cvat_events: diff --git a/cvat/apps/documentation/installation.md b/cvat/apps/documentation/installation.md index 9bff3930..1741a16b 100644 --- a/cvat/apps/documentation/installation.md +++ b/cvat/apps/documentation/installation.md @@ -3,6 +3,7 @@ - [Windows 10](#windows-10) - [Mac OS Mojave](#mac-os-mojave) - [Advanced topics](#advanced-topics) + - [Deploying CVAT behind a proxy](#deploying-cvat-behind-a-proxy) - [Additional components](#additional-components) - [Semi-automatic and automatic annotation](#semi-automatic-and-automatic-annotation) - [Stop all containers](#stop-all-containers) @@ -245,6 +246,28 @@ server. Proxy is an advanced topic and it is not covered by the guide. ## Advanced topics +### Deploying CVAT behind a proxy +If you deploy CVAT behind a proxy and do not plan to use any of [serverless functions](#semi-automatic-and-automatic-annotation) +for automatic annotation, the exported environment variables +`http_proxy`, `https_proxy` and `no_proxy` should be enough to build images. +Otherwise please create or edit the file `~/.docker/config.json` in the home directory of the user +which starts containers and add JSON such as the following: +```json +{ + "proxies": + { + "default": + { + "httpProxy": "http://proxy_server:port", + "httpsProxy": "http://proxy_server:port", + "noProxy": "*.test.example.com,.example2.com" + } + } +} +``` +These environment variables are set automatically within any container. +Please see the [Docker documentation](https://docs.docker.com/network/proxy/) for more details. + ### Additional components - [Analytics: management and monitoring of data annotation team](/components/analytics/README.md) diff --git a/docker-compose.yml b/docker-compose.yml index 60a5965b..6745493f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,7 +42,7 @@ services: args: http_proxy: https_proxy: - no_proxy: + no_proxy: nuclio,${no_proxy} socks_proxy: USER: "django" DJANGO_CONFIGURATION: "production" @@ -107,10 +107,20 @@ services: - /tmp:/tmp - /var/run/docker.sock:/var/run/docker.sock environment: + http_proxy: + https_proxy: + no_proxy: 172.28.0.1,${no_proxy} NUCLIO_CHECK_FUNCTION_CONTAINERS_HEALTHINESS: "true" ports: - "8070:8070" +networks: + default: + ipam: + config: + - subnet: 172.28.0.0/24 + gateway: 172.28.0.1 + volumes: cvat_db: cvat_data: From ca4b320d23c7c610bee9f8b03a61b70f6c63de42 Mon Sep 17 00:00:00 2001 From: Dmitry Kruchinin <33020454+dvkruchinin@users.noreply.github.com> Date: Tue, 11 Aug 2020 10:09:56 +0300 Subject: [PATCH 39/53] Preparation for testing. Add tests for issue 1599. (#1983) * Automate test preparation(mandatory operations for each test cases) - Add test for creating an annotation task. - Add automate for creating superuser. * Add tests for issue 1599. * Run Cypress from Travis CI. Remove Cypress installation command from Dockerfile.ci Remove the unnecessary docker-compose.ci.yml * Replase image for creation an annotation task. Change name of imsge in the Cypress test create_new_task.js * Temporarily deleting the annotation task creation functionality * Image generarion functionality Add Cypress module for auto generation images Add package files. * Add custome commands for create an annotation task and a shape. * Applying comments. * /tasks instead of /task in the tests (applying comments) Co-authored-by: Dmitry Kruchinin --- .travis.yml | 26 +- Dockerfile.ci | 7 - tests/cypress.json | 9 +- tests/cypress/integration/auth_page.js | 36 +- .../issue_1599_ch_user_registration.js | 50 + .../issue_1599_pl_user_registration.js | 50 + .../plugins/imageGenerator/addPlugin.js | 31 + .../imageGenerator/imageGeneratorCommand.js | 25 + tests/cypress/plugins/index.js | 13 + tests/cypress/support/commands.js | 47 + tests/cypress/support/index.js | 7 + tests/cypress_ci.json | 4 - tests/package-lock.json | 2270 +++++++++++++++++ tests/package.json | 9 + 14 files changed, 2552 insertions(+), 32 deletions(-) create mode 100644 tests/cypress/integration/issue_1599_ch_user_registration.js create mode 100644 tests/cypress/integration/issue_1599_pl_user_registration.js create mode 100644 tests/cypress/plugins/imageGenerator/addPlugin.js create mode 100644 tests/cypress/plugins/imageGenerator/imageGeneratorCommand.js create mode 100644 tests/cypress/plugins/index.js create mode 100644 tests/cypress/support/commands.js create mode 100644 tests/cypress/support/index.js delete mode 100644 tests/cypress_ci.json create mode 100644 tests/package-lock.json create mode 100644 tests/package.json diff --git a/.travis.yml b/.travis.yml index 855a9d72..68533c0d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,12 +5,29 @@ language: python python: - "3.5" +cache: + npm: true + directories: + - ~/.cache + +addons: + apt: + packages: + - libgconf-2-4 + services: - docker env: - CONTAINER_COVERAGE_DATA_DIR="/coverage_data" HOST_COVERAGE_DATA_DIR="${TRAVIS_BUILD_DIR}" + DJANGO_SU_NAME="admin" + DJANGO_SU_EMAIL="admin@localhost.company" + DJANGO_SU_PASSWORD="12qwaszx" + NODE_VERSION="12" + +before_install: + - nvm install ${NODE_VERSION} before_script: - docker-compose -f docker-compose.yml -f docker-compose.ci.yml build @@ -20,8 +37,13 @@ script: # FIXME: Git package and application name conflict in PATH and try to leave only one python test execution - docker-compose -f docker-compose.yml -f docker-compose.ci.yml run cvat_ci /bin/bash -c 'coverage run -a manage.py test cvat/apps && coverage run -a manage.py test --pattern="_test*.py" cvat/apps/dataset_manager/tests cvat/apps/engine/tests utils/cli && coverage run -a manage.py test datumaro/ && mv .coverage ${CONTAINER_COVERAGE_DATA_DIR}' - docker-compose -f docker-compose.yml -f docker-compose.ci.yml run cvat_ci /bin/bash -c 'cd cvat-data && npm install && cd ../cvat-core && npm install && npm run test && coveralls-lcov -v -n ./reports/coverage/lcov.info > ${CONTAINER_COVERAGE_DATA_DIR}/coverage.json' - # Run cypress tests - - docker-compose -f docker-compose.yml -f docker-compose.ci.yml run cvat_ci /bin/bash -c 'cd ~/tests && ./node_modules/.bin/cypress run --headless --browser chrome --config-file=cypress_ci.json' + # Up all containers + - docker-compose up -d + # Create superuser + - docker exec -it cvat bash -ic "echo \"from django.contrib.auth.models import User; User.objects.create_superuser('${DJANGO_SU_NAME}', '${DJANGO_SU_EMAIL}', '${DJANGO_SU_PASSWORD}')\" | python3 ~/manage.py shell" + # Install Cypress and run tests + - cd ./tests && npm install + - $(npm bin)/cypress run --headless --browser chrome && cd .. after_success: # https://coveralls-python.readthedocs.io/en/latest/usage/multilang.html diff --git a/Dockerfile.ci b/Dockerfile.ci index b0dd7293..422259de 100644 --- a/Dockerfile.ci +++ b/Dockerfile.ci @@ -14,7 +14,6 @@ RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - & nodejs \ python3-dev \ ruby \ - xvfb \ && \ rm -rf /var/lib/apt/lists/*; @@ -24,10 +23,4 @@ RUN gem install coveralls-lcov COPY .coveragerc . -# RUN all commands below as 'django' user -USER ${USER} - -RUN mkdir -p tests && cd tests && CI=true npm install cypress; \ - echo "export PATH=~/tests/node_modules/.bin:${PATH}" >> ~/.bashrc; - ENTRYPOINT [] diff --git a/tests/cypress.json b/tests/cypress.json index 371abf5a..4f32312d 100644 --- a/tests/cypress.json +++ b/tests/cypress.json @@ -1,3 +1,10 @@ { - "baseUrl": "http://localhost:8080" + "video": false, + "baseUrl": "http://localhost:8080", + "viewportWidth": 1300, + "viewportHeight": 960, + "testFiles": [ + "auth_page.js", + "issue_*.js" + ] } diff --git a/tests/cypress/integration/auth_page.js b/tests/cypress/integration/auth_page.js index a2120bb5..1583a326 100644 --- a/tests/cypress/integration/auth_page.js +++ b/tests/cypress/integration/auth_page.js @@ -7,27 +7,27 @@ /// describe('Check server availability', () => { - it('Server web interface is available', () => { - cy.visit('/') - }) + it('Server web interface is available', () => { + cy.visit('/') + }) - it('"/auth/login" contains in the URL', () => { - cy.url().should('include', '/auth/login') - }) + it('"/auth/login" contains in the URL', () => { + cy.url({ timeout: 8000 }).should('include', '/auth/login') + }) - it('"Sign in" button is exists', () => { - cy.get('[type="submit"]') - }) + it('"Sign in" button is exists', () => { + cy.get('[type="submit"]') + }) - it('Check plaseholder "Username"', () => { - cy.get('input').invoke('attr', 'placeholder').should('contain', 'Username') - }) + it('Check placeholder "Username"', () => { + cy.get('input').invoke('attr', 'placeholder').should('contain', 'Username') + }) - it('Check plaseholder "Password"', () => { - cy.get('[type="password"]') - }) + it('Check placeholder "Password"', () => { + cy.get('[type="password"]') + }) - it('Click to "Sign in" button', () => { - cy.get('[type="submit"]').click() - }) + it('Click to "Sign in" button', () => { + cy.get('[type="submit"]').click() + }) }) diff --git a/tests/cypress/integration/issue_1599_ch_user_registration.js b/tests/cypress/integration/issue_1599_ch_user_registration.js new file mode 100644 index 00000000..8bbe6c11 --- /dev/null +++ b/tests/cypress/integration/issue_1599_ch_user_registration.js @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + */ + +/// + +context('Issue 1599 (Chinese alphabet).', () => { + before(() => { + cy.visit('auth/register') + cy.url().should('include', '/auth/register') + }) + + describe('User registration using the Chinese alphabet.', () => { + it('Filling in the placeholder "First name"', () => { + cy.get('[placeholder="First name"]').type('测试者') + .should('not.have.class', 'has-error') + }) + + it('Filling in the placeholder "Last name"', () => { + cy.get('[placeholder="Last name"]').type('测试') + .should('not.have.class', 'has-error') + }) + + it('Filling in the placeholder "Username"', () => { + cy.get('[placeholder="Username"]').type('Testuser_ch') + }) + + it('Filling in the placeholder "Email address"', () => { + cy.get('[placeholder="Email address"]').type('Testuser_ch@local.local') + }) + + it('Filling in the placeholder "Password"', () => { + cy.get('[placeholder="Password"]').type('Qwerty123!') + }) + + it('Filling in the placeholder "Confirm password"', () => { + cy.get('[placeholder="Confirm password"]').type('Qwerty123!') + }) + + it('Click to "Submit" button', () => { + cy.get('[type="submit"]').click() + }) + + it('Successful registration', () => { + cy.url().should('include', '/tasks') + }) + }) +}) diff --git a/tests/cypress/integration/issue_1599_pl_user_registration.js b/tests/cypress/integration/issue_1599_pl_user_registration.js new file mode 100644 index 00000000..4551ac94 --- /dev/null +++ b/tests/cypress/integration/issue_1599_pl_user_registration.js @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + */ + +/// + +context('Issue 1599 (Polish alphabet).', () => { + before(() => { + cy.visit('auth/register') + cy.url().should('include', '/auth/register') + }) + + describe('User registration using the Polish alphabet.', () => { + it('Filling in the placeholder "First name"', () => { + cy.get('[placeholder="First name"]').type('Świętobor') + .should('not.have.class', 'has-error') + }) + + it('Filling in the placeholder "Last name"', () => { + cy.get('[placeholder="Last name"]').type('Сzcić') + .should('not.have.class', 'has-error') + }) + + it('Filling in the placeholder "Username"', () => { + cy.get('[placeholder="Username"]').type('Testuser_pl') + }) + + it('Filling in the placeholder "Email address"', () => { + cy.get('[placeholder="Email address"]').type('Testuser_pl@local.local') + }) + + it('Filling in the placeholder "Password"', () => { + cy.get('[placeholder="Password"]').type('Qwerty123!') + }) + + it('Filling in the placeholder "Confirm password"', () => { + cy.get('[placeholder="Confirm password"]').type('Qwerty123!') + }) + + it('Click to "Submit" button', () => { + cy.get('[type="submit"]').click() + }) + + it('Successful registration', () => { + cy.url().should('include', '/tasks') + }) + }) +}) diff --git a/tests/cypress/plugins/imageGenerator/addPlugin.js b/tests/cypress/plugins/imageGenerator/addPlugin.js new file mode 100644 index 00000000..9156ad58 --- /dev/null +++ b/tests/cypress/plugins/imageGenerator/addPlugin.js @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + */ + +exports.imageGenerator = imageGenerator + +const jimp = require('jimp') +const path = require('path') + +function imageGenerator(args) { + const directory = args.directory + const fileName = args.fileName + const width = args.width + const height = args.height + const color = args.color + const posX = args.posX + const posY = args.posY + const message = args.message + const file = path.join(directory, fileName) + const image = new jimp(width, height, color, function (err, image) { + if (err) throw err + jimp.loadFont(jimp.FONT_SANS_64_BLACK, function (err, font) { + if (err) throw err + image.print(font, Number(posX), Number(posY), message) + .write(file) + }) + }) + return file +} diff --git a/tests/cypress/plugins/imageGenerator/imageGeneratorCommand.js b/tests/cypress/plugins/imageGenerator/imageGeneratorCommand.js new file mode 100644 index 00000000..b51b6e23 --- /dev/null +++ b/tests/cypress/plugins/imageGenerator/imageGeneratorCommand.js @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + */ + +Cypress.Commands.add('imageGenerator', (directory, + fileName, + width, + height, + color, + posX, + posY, + message) => { + return cy.task('imageGenerator', { + directory: directory, + fileName: fileName, + width: width, + height: height, + color: color, + posX: posX, + posY: posY, + message: message + }) +}) diff --git a/tests/cypress/plugins/index.js b/tests/cypress/plugins/index.js new file mode 100644 index 00000000..d5499c43 --- /dev/null +++ b/tests/cypress/plugins/index.js @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + */ + +/// + +const {imageGenerator} = require('../plugins/imageGenerator/addPlugin') + +module.exports = (on) => { + on('task', {imageGenerator}) +} diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js new file mode 100644 index 00000000..1601e60b --- /dev/null +++ b/tests/cypress/support/commands.js @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + */ + +/// + +require('cypress-file-upload') +require('../plugins/imageGenerator/imageGeneratorCommand') + +Cypress.Commands.add('login', (username='admin', password='12qwaszx') => { + cy.get('[placeholder="Username"]').type(username) + cy.get('[placeholder="Password"]').type(password) +}) + +Cypress.Commands.add('createAnnotationTask', (taksName='New annotation task', + labelName='Some label', + attrName='Some attr name', + textDefaultValue='Some default value for type Text', + image='image.png') => { + cy.contains('button', 'Create new task').click() + cy.url().should('include', '/tasks/create') + cy.get('[id="name"]').type(taksName) + cy.contains('button', 'Add label').click() + cy.get('[placeholder="Label name"]').type(labelName) + cy.contains('button', 'Add an attribute').click() + cy.get('[placeholder="Name"]').type(attrName) + cy.get('div[title="Select"]').click() + cy.get('li').contains('Text').click() + cy.get('[placeholder="Default value"]').type(textDefaultValue) + cy.contains('button', 'Done').click() + cy.get('input[type="file"]').attachFile(image, { subjectType: 'drag-n-drop' }); + cy.contains('button', 'Submit').click() + cy.contains('The task has been created', {timeout: '8000'}) + cy.get('button[value="tasks"]').click() + cy.url().should('include', '/tasks?page=') +}) + +Cypress.Commands.add('createShape', (ferstX, ferstY, lastX, lastY) => { + cy.get(':nth-child(8) > svg').trigger('mousemove').click() + cy.get(':nth-child(6) > :nth-child(1) > .ant-btn').click() + cy.get('.cvat-canvas-container') + .click(ferstX, ferstY) + cy.get('.cvat-canvas-container') + .click(lastX, lastY) +}) diff --git a/tests/cypress/support/index.js b/tests/cypress/support/index.js new file mode 100644 index 00000000..bf9295aa --- /dev/null +++ b/tests/cypress/support/index.js @@ -0,0 +1,7 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + */ + +import './commands' diff --git a/tests/cypress_ci.json b/tests/cypress_ci.json deleted file mode 100644 index ed68fd7c..00000000 --- a/tests/cypress_ci.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "video": false, - "baseUrl": "http://cvat_ui" -} diff --git a/tests/package-lock.json b/tests/package-lock.json new file mode 100644 index 00000000..9b299b3d --- /dev/null +++ b/tests/package-lock.json @@ -0,0 +1,2270 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@babel/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@cypress/listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha1-p3SS9LEdzHxEajSz4ochr9M8ZCo=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-cursor": "^1.0.2", + "date-fns": "^1.27.2", + "figures": "^1.7.0" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "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" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "@cypress/request": { + "version": "2.88.5", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.5.tgz", + "integrity": "sha512-TzEC1XMi1hJkywWpRfD2clreTa/Z+lOrXDCxxBTBPEcY5azdPi56A6Xw+O4tWJnaJH3iIE7G5aDXZC6JgRZLcA==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "@jimp/bmp": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.14.0.tgz", + "integrity": "sha512-5RkX6tSS7K3K3xNEb2ygPuvyL9whjanhoaB/WmmXlJS6ub4DjTqrapu8j4qnIWmO4YYtFeTbDTXV6v9P1yMA5A==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0", + "bmp-js": "^0.1.0" + } + }, + "@jimp/core": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.14.0.tgz", + "integrity": "sha512-S62FcKdtLtj3yWsGfJRdFXSutjvHg7aQNiFogMbwq19RP4XJWqS2nOphu7ScB8KrSlyy5nPF2hkWNhLRLyD82w==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^9.0.0", + "load-bmfont": "^1.3.1", + "mkdirp": "^0.5.1", + "phin": "^2.9.1", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.4.1" + } + }, + "@jimp/custom": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.14.0.tgz", + "integrity": "sha512-kQJMeH87+kWJdVw8F9GQhtsageqqxrvzg7yyOw3Tx/s7v5RToe8RnKyMM+kVtBJtNAG+Xyv/z01uYQ2jiZ3GwA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/core": "^0.14.0" + } + }, + "@jimp/gif": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.14.0.tgz", + "integrity": "sha512-DHjoOSfCaCz72+oGGEh8qH0zE6pUBaBxPxxmpYJjkNyDZP7RkbBkZJScIYeQ7BmJxmGN4/dZn+MxamoQlr+UYg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0", + "gifwrap": "^0.9.2", + "omggif": "^1.0.9" + } + }, + "@jimp/jpeg": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.14.0.tgz", + "integrity": "sha512-561neGbr+87S/YVQYnZSTyjWTHBm9F6F1obYHiyU3wVmF+1CLbxY3FQzt4YolwyQHIBv36Bo0PY2KkkU8BEeeQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0", + "jpeg-js": "^0.4.0" + } + }, + "@jimp/plugin-blit": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.14.0.tgz", + "integrity": "sha512-YoYOrnVHeX3InfgbJawAU601iTZMwEBZkyqcP1V/S33Qnz9uzH1Uj1NtC6fNgWzvX6I4XbCWwtr4RrGFb5CFrw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-blur": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.14.0.tgz", + "integrity": "sha512-9WhZcofLrT0hgI7t0chf7iBQZib//0gJh9WcQMUt5+Q1Bk04dWs8vTgLNj61GBqZXgHSPzE4OpCrrLDBG8zlhQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-circle": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.14.0.tgz", + "integrity": "sha512-o5L+wf6QA44tvTum5HeLyLSc5eVfIUd5ZDVi5iRfO4o6GT/zux9AxuTSkKwnjhsG8bn1dDmywAOQGAx7BjrQVA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-color": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.14.0.tgz", + "integrity": "sha512-JJz512SAILYV0M5LzBb9sbOm/XEj2fGElMiHAxb7aLI6jx+n0agxtHpfpV/AePTLm1vzzDxx6AJxXbKv355hBQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0", + "tinycolor2": "^1.4.1" + } + }, + "@jimp/plugin-contain": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.14.0.tgz", + "integrity": "sha512-RX2q233lGyaxiMY6kAgnm9ScmEkNSof0hdlaJAVDS1OgXphGAYAeSIAwzESZN4x3ORaWvkFefeVH9O9/698Evg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-cover": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.14.0.tgz", + "integrity": "sha512-0P/5XhzWES4uMdvbi3beUgfvhn4YuQ/ny8ijs5kkYIw6K8mHcl820HahuGpwWMx56DJLHRl1hFhJwo9CeTRJtQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-crop": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.14.0.tgz", + "integrity": "sha512-Ojtih+XIe6/XSGtpWtbAXBozhCdsDMmy+THUJAGu2x7ZgKrMS0JotN+vN2YC3nwDpYkM+yOJImQeptSfZb2Sug==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-displace": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.14.0.tgz", + "integrity": "sha512-c75uQUzMgrHa8vegkgUvgRL/PRvD7paFbFJvzW0Ugs8Wl+CDMGIPYQ3j7IVaQkIS+cAxv+NJ3TIRBQyBrfVEOg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-dither": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.14.0.tgz", + "integrity": "sha512-g8SJqFLyYexXQQsoh4dc1VP87TwyOgeTElBcxSXX2LaaMZezypmxQfLTzOFzZoK8m39NuaoH21Ou1Ftsq7LzVQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-fisheye": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.14.0.tgz", + "integrity": "sha512-BFfUZ64EikCaABhCA6mR3bsltWhPpS321jpeIQfJyrILdpFsZ/OccNwCgpW1XlbldDHIoNtXTDGn3E+vCE7vDg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-flip": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.14.0.tgz", + "integrity": "sha512-WtL1hj6ryqHhApih+9qZQYA6Ye8a4HAmdTzLbYdTMrrrSUgIzFdiZsD0WeDHpgS/+QMsWwF+NFmTZmxNWqKfXw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-gaussian": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.14.0.tgz", + "integrity": "sha512-uaLwQ0XAQoydDlF9tlfc7iD9drYPriFe+jgYnWm8fbw5cN+eOIcnneEX9XCOOzwgLPkNCxGox6Kxjn8zY6GxtQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-invert": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.14.0.tgz", + "integrity": "sha512-UaQW9X9vx8orQXYSjT5VcITkJPwDaHwrBbxxPoDG+F/Zgv4oV9fP+udDD6qmkgI9taU+44Fy+zm/J/gGcMWrdg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-mask": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.14.0.tgz", + "integrity": "sha512-tdiGM69OBaKtSPfYSQeflzFhEpoRZ+BvKfDEoivyTjauynbjpRiwB1CaiS8En1INTDwzLXTT0Be9SpI3LkJoEA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-normalize": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.14.0.tgz", + "integrity": "sha512-AfY8sqlsbbdVwFGcyIPy5JH/7fnBzlmuweb+Qtx2vn29okq6+HelLjw2b+VT2btgGUmWWHGEHd86oRGSoWGyEQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-print": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.14.0.tgz", + "integrity": "sha512-MwP3sH+VS5AhhSTXk7pui+tEJFsxnTKFY3TraFJb8WFbA2Vo2qsRCZseEGwpTLhENB7p/JSsLvWoSSbpmxhFAQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0", + "load-bmfont": "^1.4.0" + } + }, + "@jimp/plugin-resize": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.14.0.tgz", + "integrity": "sha512-qFeMOyXE/Bk6QXN0GQo89+CB2dQcXqoxUcDb2Ah8wdYlKqpi53skABkgVy5pW3EpiprDnzNDboMltdvDslNgLQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-rotate": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.14.0.tgz", + "integrity": "sha512-aGaicts44bvpTcq5Dtf93/8TZFu5pMo/61lWWnYmwJJU1RqtQlxbCLEQpMyRhKDNSfPbuP8nyGmaqXlM/82J0Q==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-scale": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.14.0.tgz", + "integrity": "sha512-ZcJk0hxY5ZKZDDwflqQNHEGRblgaR+piePZm7dPwPUOSeYEH31P0AwZ1ziceR74zd8N80M0TMft+e3Td6KGBHw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-shadow": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.14.0.tgz", + "integrity": "sha512-p2igcEr/iGrLiTu0YePNHyby0WYAXM14c5cECZIVnq/UTOOIQ7xIcWZJ1lRbAEPxVVXPN1UibhZAbr3HAb5BjQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugin-threshold": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.14.0.tgz", + "integrity": "sha512-N4BlDgm/FoOMV/DQM2rSpzsgqAzkP0DXkWZoqaQrlRxQBo4zizQLzhEL00T/YCCMKnddzgEhnByaocgaaa0fKw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0" + } + }, + "@jimp/plugins": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.14.0.tgz", + "integrity": "sha512-vDO3XT/YQlFlFLq5TqNjQkISqjBHT8VMhpWhAfJVwuXIpilxz5Glu4IDLK6jp4IjPR6Yg2WO8TmRY/HI8vLrOw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/plugin-blit": "^0.14.0", + "@jimp/plugin-blur": "^0.14.0", + "@jimp/plugin-circle": "^0.14.0", + "@jimp/plugin-color": "^0.14.0", + "@jimp/plugin-contain": "^0.14.0", + "@jimp/plugin-cover": "^0.14.0", + "@jimp/plugin-crop": "^0.14.0", + "@jimp/plugin-displace": "^0.14.0", + "@jimp/plugin-dither": "^0.14.0", + "@jimp/plugin-fisheye": "^0.14.0", + "@jimp/plugin-flip": "^0.14.0", + "@jimp/plugin-gaussian": "^0.14.0", + "@jimp/plugin-invert": "^0.14.0", + "@jimp/plugin-mask": "^0.14.0", + "@jimp/plugin-normalize": "^0.14.0", + "@jimp/plugin-print": "^0.14.0", + "@jimp/plugin-resize": "^0.14.0", + "@jimp/plugin-rotate": "^0.14.0", + "@jimp/plugin-scale": "^0.14.0", + "@jimp/plugin-shadow": "^0.14.0", + "@jimp/plugin-threshold": "^0.14.0", + "timm": "^1.6.1" + } + }, + "@jimp/png": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.14.0.tgz", + "integrity": "sha512-0RV/mEIDOrPCcNfXSPmPBqqSZYwGADNRVUTyMt47RuZh7sugbYdv/uvKmQSiqRdR0L1sfbCBMWUEa5G/8MSbdA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.14.0", + "pngjs": "^3.3.3" + } + }, + "@jimp/tiff": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.14.0.tgz", + "integrity": "sha512-zBYDTlutc7j88G/7FBCn3kmQwWr0rmm1e0FKB4C3uJ5oYfT8645lftUsvosKVUEfkdmOaMAnhrf4ekaHcb5gQw==", + "requires": { + "@babel/runtime": "^7.7.2", + "utif": "^2.0.1" + } + }, + "@jimp/types": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.14.0.tgz", + "integrity": "sha512-hx3cXAW1KZm+b+XCrY3LXtdWy2U+hNtq0rPyJ7NuXCjU7lZR3vIkpz1DLJ3yDdS70hTi5QDXY3Cd9kd6DtloHQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/bmp": "^0.14.0", + "@jimp/gif": "^0.14.0", + "@jimp/jpeg": "^0.14.0", + "@jimp/png": "^0.14.0", + "@jimp/tiff": "^0.14.0", + "timm": "^1.6.1" + } + }, + "@jimp/utils": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.14.0.tgz", + "integrity": "sha512-MY5KFYUru0y74IsgM/9asDwb3ERxWxXEu3CRCZEvE7DtT86y1bR1XgtlSliMrptjz4qbivNGMQSvUBpEFJDp1A==", + "requires": { + "@babel/runtime": "^7.7.2", + "regenerator-runtime": "^0.13.3" + } + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, + "@types/sinonjs__fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.1.tgz", + "integrity": "sha512-yYezQwGWty8ziyYLdZjwxyMb0CZR49h8JALHGrxjQHWlqGgc8kLdHEgWrgL0uZ29DMvEVBDnHU2Wg36zKSIUtA==", + "dev": true + }, + "@types/sizzle": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", + "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==", + "dev": true + }, + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, + "arch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.2.tgz", + "integrity": "sha512-NTBIIbAfkJeIletyABbVtdPgeKfDafR+1mZV/AyyfC1UkVkp9iUjV+wwmqtUgphHYajbI86jejBJp5e+jkGTiQ==", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", + "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", + "dev": true + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "dev": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "optional": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "cypress": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-4.12.1.tgz", + "integrity": "sha512-9SGIPEmqU8vuRA6xst2CMTYd9sCFCxKSzrHt0wr+w2iAQMCIIsXsQ5Gplns1sT6LDbZcmLv6uehabAOl3fhc9Q==", + "dev": true, + "requires": { + "@cypress/listr-verbose-renderer": "^0.4.1", + "@cypress/request": "^2.88.5", + "@cypress/xvfb": "^1.2.4", + "@types/sinonjs__fake-timers": "^6.0.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.1.2", + "bluebird": "^3.7.2", + "cachedir": "^2.3.0", + "chalk": "^2.4.2", + "check-more-types": "^2.24.0", + "cli-table3": "~0.5.1", + "commander": "^4.1.1", + "common-tags": "^1.8.0", + "debug": "^4.1.1", + "eventemitter2": "^6.4.2", + "execa": "^1.0.0", + "executable": "^4.1.1", + "extract-zip": "^1.7.0", + "fs-extra": "^8.1.0", + "getos": "^3.2.1", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.2", + "lazy-ass": "^1.6.0", + "listr": "^0.14.3", + "lodash": "^4.17.19", + "log-symbols": "^3.0.0", + "minimist": "^1.2.5", + "moment": "^2.27.0", + "ospath": "^1.2.2", + "pretty-bytes": "^5.3.0", + "ramda": "~0.26.1", + "request-progress": "^3.0.0", + "supports-color": "^7.1.0", + "tmp": "~0.1.0", + "untildify": "^4.0.0", + "url": "^0.11.0", + "yauzl": "^2.10.0" + } + }, + "cypress-file-upload": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cypress-file-upload/-/cypress-file-upload-4.0.7.tgz", + "integrity": "sha512-rFFmnoZ2bWyWFpSV09AhkSUgYEiVy70pcQ6nf/mGTMTrVHvKCCCIfRu3TbgVYHbgBq+0hqjfjQrtz4IbgH7qZA==", + "dev": true, + "requires": { + "mime": "^2.4.4" + }, + "dependencies": { + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + } + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eventemitter2": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.3.tgz", + "integrity": "sha512-t0A2msp6BzOf+QAcI6z9XMktLj52OjGQg+8SJH6v5+3uxNpWYRR3wQmfA+6xtMU9kOC59qk9licus5dYcrYkMQ==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.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" + } + }, + "executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "requires": { + "pify": "^2.2.0" + } + }, + "exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, + "requires": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-type": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", + "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, + "requires": { + "async": "^3.2.0" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "gifwrap": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.2.tgz", + "integrity": "sha512-fcIswrPaiCDAyO8xnWvHSZdWChjKXUanKKpAiWWJ/UTkEi/aYKn5+90e7DE820zbEaVR9CE2y4z9bzhQijZ0BA==", + "requires": { + "image-q": "^1.1.1", + "omggif": "^1.0.10" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "requires": { + "min-document": "^2.19.0", + "process": "~0.5.1" + } + }, + "global-dirs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", + "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "dev": true, + "requires": { + "ini": "^1.3.5" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "image-q": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-1.1.1.tgz", + "integrity": "sha1-/IQJlmRGC5DKhi2TALa/u7+/gFY=" + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" + }, + "is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "dev": true, + "requires": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + } + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dev": true, + "requires": { + "symbol-observable": "^1.1.0" + } + }, + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "dev": true + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jimp": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.14.0.tgz", + "integrity": "sha512-8BXU+J8+SPmwwyq9ELihpSV4dWPTiOKBWCEgtkbnxxAVMjXdf3yGmyaLSshBfXc8sP/JQ9OZj5R8nZzz2wPXgA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/custom": "^0.14.0", + "@jimp/plugins": "^0.14.0", + "@jimp/types": "^0.14.0", + "regenerator-runtime": "^0.13.3" + } + }, + "jpeg-js": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.1.tgz", + "integrity": "sha512-jA55yJiB5tCXEddos8JBbvW+IMrqY0y1tjjx9KNVtA+QPmu7ND5j0zkKopClpUTsaETL135uOM2XfcYG4XRjmw==" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", + "dev": true + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dev": true, + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "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" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + }, + "dependencies": { + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + } + } + }, + "load-bmfont": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", + "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", + "requires": { + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^2.9.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" + } + }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "requires": { + "dom-walk": "^0.1.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "moment": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=" + }, + "parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=" + }, + "parse-bmfont-xml": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", + "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", + "requires": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.4.5" + } + }, + "parse-headers": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", + "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "phin": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pixelmatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=", + "requires": { + "pngjs": "^3.0.0" + } + }, + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" + }, + "pretty-bytes": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz", + "integrity": "sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg==", + "dev": true + }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, + "request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", + "dev": true, + "requires": { + "throttleit": "^1.0.0" + } + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rxjs": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz", + "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + } + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "dev": true + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "timm": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.6.2.tgz", + "integrity": "sha512-IH3DYDL1wMUwmIlVmMrmesw5lZD6N+ZOAFWEyLrtpoL9Bcrs9u7M/vyOnHzDD2SMs4irLkVjqxZbHrXStS/Nmw==" + }, + "tinycolor2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, + "tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "dev": true, + "requires": { + "rimraf": "^2.6.3" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "utif": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", + "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", + "requires": { + "pako": "^1.0.5" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "requires": { + "global": "~4.3.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=" + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/tests/package.json b/tests/package.json new file mode 100644 index 00000000..a1ab2cc8 --- /dev/null +++ b/tests/package.json @@ -0,0 +1,9 @@ +{ + "devDependencies": { + "cypress": "^4.12.1", + "cypress-file-upload": "^4.0.7" + }, + "dependencies": { + "jimp": "^0.14.0" + } +} From 2c661020b61b6c87efe086a8de6aeeb7052aa747 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Tue, 11 Aug 2020 12:50:54 +0300 Subject: [PATCH 40/53] Fixed issue related with deactivated nuclio dashboard (#2008) * Fixed issue related with deactivated nuclio dashboard * Updated version, updated changelog --- CHANGELOG.md | 1 + cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- cvat-ui/src/actions/plugins-actions.ts | 19 +++++------------- cvat-ui/src/components/cvat-app.tsx | 18 +++++++++++++---- .../model-runner-modal/model-runner-modal.tsx | 16 +-------------- .../components/models-page/models-page.tsx | 19 +----------------- .../model-runner-dialog.tsx | 20 ++----------------- .../containers/models-page/models-page.tsx | 20 +------------------ cvat-ui/src/index.tsx | 9 ++++++++- cvat-ui/src/reducers/interfaces.ts | 3 --- cvat-ui/src/reducers/notifications-reducer.ts | 19 ------------------ cvat-ui/src/utils/plugin-checker.ts | 8 ++++++-- 13 files changed, 41 insertions(+), 115 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48c0d0ff..26e3bafc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Issue loading openvino models for semi-automatic and automatic annotation () +- Basic functions of CVAT works without activated nuclio dashboard ### Security - diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 256a48e6..8def8aaa 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.7.0", + "version": "1.7.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 1ec122bd..f20e3eb6 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.7.0", + "version": "1.7.1", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { diff --git a/cvat-ui/src/actions/plugins-actions.ts b/cvat-ui/src/actions/plugins-actions.ts index 5d58a11f..6b5ca2c9 100644 --- a/cvat-ui/src/actions/plugins-actions.ts +++ b/cvat-ui/src/actions/plugins-actions.ts @@ -9,7 +9,6 @@ import PluginChecker from 'utils/plugin-checker'; export enum PluginsActionTypes { CHECK_PLUGINS = 'CHECK_PLUGINS', CHECKED_ALL_PLUGINS = 'CHECKED_ALL_PLUGINS', - RAISE_PLUGIN_CHECK_ERROR = 'RAISE_PLUGIN_CHECK_ERROR' } type PluginObjects = Record; @@ -21,11 +20,6 @@ const pluginActions = { list, }) ), - raisePluginCheckError: (error: Error) => ( - createAction(PluginsActionTypes.RAISE_PLUGIN_CHECK_ERROR, { - error, - }) - ), }; export type PluginActions = ActionUnion; @@ -40,18 +34,15 @@ export function checkPluginsAsync(): ThunkAction { }; const promises: Promise[] = [ + // check must return true/false with no exceptions PluginChecker.check(SupportedPlugins.ANALYTICS), PluginChecker.check(SupportedPlugins.GIT_INTEGRATION), PluginChecker.check(SupportedPlugins.DEXTR_SEGMENTATION), ]; - try { - const values = await Promise.all(promises); - [plugins.ANALYTICS, plugins.GIT_INTEGRATION, - plugins.DEXTR_SEGMENTATION] = values; - dispatch(pluginActions.checkedAllPlugins(plugins)); - } catch (error) { - dispatch(pluginActions.raisePluginCheckError(error)); - } + const values = await Promise.all(promises); + [plugins.ANALYTICS, plugins.GIT_INTEGRATION, + plugins.DEXTR_SEGMENTATION] = values; + dispatch(pluginActions.checkedAllPlugins(plugins)); }; } diff --git a/cvat-ui/src/components/cvat-app.tsx b/cvat-ui/src/components/cvat-app.tsx index 3417b4b4..8b732270 100644 --- a/cvat-ui/src/components/cvat-app.tsx +++ b/cvat-ui/src/components/cvat-app.tsx @@ -34,6 +34,7 @@ interface CVATAppProps { verifyAuthorized: () => void; loadUserAgreements: () => void; initPlugins: () => void; + initModels: () => void; resetErrors: () => void; resetMessages: () => void; switchShortcutsDialog: () => void; @@ -44,6 +45,8 @@ interface CVATAppProps { userFetching: boolean; pluginsInitialized: boolean; pluginsFetching: boolean; + modelsInitialized: boolean; + modelsFetching: boolean; formatsInitialized: boolean; formatsFetching: boolean; usersInitialized: boolean; @@ -88,6 +91,7 @@ class CVATApplication extends React.PureComponent - {!modelsInitialized - && } - {modelsInitialized && this.renderContent()} + { this.renderContent() } ) ); diff --git a/cvat-ui/src/components/models-page/models-page.tsx b/cvat-ui/src/components/models-page/models-page.tsx index 7c744c8d..a5606a2a 100644 --- a/cvat-ui/src/components/models-page/models-page.tsx +++ b/cvat-ui/src/components/models-page/models-page.tsx @@ -4,7 +4,6 @@ import './styles.scss'; import React from 'react'; -import Spin from 'antd/lib/spin'; import TopBarComponent from './top-bar'; import DeployedModelsList from './deployed-models-list'; @@ -13,27 +12,11 @@ import FeedbackComponent from '../feedback/feedback'; import { Model } from '../../reducers/interfaces'; interface Props { - modelsInitialized: boolean; - modelsFetching: boolean; deployedModels: Model[]; - getModels(): void; } export default function ModelsPageComponent(props: Props): JSX.Element { - const { - modelsInitialized, - modelsFetching, - deployedModels, - } = props; - - if (!modelsInitialized) { - if (!modelsFetching) { - props.getModels(); - } - return ( - - ); - } + const { deployedModels } = props; return (
diff --git a/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx b/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx index 9ec5b670..b956876c 100644 --- a/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx +++ b/cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx @@ -5,20 +5,10 @@ import { connect } from 'react-redux'; import ModelRunnerModalComponent from 'components/model-runner-modal/model-runner-modal'; -import { - Model, - CombinedState, -} from 'reducers/interfaces'; -import { - getModelsAsync, - startInferenceAsync, - modelsActions, -} from 'actions/models-actions'; - +import { Model, CombinedState } from 'reducers/interfaces'; +import { startInferenceAsync, modelsActions } from 'actions/models-actions'; interface StateToProps { - modelsFetching: boolean; - modelsInitialized: boolean; models: Model[]; activeProcesses: { [index: string]: string; @@ -33,7 +23,6 @@ interface DispatchToProps { model: Model, body: object, ): void; - getModels(): void; closeDialog(): void; } @@ -41,8 +30,6 @@ function mapStateToProps(state: CombinedState): StateToProps { const { models } = state; return { - modelsFetching: models.fetching, - modelsInitialized: models.initialized, models: models.models, activeProcesses: {}, taskInstance: models.activeRunTask, @@ -59,9 +46,6 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { ): void { dispatch(startInferenceAsync(taskInstance, model, body)); }, - getModels(): void { - dispatch(getModelsAsync()); - }, closeDialog(): void { dispatch(modelsActions.closeRunModelDialog()); }, diff --git a/cvat-ui/src/containers/models-page/models-page.tsx b/cvat-ui/src/containers/models-page/models-page.tsx index 27eb9df9..8282d41d 100644 --- a/cvat-ui/src/containers/models-page/models-page.tsx +++ b/cvat-ui/src/containers/models-page/models-page.tsx @@ -9,37 +9,19 @@ import { Model, CombinedState, } from 'reducers/interfaces'; -import { getModelsAsync } from 'actions/models-actions'; interface StateToProps { - modelsInitialized: boolean; - modelsFetching: boolean; deployedModels: Model[]; } -interface DispatchToProps { - getModels(): void; -} - function mapStateToProps(state: CombinedState): StateToProps { const { models } = state; return { - modelsInitialized: models.initialized, - modelsFetching: models.fetching, deployedModels: models.models, }; } -function mapDispatchToProps(dispatch: any): DispatchToProps { - return { - getModels(): void { - dispatch(getModelsAsync()); - }, - }; -} - export default connect( - mapStateToProps, - mapDispatchToProps, + mapStateToProps, {}, )(ModelsPageComponent); diff --git a/cvat-ui/src/index.tsx b/cvat-ui/src/index.tsx index d246dc0e..cfb1605d 100644 --- a/cvat-ui/src/index.tsx +++ b/cvat-ui/src/index.tsx @@ -22,6 +22,7 @@ import { getFormatsAsync } from 'actions/formats-actions'; import { checkPluginsAsync } from 'actions/plugins-actions'; import { getUsersAsync } from 'actions/users-actions'; import { getAboutAsync } from 'actions/about-actions'; +import { getModelsAsync } from 'actions/models-actions'; import { getUserAgreementsAsync } from 'actions/useragreements-actions'; import { shortcutsActions } from 'actions/shortcuts-actions'; import { switchSettingsDialog } from 'actions/settings-actions'; @@ -30,7 +31,6 @@ import { resetMessages, } from './actions/notification-actions'; - import { CombinedState, NotificationsState, @@ -42,6 +42,8 @@ const cvatStore = getCVATStore(); interface StateToProps { pluginsInitialized: boolean; pluginsFetching: boolean; + modelsInitialized: boolean; + modelsFetching: boolean; userInitialized: boolean; userFetching: boolean; usersInitialized: boolean; @@ -65,6 +67,7 @@ interface DispatchToProps { verifyAuthorized: () => void; loadUsers: () => void; loadAbout: () => void; + initModels: () => void; initPlugins: () => void; resetErrors: () => void; resetMessages: () => void; @@ -82,12 +85,15 @@ function mapStateToProps(state: CombinedState): StateToProps { const { about } = state; const { shortcuts } = state; const { userAgreements } = state; + const { models } = state; return { userInitialized: auth.initialized, userFetching: auth.fetching, pluginsInitialized: plugins.initialized, pluginsFetching: plugins.fetching, + modelsInitialized: models.initialized, + modelsFetching: models.fetching, usersInitialized: users.initialized, usersFetching: users.fetching, aboutInitialized: about.initialized, @@ -111,6 +117,7 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { verifyAuthorized: (): void => dispatch(authorizedAsync()), loadUserAgreements: (): void => dispatch(getUserAgreementsAsync()), initPlugins: (): void => dispatch(checkPluginsAsync()), + initModels: (): void => dispatch(getModelsAsync()), loadUsers: (): void => dispatch(getUsersAsync()), loadAbout: (): void => dispatch(getAboutAsync()), resetErrors: (): void => dispatch(resetErrors()), diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts index b7cf3cd4..72feee69 100644 --- a/cvat-ui/src/reducers/interfaces.ts +++ b/cvat-ui/src/reducers/interfaces.ts @@ -241,9 +241,6 @@ export interface NotificationsState { userAgreements: { fetching: null | ErrorState; }; - plugins: { - initializationError: null | ErrorState; - }; }; messages: { tasks: { diff --git a/cvat-ui/src/reducers/notifications-reducer.ts b/cvat-ui/src/reducers/notifications-reducer.ts index d9b39153..e4da7086 100644 --- a/cvat-ui/src/reducers/notifications-reducer.ts +++ b/cvat-ui/src/reducers/notifications-reducer.ts @@ -15,7 +15,6 @@ import { AnnotationActionTypes } from 'actions/annotation-actions'; import { NotificationsActionType } from 'actions/notification-actions'; import { BoundariesActionTypes } from 'actions/boundaries-actions'; import { UserAgreementsActionTypes } from 'actions/useragreements-actions'; -import { PluginsActionTypes } from 'actions/plugins-actions'; import { NotificationsState } from './interfaces'; @@ -88,9 +87,6 @@ const defaultState: NotificationsState = { userAgreements: { fetching: null, }, - plugins: { - initializationError: null, - }, }, messages: { tasks: { @@ -857,21 +853,6 @@ export default function (state = defaultState, action: AnyAction): Notifications }, }; } - case PluginsActionTypes.RAISE_PLUGIN_CHECK_ERROR: { - return { - ...state, - errors: { - ...state.errors, - plugins: { - ...state.errors.plugins, - initializationError: { - message: 'Could not initialize plugins state', - reason: action.payload.error.toString(), - }, - }, - }, - }; - } case NotificationsActionType.RESET_ERRORS: { return { ...state, diff --git a/cvat-ui/src/utils/plugin-checker.ts b/cvat-ui/src/utils/plugin-checker.ts index 7bb016ae..38c29575 100644 --- a/cvat-ui/src/utils/plugin-checker.ts +++ b/cvat-ui/src/utils/plugin-checker.ts @@ -18,8 +18,12 @@ class PluginChecker { return isReachable(`${serverHost}/git/repository/meta/get`, 'OPTIONS'); } case SupportedPlugins.DEXTR_SEGMENTATION: { - const list = await core.lambda.list(); - return list.map((func: any): boolean => func.id).includes('openvino.dextr'); + try { + const list = await core.lambda.list(); + return list.map((func: any): boolean => func.id).includes('openvino.dextr'); + } catch (_) { + return false; + } } case SupportedPlugins.ANALYTICS: { return isReachable(`${serverHost}/analytics/app/kibana`, 'GET'); From 181481d77f86c9a5603651a0481b0e2ebb8b3f81 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 12 Aug 2020 14:15:32 +0300 Subject: [PATCH 41/53] Bump opencv-python from 4.3.0.38 to 4.4.0.40 in /cvat/requirements (#2021) Bumps [opencv-python](https://github.com/skvark/opencv-python) from 4.3.0.38 to 4.4.0.40. - [Release notes](https://github.com/skvark/opencv-python/releases) - [Commits](https://github.com/skvark/opencv-python/commits) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- cvat/requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/requirements/base.txt b/cvat/requirements/base.txt index 33b84dfe..7a9da4d3 100644 --- a/cvat/requirements/base.txt +++ b/cvat/requirements/base.txt @@ -40,7 +40,7 @@ matplotlib==3.0.3 scikit-image==0.15.0 tensorflow==2.2.0 keras==2.4.2 -opencv-python==4.3.0.38 +opencv-python==4.4.0.40 h5py==2.10.0 imgaug==0.4.0 django-cors-headers==3.4.0 From 2fdd8d8bf53ca401169884ebe597e2c2c9536e71 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Wed, 12 Aug 2020 14:16:33 +0300 Subject: [PATCH 42/53] Fix cli (#2022) --- datumaro/datumaro/cli/contexts/project/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datumaro/datumaro/cli/contexts/project/__init__.py b/datumaro/datumaro/cli/contexts/project/__init__.py index 9731d48b..e6d5809b 100644 --- a/datumaro/datumaro/cli/contexts/project/__init__.py +++ b/datumaro/datumaro/cli/contexts/project/__init__.py @@ -465,7 +465,7 @@ def build_merge_parser(parser_ctor=argparse.ArgumentParser): """, formatter_class=MultilineFormatter) - parser.add_argument('other_project', + parser.add_argument('other_project_dir', help="Path to a project") parser.add_argument('-o', '--output-dir', dest='dst_dir', default=None, help="Output directory (default: current project's dir)") From b9f47fd3200485f05476a4be95ef877f837652fe Mon Sep 17 00:00:00 2001 From: Dmitry Kruchinin <33020454+dvkruchinin@users.noreply.github.com> Date: Wed, 12 Aug 2020 15:35:32 +0300 Subject: [PATCH 43/53] Cypress test for issue 1919 (#2013) * Cypress test for issue 1919 * Increase value of "defaultCommandTimeout" to 10000ms * Appying comments. Co-authored-by: Dmitry Kruchinin --- tests/cypress.json | 1 + .../integration/issue_1919_check_text_attr.js | 55 +++++++++++++++++++ tests/cypress/support/commands.js | 18 ++++++ 3 files changed, 74 insertions(+) create mode 100644 tests/cypress/integration/issue_1919_check_text_attr.js diff --git a/tests/cypress.json b/tests/cypress.json index 4f32312d..51422aa1 100644 --- a/tests/cypress.json +++ b/tests/cypress.json @@ -3,6 +3,7 @@ "baseUrl": "http://localhost:8080", "viewportWidth": 1300, "viewportHeight": 960, + "defaultCommandTimeout": 10000, "testFiles": [ "auth_page.js", "issue_*.js" diff --git a/tests/cypress/integration/issue_1919_check_text_attr.js b/tests/cypress/integration/issue_1919_check_text_attr.js new file mode 100644 index 00000000..ea6fca77 --- /dev/null +++ b/tests/cypress/integration/issue_1919_check_text_attr.js @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + */ + +/// + +context('Check label attribute changes', () => { + + const issueId = '1919' + const labelName = `Issue ${issueId}` + const taskName = `New annotation task for ${labelName}` + const attrName = `Attr for ${labelName}` + const textDefaultValue = 'Some default value for type Text' + const image = `image_${issueId}.png` + const newLabelAttrValue = 'New attribute value' + const width = 800 + const height = 800 + const posX = 10 + const posY = 10 + const color = 'gray' + + before(() => { + cy.visit('auth/login') + cy.login() + cy.imageGenerator('cypress/fixtures', image, width, height, color, posX, posY, labelName) + cy.createAnnotationTask(taskName, labelName, attrName, textDefaultValue, image) + cy.openTaskJob(taskName) + cy.createShape(309, 431, 616, 671) + }) + + describe(`Testing issue "${issueId}"`, () => { + it('Open object menu', () => { + cy.get('#cvat_canvas_shape_1').trigger('mousemove').rightclick() + }) + it('Open object menu details', () => { + cy.get('.cvat-canvas-context-menu') + .contains('Details') + .click() + }) + it('Clear field of text attribute and write new value', () => { + cy.get('.cvat-canvas-context-menu') + .find('.cvat-object-item-text-attribute') + .should('have.value', textDefaultValue) + .clear() + .type(newLabelAttrValue) + }) + it('Check what value of right panel is changed too', () => { + cy.get('#cvat-objects-sidebar-state-item-1') + .find('.cvat-object-item-text-attribute') + .should('have.value', newLabelAttrValue) + }) + }) +}) diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js index 1601e60b..d8c338c8 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.js @@ -12,6 +12,7 @@ require('../plugins/imageGenerator/imageGeneratorCommand') Cypress.Commands.add('login', (username='admin', password='12qwaszx') => { cy.get('[placeholder="Username"]').type(username) cy.get('[placeholder="Password"]').type(password) + cy.get('[type="submit"]').click() }) Cypress.Commands.add('createAnnotationTask', (taksName='New annotation task', @@ -37,6 +38,23 @@ Cypress.Commands.add('createAnnotationTask', (taksName='New annotation task', cy.url().should('include', '/tasks?page=') }) +Cypress.Commands.add('openTask', (taskName) => { + cy.contains('strong', taskName) + .parents('.cvat-tasks-list-item') + .contains('a', 'Open') + .click() +}) + +Cypress.Commands.add('openJob', () => { + cy.contains('a', 'Job #').click() + cy.url().should('include', '/jobs') +}) + +Cypress.Commands.add('openTaskJob', (taskName) => { + cy.openTask(taskName) + cy.openJob() +}) + Cypress.Commands.add('createShape', (ferstX, ferstY, lastX, lastY) => { cy.get(':nth-child(8) > svg').trigger('mousemove').click() cy.get(':nth-child(6) > :nth-child(1) > .ant-btn').click() From 0856be00e97370a9a102c3b0f505b5e39f821e86 Mon Sep 17 00:00:00 2001 From: Dmitry Kruchinin <33020454+dvkruchinin@users.noreply.github.com> Date: Wed, 12 Aug 2020 15:37:56 +0300 Subject: [PATCH 44/53] Cypress test for issue 1870 (#2016) * Cypress test for issue 1870 * Applying comments. Refactoring the test code. Co-authored-by: Dmitry Kruchinin --- .../issue_1870_cursor_not_jump_to_end.js | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/cypress/integration/issue_1870_cursor_not_jump_to_end.js diff --git a/tests/cypress/integration/issue_1870_cursor_not_jump_to_end.js b/tests/cypress/integration/issue_1870_cursor_not_jump_to_end.js new file mode 100644 index 00000000..e44ea21c --- /dev/null +++ b/tests/cypress/integration/issue_1870_cursor_not_jump_to_end.js @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + */ + +/// + +context('Checks that the cursor doesn\'t automatically jump to the end of a word when the attribute value changes', () => { + + const issueId = '1870' + const labelName = `Issue ${issueId}` + const taskName = `New annotation task for ${labelName}` + const attrName = `Attr for ${labelName}` + const textDefaultValue = 'text' + const image = `image_${issueId}.png` + const newLabelAttrValue = 'teeext' + const width = 800 + const height = 800 + const posX=10 + const posY=10 + const color='gray' + + before(() => { + cy.visit('auth/login') + cy.login() + cy.imageGenerator('cypress/fixtures', image, width, height, color, posX, posY, labelName) + cy.createAnnotationTask(taskName, labelName, attrName, textDefaultValue, image) + cy.openTaskJob(taskName) + cy.createShape(309, 431, 616, 671) + }) + + describe(`Testing issue "${issueId}"`, () => { + it('Enter 2 characters in the middle of the word attribute value and check the result', () => { + cy.get('#cvat-objects-sidebar-state-item-1') + .find('.ant-collapse-item') + .click() + .find('.cvat-object-item-text-attribute') + .type('{leftarrow}{leftarrow}ee') + .should('have.value', newLabelAttrValue) + }) + }) +}) From d66449241a3507e1586e456703f6a8338d60c59e Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Thu, 13 Aug 2020 10:50:03 +0300 Subject: [PATCH 45/53] Batch of fixes for Safari (#2025) * Styles fixes * Fixed imageBitmap & styles on annotation page * Increased version of cvat-data --- cvat-data/package-lock.json | 2 +- cvat-data/package.json | 2 +- cvat-data/src/js/cvat-data.js | 21 ++++++++++++++++++- cvat-data/src/js/unzip_imgs.worker.js | 15 ++++++++++--- .../annotation-page/annotation-page.tsx | 6 +++--- .../standard-workspace/styles.scss | 2 +- .../components/create-task-page/styles.scss | 5 +++-- cvat-ui/src/components/cvat-app.tsx | 2 +- cvat-ui/src/components/feedback/styles.scss | 3 ++- .../models-page/deployed-models-list.tsx | 4 ++-- .../src/components/models-page/styles.scss | 4 +++- .../src/components/models-page/top-bar.tsx | 2 +- cvat-ui/src/components/task-page/styles.scss | 4 +++- cvat-ui/src/components/tasks-page/styles.scss | 3 +++ 14 files changed, 56 insertions(+), 19 deletions(-) diff --git a/cvat-data/package-lock.json b/cvat-data/package-lock.json index 4a96cca3..f392ce8e 100644 --- a/cvat-data/package-lock.json +++ b/cvat-data/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-data", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-data/package.json b/cvat-data/package.json index eb78de78..5c42155e 100644 --- a/cvat-data/package.json +++ b/cvat-data/package.json @@ -1,6 +1,6 @@ { "name": "cvat-data", - "version": "1.0.0", + "version": "1.0.1", "description": "", "main": "src/js/cvat-data.js", "devDependencies": { diff --git a/cvat-data/src/js/cvat-data.js b/cvat-data/src/js/cvat-data.js index 8484e9ac..86a0a6d0 100644 --- a/cvat-data/src/js/cvat-data.js +++ b/cvat-data/src/js/cvat-data.js @@ -295,7 +295,26 @@ class FrameProvider { worker.terminate(); }; - worker.onmessage = (event) => { + worker.onmessage = async (event) => { + if (event.data.isRaw) { + // safary doesn't support createImageBitmap + // there is a way to polyfill it with using document.createElement + // but document.createElement doesn't work in worker + // so, we get raw data and decode it here, no other way + + const createImageBitmap = async function(blob) { + return new Promise((resolve,reject) => { + let img = document.createElement('img'); + img.addEventListener('load', function() { + resolve(this); + }); + img.src = URL.createObjectURL(blob); + }); + }; + + event.data.data = await createImageBitmap(event.data.data); + } + this._frames[event.data.index] = event.data.data; if (this._decodingBlocks[`${start}:${end}`].resolveCallback) { diff --git a/cvat-data/src/js/unzip_imgs.worker.js b/cvat-data/src/js/unzip_imgs.worker.js index f704e098..68d0b2a5 100644 --- a/cvat-data/src/js/unzip_imgs.worker.js +++ b/cvat-data/src/js/unzip_imgs.worker.js @@ -20,13 +20,22 @@ onmessage = (e) => { const fileIndex = index++; if (fileIndex <= end) { _zip.file(relativePath).async('blob').then((fileData) => { - createImageBitmap(fileData).then((img) => { + if (self.createImageBitmap) { + createImageBitmap(fileData).then((img) => { + postMessage({ + fileName: relativePath, + index: fileIndex, + data: img, + }); + }); + } else { postMessage({ fileName: relativePath, index: fileIndex, - data: img, + data: fileData, + isRaw: true, }); - }); + } }); } }); diff --git a/cvat-ui/src/components/annotation-page/annotation-page.tsx b/cvat-ui/src/components/annotation-page/annotation-page.tsx index 8854dd5d..d98d4284 100644 --- a/cvat-ui/src/components/annotation-page/annotation-page.tsx +++ b/cvat-ui/src/components/annotation-page/annotation-page.tsx @@ -80,17 +80,17 @@ export default function AnnotationPageComponent(props: Props): JSX.Element { { workspace === Workspace.STANDARD && ( - + )} { workspace === Workspace.ATTRIBUTE_ANNOTATION && ( - + )} { workspace === Workspace.TAG_ANNOTATION && ( - + )} diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss b/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss index c729d259..a9514add 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss +++ b/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss @@ -98,7 +98,7 @@ padding: 10px; border-radius: 5px; background: $background-color-2; - width: 250px; + width: 270px; > div { margin-top: 5px; diff --git a/cvat-ui/src/components/create-task-page/styles.scss b/cvat-ui/src/components/create-task-page/styles.scss index ccf664b2..a9b03632 100644 --- a/cvat-ui/src/components/create-task-page/styles.scss +++ b/cvat-ui/src/components/create-task-page/styles.scss @@ -8,8 +8,9 @@ text-align: center; padding-top: 40px; overflow-y: auto; - height: 100%; - padding-bottom: 40px; + height: 90%; + position: fixed; + width: 100%; > div > span { font-size: 36px; diff --git a/cvat-ui/src/components/cvat-app.tsx b/cvat-ui/src/components/cvat-app.tsx index 8b732270..50d7ce04 100644 --- a/cvat-ui/src/components/cvat-app.tsx +++ b/cvat-ui/src/components/cvat-app.tsx @@ -273,7 +273,7 @@ class CVATApplication extends React.PureComponent - + diff --git a/cvat-ui/src/components/feedback/styles.scss b/cvat-ui/src/components/feedback/styles.scss index 88495873..39415886 100644 --- a/cvat-ui/src/components/feedback/styles.scss +++ b/cvat-ui/src/components/feedback/styles.scss @@ -3,10 +3,11 @@ // SPDX-License-Identifier: MIT .cvat-feedback-button { - position: absolute; + position: fixed; bottom: 20px; right: 20px; padding: 0; + height: auto; > i { font-size: 40px; diff --git a/cvat-ui/src/components/models-page/deployed-models-list.tsx b/cvat-ui/src/components/models-page/deployed-models-list.tsx index c9d9ec6e..93e301be 100644 --- a/cvat-ui/src/components/models-page/deployed-models-list.tsx +++ b/cvat-ui/src/components/models-page/deployed-models-list.tsx @@ -35,10 +35,10 @@ export default function DeployedModelsListComponent(props: Props): JSX.Element { Type - + Description - + Labels diff --git a/cvat-ui/src/components/models-page/styles.scss b/cvat-ui/src/components/models-page/styles.scss index f566e92f..ddcaef8a 100644 --- a/cvat-ui/src/components/models-page/styles.scss +++ b/cvat-ui/src/components/models-page/styles.scss @@ -6,8 +6,10 @@ .cvat-models-page { padding-top: 30px; - height: 100%; + height: 90%; overflow: auto; + position: fixed; + width: 100%; > div:nth-child(1) { margin-bottom: 10px; diff --git a/cvat-ui/src/components/models-page/top-bar.tsx b/cvat-ui/src/components/models-page/top-bar.tsx index 584fa83c..d0ede583 100644 --- a/cvat-ui/src/components/models-page/top-bar.tsx +++ b/cvat-ui/src/components/models-page/top-bar.tsx @@ -9,7 +9,7 @@ import Text from 'antd/lib/typography/Text'; export default function TopBarComponent(): JSX.Element { return ( - + Models diff --git a/cvat-ui/src/components/task-page/styles.scss b/cvat-ui/src/components/task-page/styles.scss index b13a2c44..fd218c50 100644 --- a/cvat-ui/src/components/task-page/styles.scss +++ b/cvat-ui/src/components/task-page/styles.scss @@ -6,7 +6,9 @@ .cvat-task-details-wrapper { overflow-y: auto; - height: 100%; + height: 90%; + width: 100%; + position: fixed; .cvat-task-details { width: 100%; diff --git a/cvat-ui/src/components/tasks-page/styles.scss b/cvat-ui/src/components/tasks-page/styles.scss index a5a88ca5..623b7633 100644 --- a/cvat-ui/src/components/tasks-page/styles.scss +++ b/cvat-ui/src/components/tasks-page/styles.scss @@ -6,7 +6,10 @@ .cvat-tasks-page { padding-top: 15px; + padding-bottom: 40px; height: 100%; + position: fixed; + width: 100%; > div:nth-child(1) { padding-bottom: 10px; From 8f323cfd5c579473e24818e004708dfbdfed829b Mon Sep 17 00:00:00 2001 From: Dmitry Kruchinin <33020454+dvkruchinin@users.noreply.github.com> Date: Thu, 13 Aug 2020 11:13:13 +0300 Subject: [PATCH 46/53] Cypress test for issue 1429 (#2017) * Cypress test for issue 1429 * Rebase. Code refactoring. Co-authored-by: Dmitry Kruchinin --- .../integration/issue_1429_check_new_label.js | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 tests/cypress/integration/issue_1429_check_new_label.js diff --git a/tests/cypress/integration/issue_1429_check_new_label.js b/tests/cypress/integration/issue_1429_check_new_label.js new file mode 100644 index 00000000..955103a3 --- /dev/null +++ b/tests/cypress/integration/issue_1429_check_new_label.js @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + */ + +/// + +context('Check if the new label reflects in the options', () => { + + const issueId = '1429' + const labelName = `Issue ${issueId}` + const taskName = `New annotation task for ${labelName}` + const attrName = `Attr for ${labelName}` + const textDefaultValue = 'Some default value for type Text' + const image = `image_${issueId}.png` + const newLabelName = `New ${labelName}` + const width = 800 + const height = 800 + const posX = 10 + const posY = 10 + const color = 'gray' + + before(() => { + cy.visit('auth/login') + cy.login() + cy.imageGenerator('cypress/fixtures', image, width, height, color, posX, posY, labelName) + cy.createAnnotationTask(taskName, labelName, attrName, textDefaultValue, image) + }) + + describe(`Testing issue "${issueId}"`, () => { + it('Open a task. Open a job', () => { + cy.openTaskJob(taskName) + }) + it('Return to task page using browser button "previous page"', () => { + cy.go('back') + cy.url().should('include', '/tasks').and('not.contain', '/jobs') + }) + it('Add new label', () => { + cy.contains('button', 'Add label').click() + cy.get('[placeholder="Label name"]').type(newLabelName) + cy.contains('button', 'Done').click() + }) + it('Open the job again', () => { + cy.openJob() + }) + it('Create a shape', () => { + cy.createShape(309, 431, 616, 671) + }) + it('Checking for the new label', () => { + cy.get('#cvat-objects-sidebar-state-item-1') + .find('.ant-select-selection') + .click() + cy.get('.ant-select-dropdown-menu-item') + .should('contain', newLabelName) + }) + }) +}) From cf465b51eb5f5b13beeb22fce99ca2652070f2ce Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Sun, 16 Aug 2020 20:01:26 +0300 Subject: [PATCH 47/53] Added html meta description for cvat.org (#2035) * Added html meta description for cvat.org * Update index.html Changed tabs to spaces --- cvat-ui/src/index.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cvat-ui/src/index.html b/cvat-ui/src/index.html index b115e93b..5a7b61a0 100644 --- a/cvat-ui/src/index.html +++ b/cvat-ui/src/index.html @@ -8,8 +8,10 @@ - + + + Computer Vision Annotation Tool From e8c44bc8e2c2f74cb2fa21dd99e305008b813a32 Mon Sep 17 00:00:00 2001 From: Dmitry Kruchinin <33020454+dvkruchinin@users.noreply.github.com> Date: Sun, 16 Aug 2020 20:03:40 +0300 Subject: [PATCH 48/53] Cypress test for issue 1439 (#2028) Co-authored-by: Dmitry Kruchinin --- .../issue_1439_blocked_object_info.js | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/cypress/integration/issue_1439_blocked_object_info.js diff --git a/tests/cypress/integration/issue_1439_blocked_object_info.js b/tests/cypress/integration/issue_1439_blocked_object_info.js new file mode 100644 index 00000000..a729f78c --- /dev/null +++ b/tests/cypress/integration/issue_1439_blocked_object_info.js @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + */ + +/// + +context('Information about a blocked object disappears if hover the cursor over another object', () => { + + const issueId = '1439' + const labelName = `Issue ${issueId}` + const taskName = `New annotation task for ${labelName}` + const attrName = `Attr for ${labelName}` + const textDefaultValue = 'Some default value for type Text' + const image = `image_${issueId}.png` + const width = 800 + const height = 800 + const posX = 10 + const posY = 10 + const color = 'gray' + + before(() => { + cy.visit('auth/login') + cy.login() + cy.imageGenerator('cypress/fixtures', image, width, height, color, posX, posY, labelName) + cy.createAnnotationTask(taskName, labelName, attrName, textDefaultValue, image) + cy.openTaskJob(taskName) + }) + + describe(`Testing issue "${issueId}"`, () => { + it('Create multiple objects', () => { + cy.createShape(309, 431, 409, 531) + cy.createShape(200, 300, 300, 400) + }) + it('Lock all objects', () => { + cy.get('.cvat-objects-sidebar-states-header') + .find('.anticon-unlock') + .click() + }) + it('Mousemove to 1st object', () => { + cy.get('#cvat_canvas_shape_1').trigger('mousemove') + }) + it('Mousemove to 2nd object', () => { + cy.get('#cvat_canvas_shape_2').trigger('mousemove') + }) + it('Information about 1st object not exist', () => { + cy.get('#cvat_canvas_text_content') + .contains(`${labelName} 1`) + .should('not.exist') + }) + }) +}) From 90cc36eb1c47123cfafcd91ae32eb8634fd30bd0 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 17 Aug 2020 10:34:44 +0300 Subject: [PATCH 49/53] More classes to cypress testing (#2038) --- .../attribute-switcher.tsx | 2 +- .../object-switcher.tsx | 2 +- .../attribute-annotation-workspace/styles.scss | 3 ++- .../controls-side-bar/draw-cuboid-control.tsx | 1 + .../controls-side-bar/draw-points-control.tsx | 1 + .../controls-side-bar/draw-polygon-control.tsx | 1 + .../controls-side-bar/draw-polyline-control.tsx | 1 + .../controls-side-bar/draw-rectangle-control.tsx | 1 + .../annotation-page/top-bar/player-buttons.tsx | 14 ++++++++------ 9 files changed, 17 insertions(+), 9 deletions(-) diff --git a/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-switcher.tsx b/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-switcher.tsx index 23675d0b..66357b2f 100644 --- a/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-switcher.tsx +++ b/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-switcher.tsx @@ -27,7 +27,7 @@ function AttributeSwitcher(props: Props): JSX.Element { const title = `${currentAttribute} [${currentIndex + 1}/${attributesCount}]`; return ( -
+