From a6577856845c8eb90200fa241fda5dd374efb744 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 7 Jun 2022 13:58:03 -0400 Subject: [PATCH 001/108] Allow gates draggable --- example/script.js | 2 +- src/circuit.ts | 8 +- src/editable.ts | 302 ++++++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 4 +- src/sqore.ts | 23 ++-- 5 files changed, 323 insertions(+), 16 deletions(-) create mode 100644 src/editable.ts diff --git a/example/script.js b/example/script.js index f6d62df9..ae8c42c3 100644 --- a/example/script.js +++ b/example/script.js @@ -12,7 +12,7 @@ if (typeof qviz != 'undefined') { const sampleDiv = document.getElementById('sample'); if (sampleDiv != null) { - qviz.draw(sample, sampleDiv, qviz.STYLES['Default']); + qviz.draw(sample, sampleDiv, qviz.STYLES['Default'], 0, true); } const teleportDiv = document.getElementById('teleport'); diff --git a/src/circuit.ts b/src/circuit.ts index 685215e3..2163c8e5 100644 --- a/src/circuit.ts +++ b/src/circuit.ts @@ -54,13 +54,13 @@ export interface Operation { /** Nested operations within this operation. */ children?: Operation[]; /** Whether gate is a measurement operation. */ - isMeasurement: boolean; + isMeasurement?: boolean; /** Whether gate is a conditional operation. */ - isConditional: boolean; + isConditional?: boolean; /** Whether gate is a controlled operation. */ - isControlled: boolean; + isControlled?: boolean; /** Whether gate is an adjoint operation. */ - isAdjoint: boolean; + isAdjoint?: boolean; /** Control registers the gate acts on. */ controls?: Register[]; /** Target registers the gate acts on. */ diff --git a/src/editable.ts b/src/editable.ts new file mode 100644 index 00000000..5f56f04d --- /dev/null +++ b/src/editable.ts @@ -0,0 +1,302 @@ +import { Operation } from './circuit'; +import { leftPadding } from './constants'; +import { box } from './formatters/formatUtils'; +import { Sqore } from './sqore'; + +interface Context { + container: HTMLElement; + operations: Operation[]; + wires: Wires; + renderFn: () => void; +} + +interface Wires { + [y: string]: string; +} + +let _sourceTarget: SVGElement | null; + +const addEditable = (container: HTMLElement, sqore: Sqore): void => { + const context: Context = { + container: container, + operations: sqore.circuit.operations, + wires: getWireElemsY(container), + renderFn: () => sqore.draw(container, 0, true), + }; + addCustomStyles(container); + addDropzones(container); + addDocumentEvents(container); + addDropzoneEvents(context); + addMouseEvents(context); +}; + +// Commands + +const addCustomStyles = (container: HTMLElement) => { + const style = container.querySelector<HTMLStyleElement>('style'); + if (style) { + style.innerHTML += ` + .dropzone { + fill: transparent; + stroke: transparent; + } + .dropzone:hover{ + fill: red; + opacity: 25%; + } + text { + user-select: none; + } + .copying { + cursor: copy; + } + .moving { + cursor: move; + } + .detail-panel { + display: flex; + align-content: center; + gap: 12px; + } + `; + } +}; + +const addDropzones = (container: HTMLElement) => { + const gateElems = getGateElems(container); + gateElems.forEach((gateElem) => { + const { x, y, width, height } = gateElem.getBBox({ stroke: true }); + const dataId = getDataId(gateElem); + gateElem.append(createLeftDropzone(x, y, height, dataId)); + gateElem.append(createRightDropzone(x, y, width, height, dataId)); + }); +}; + +const addDocumentEvents = (container: HTMLElement) => { + container.addEventListener('click', (ev: MouseEvent) => { + _sourceTarget = null; + if (ev.ctrlKey) return; + }); + container.addEventListener('contextmenu', (ev: MouseEvent) => { + ev.preventDefault(); + }); + container.addEventListener('mouseup', () => { + cursorCopy(container, false); + cursorMove(container, false); + }); +}; + +const addDropzoneEvents = (context: Context) => { + const { container } = context; + const dropzoneElems = container.querySelectorAll<SVGRectElement>('.dropzone'); + dropzoneElems.forEach((dropzoneElem) => { + dropzoneElem.addEventListener('mouseup', (ev: MouseEvent) => handleDropzoneMouseUp(ev, context)); + }); +}; + +const addMouseEvents = (context: Context) => { + const { container } = context; + const gateElems = getGateElems(container); + gateElems.forEach((gateElem) => { + gateElem.addEventListener('mousedown', (ev: MouseEvent) => handleGateMouseDown(ev, container)); + }); +}; + +// Event handlers +const handleGateMouseDown = (ev: MouseEvent, container: HTMLElement) => { + ev.stopPropagation(); + _sourceTarget = ev.currentTarget as SVGGElement; + + // Ctrl + Mousedown to copy. Mousedown only to move. + ev.ctrlKey ? cursorCopy(container, true) : cursorMove(container, true); +}; + +const handleDropzoneMouseUp = (ev: MouseEvent, context: Context) => { + ev.stopPropagation(); + + const { container, operations, wires, renderFn } = context; + + const currentTarget = ev.currentTarget as SVGGElement; + + if (!currentTarget) return false; + + const dataId = getDataId(currentTarget); + const parent = getParent(dataId, operations); + const index = splitDataId(dataId).pop(); + const position = getDropzonePosition(currentTarget); + + if (_sourceTarget == null) return false; + + const sourceDataId = getDataId(_sourceTarget); + const sourceParent = getParent(sourceDataId, operations); + const sourceIndex = splitDataId(sourceDataId).pop(); + + if (index == null || sourceIndex == null) return false; + + const newGate = getGate(sourceDataId, operations); + const wireY = getClosestWireY(ev.offsetY, wires); + + // Not allow Measure gate to move vertically + if (wireY != null && newGate.gate !== 'measure') { + console.log(wires[wireY]); + // wires[wireY] returns qubit name (i.e: 'q0') + // this remove 'q' and assign an index (i.e: 0) + const index = Number(wires[wireY].slice(1)); + const [firstTarget, ...targetsExceptFirst] = newGate.targets; + // Reserve all other properties, only change qId + Object.assign(firstTarget, { ...firstTarget, qId: index }); + // Reserve all other targets, only change first target + Object.assign(newGate, { ...newGate, targets: [firstTarget, ...targetsExceptFirst] }); + } + + // Remove source element if moving using Ctrl + Mousedown + if (!ev.ctrlKey) { + deleteAt(sourceParent, sourceIndex); + } + + // If dropzone is left of gate, insert before gate. + // Otherwise, insert after. + if (position === 'left') { + insertBefore(parent, index, newGate); + } else { + insertAfter(parent, index, newGate); + } + + // Remove cursor styles + cursorCopy(container, false); + cursorMove(container, false); + + // Redraw the circuit + renderFn(); +}; + +// Element getters + +const getGateElems = (container: HTMLElement): SVGGElement[] => { + return Array.from(container.querySelectorAll('g.gate')); +}; + +const getWireElems = (container: HTMLElement) => { + // elems include qubit wires and lines of measure gates + const elems = container.querySelectorAll<SVGGElement>('svg > g:nth-child(3) > g'); + // filter out <g> elements having more than 2 elements because + // qubit wires contain only 2 elements: <line> and <text> + // lines of measure gates contain 4 <line> elements + return Array.from(elems).filter((elem) => elem.childElementCount < 3); +}; + +// Element creators + +const createDropzone = ( + x: number, + y: number, + width: number, + height: number, + dataId: string, + position: 'left' | 'right', +): SVGElement => { + const dropzone = box(x, y, width, height, `dropzone`); + dropzone.setAttribute('data-id', dataId); + dropzone.setAttribute('data-dropzone-position', position); + return dropzone; +}; + +const createLeftDropzone = (x: number, y: number, height: number, dataId: string): SVGElement => { + return createDropzone(x - leftPadding / 2, y, leftPadding / 2, height, dataId, 'left'); +}; +const createRightDropzone = (x: number, y: number, width: number, height: number, dataId: string): SVGElement => { + return createDropzone(x + width, y, leftPadding / 2, height, dataId, 'right'); +}; + +// Operation getters + +const getParent = (dataId: string, operations: Operation[]): Operation[] => { + const segments = splitDataId(dataId); + // Remove last segment to navigate to parent instead of child + segments.pop(); + + let parent = operations; + for (const segment of segments) { + parent = parent[segment].children || parent; + } + return parent; +}; + +const getGate = (dataId: string, operations: Operation[]): Operation => { + const parent = getParent(dataId, operations); + const index = splitDataId(dataId).pop(); + + if (index == null) { + throw new Error('Gate not found'); + } + + return parent[index]; +}; + +// Utilities +const getDataId = (element: Element): string => { + return element.getAttribute('data-id') || ''; +}; + +const splitDataId = (dataId: string): number[] => { + return dataId.split('-').map(Number); +}; + +const getWireElemsY = (container: HTMLElement): Wires => { + const wireElems = getWireElems(container); + return wireElems.reduce((previous, current) => { + const y = getWireElemY(current); + const text = getWireElemText(current); + return { ...previous, [`${y}`]: text }; + }, {}); +}; + +const getWireElemY = (wireElem: SVGGElement): number => { + const lineElem = wireElem.querySelector<SVGLineElement>('line'); + if (lineElem == null || lineElem.y1.baseVal.value == null) throw Error('y not found'); + return lineElem.y1.baseVal.value; +}; +const getWireElemText = (wireElem: SVGGElement): string => { + const textElem = wireElem.querySelector<SVGTextElement>('text'); + if (textElem == null || textElem.textContent == null) throw new Error('Text not found'); + return textElem.textContent; +}; + +const getClosestWireY = (offsetY: number, wires: { [y: number]: string }) => { + let wireY; + Object.entries(wires).forEach((wire) => { + const y = wire[0]; + const distance = Math.abs(offsetY - Number(y)); + // 15 is a magic number + if (distance < 15) { + wireY = y; + } + }); + return wireY || null; +}; + +const getDropzonePosition = (element: SVGElement) => { + return element.getAttribute('data-dropzone-position'); +}; + +const insertBefore = (parent: Operation[], index: number, newGate: Operation): void => { + parent.splice(index, 0, newGate); +}; + +const insertAfter = (parent: Operation[], index: number, newGate: Operation): void => { + parent.splice(index + 1, 0, newGate); +}; + +const deleteAt = (parent: Operation[], index: number): void => { + parent.splice(index, 1); +}; + +const cursorMove = (container: HTMLElement, value: boolean) => { + value ? container.classList.add('moving') : container.classList.remove('moving'); +}; + +const cursorCopy = (container: HTMLElement, value: boolean) => { + value ? container.classList.add('copying') : container.classList.remove('copying'); +}; + +export { addEditable }; diff --git a/src/index.ts b/src/index.ts index 0a040268..8a9093bc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,9 +18,11 @@ export const draw = ( container: HTMLElement, style: StyleConfig | string = {}, renderDepth = 0, + editable = false, ): void => { const sqore = new Sqore(circuit, style); - sqore.draw(container, renderDepth); + + sqore.draw(container, renderDepth, editable); }; export { STYLES } from './styles'; diff --git a/src/sqore.ts b/src/sqore.ts index c20ba65c..e0d85dfc 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -10,6 +10,7 @@ import { Metadata, GateType } from './metadata'; import { StyleConfig, style, STYLES } from './styles'; import { createUUID } from './utils'; import { svgNS } from './constants'; +import { addEditable } from './editable'; /** * Contains metadata for visualization. @@ -56,7 +57,7 @@ export class Sqore { * @param container HTML element for rendering visualization into. * @param renderDepth Initial layer depth at which to render gates. */ - draw(container: HTMLElement, renderDepth = 0): void { + draw(container: HTMLElement, renderDepth = 0, editable = false): void { // Inject into container if (container == null) throw new Error(`Container not provided.`); @@ -78,8 +79,7 @@ export class Sqore { const id: string = circuit.operations[0].dataAttributes['id']; this.expandOperation(circuit.operations, id); } - - this.renderCircuit(container, circuit); + this.renderCircuit(container, circuit, editable); } /** @@ -107,13 +107,17 @@ export class Sqore { * @param container HTML element for rendering visualization into. * @param circuit Circuit object to be rendered. */ - private renderCircuit(container: HTMLElement, circuit: Circuit): void { + public renderCircuit(container: HTMLElement, circuit: Circuit, editable: boolean): void { // Create visualization components const composedSqore: ComposedSqore = this.compose(circuit); const svg: SVGElement = this.generateSvg(composedSqore); container.innerHTML = ''; container.appendChild(svg); - this.addGateClickHandlers(container, circuit); + this.addGateClickHandlers(container, circuit, editable); + + if (editable) { + addEditable(container, this); + } } /** @@ -231,9 +235,9 @@ export class Sqore { * @param circuit Circuit to be visualized. * */ - private addGateClickHandlers(container: HTMLElement, circuit: Circuit): void { + private addGateClickHandlers(container: HTMLElement, circuit: Circuit, editable: boolean): void { this.addClassicalControlHandlers(container); - this.addZoomHandlers(container, circuit); + this.addZoomHandlers(container, circuit, editable); } /** @@ -291,7 +295,7 @@ export class Sqore { * @param circuit Circuit to be visualized. * */ - private addZoomHandlers(container: HTMLElement, circuit: Circuit): void { + private addZoomHandlers(container: HTMLElement, circuit: Circuit, editable: boolean): void { container.querySelectorAll('.gate .gate-control').forEach((ctrl) => { // Zoom in on clicked gate ctrl.addEventListener('click', (ev: Event) => { @@ -302,8 +306,7 @@ export class Sqore { } else if (ctrl.classList.contains('gate-expand')) { this.expandOperation(circuit.operations, gateId); } - this.renderCircuit(container, circuit); - + this.renderCircuit(container, circuit, editable); ev.stopPropagation(); } }); From 9a66bc84a6e4b5854bc0a3da9ef77330b8285edb Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 7 Jun 2022 14:08:48 -0400 Subject: [PATCH 002/108] Add description to addEditable function --- src/editable.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/editable.ts b/src/editable.ts index 5f56f04d..68c0b340 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -16,6 +16,14 @@ interface Wires { let _sourceTarget: SVGElement | null; +/** + * Add editable elements and events. + * + * @param container HTML element for rendering visualization into. + * @param sqore Sqore object + * + */ + const addEditable = (container: HTMLElement, sqore: Sqore): void => { const context: Context = { container: container, From d831c48717d4cb063e53a595b83acd01e9f6d1d5 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 7 Jun 2022 14:09:07 -0400 Subject: [PATCH 003/108] Add return types --- src/editable.ts | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/editable.ts b/src/editable.ts index 68c0b340..9e900205 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -40,7 +40,7 @@ const addEditable = (container: HTMLElement, sqore: Sqore): void => { // Commands -const addCustomStyles = (container: HTMLElement) => { +const addCustomStyles = (container: HTMLElement): void => { const style = container.querySelector<HTMLStyleElement>('style'); if (style) { style.innerHTML += ` @@ -70,7 +70,7 @@ const addCustomStyles = (container: HTMLElement) => { } }; -const addDropzones = (container: HTMLElement) => { +const addDropzones = (container: HTMLElement): void => { const gateElems = getGateElems(container); gateElems.forEach((gateElem) => { const { x, y, width, height } = gateElem.getBBox({ stroke: true }); @@ -80,7 +80,7 @@ const addDropzones = (container: HTMLElement) => { }); }; -const addDocumentEvents = (container: HTMLElement) => { +const addDocumentEvents = (container: HTMLElement): void => { container.addEventListener('click', (ev: MouseEvent) => { _sourceTarget = null; if (ev.ctrlKey) return; @@ -94,7 +94,7 @@ const addDocumentEvents = (container: HTMLElement) => { }); }; -const addDropzoneEvents = (context: Context) => { +const addDropzoneEvents = (context: Context): void => { const { container } = context; const dropzoneElems = container.querySelectorAll<SVGRectElement>('.dropzone'); dropzoneElems.forEach((dropzoneElem) => { @@ -102,7 +102,7 @@ const addDropzoneEvents = (context: Context) => { }); }; -const addMouseEvents = (context: Context) => { +const addMouseEvents = (context: Context): void => { const { container } = context; const gateElems = getGateElems(container); gateElems.forEach((gateElem) => { @@ -111,7 +111,7 @@ const addMouseEvents = (context: Context) => { }; // Event handlers -const handleGateMouseDown = (ev: MouseEvent, container: HTMLElement) => { +const handleGateMouseDown = (ev: MouseEvent, container: HTMLElement): void => { ev.stopPropagation(); _sourceTarget = ev.currentTarget as SVGGElement; @@ -119,7 +119,7 @@ const handleGateMouseDown = (ev: MouseEvent, container: HTMLElement) => { ev.ctrlKey ? cursorCopy(container, true) : cursorMove(container, true); }; -const handleDropzoneMouseUp = (ev: MouseEvent, context: Context) => { +const handleDropzoneMouseUp = (ev: MouseEvent, context: Context): void | false => { ev.stopPropagation(); const { container, operations, wires, renderFn } = context; @@ -184,7 +184,7 @@ const getGateElems = (container: HTMLElement): SVGGElement[] => { return Array.from(container.querySelectorAll('g.gate')); }; -const getWireElems = (container: HTMLElement) => { +const getWireElems = (container: HTMLElement): SVGGElement[] => { // elems include qubit wires and lines of measure gates const elems = container.querySelectorAll<SVGGElement>('svg > g:nth-child(3) > g'); // filter out <g> elements having more than 2 elements because @@ -270,7 +270,7 @@ const getWireElemText = (wireElem: SVGGElement): string => { return textElem.textContent; }; -const getClosestWireY = (offsetY: number, wires: { [y: number]: string }) => { +const getClosestWireY = (offsetY: number, wires: { [y: number]: string }): number | null => { let wireY; Object.entries(wires).forEach((wire) => { const y = wire[0]; @@ -283,8 +283,10 @@ const getClosestWireY = (offsetY: number, wires: { [y: number]: string }) => { return wireY || null; }; -const getDropzonePosition = (element: SVGElement) => { - return element.getAttribute('data-dropzone-position'); +const getDropzonePosition = (element: SVGElement): string => { + const position = element.getAttribute('data-dropzone-position'); + if (position == null) throw new Error('Position not found'); + return position; }; const insertBefore = (parent: Operation[], index: number, newGate: Operation): void => { @@ -299,11 +301,11 @@ const deleteAt = (parent: Operation[], index: number): void => { parent.splice(index, 1); }; -const cursorMove = (container: HTMLElement, value: boolean) => { +const cursorMove = (container: HTMLElement, value: boolean): void => { value ? container.classList.add('moving') : container.classList.remove('moving'); }; -const cursorCopy = (container: HTMLElement, value: boolean) => { +const cursorCopy = (container: HTMLElement, value: boolean): void => { value ? container.classList.add('copying') : container.classList.remove('copying'); }; From 13108145ce9b22e6b5b87b976077e075a6c0d214 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 7 Jun 2022 20:30:26 -0400 Subject: [PATCH 004/108] Add tests --- __tests__/__snapshots__/editable.test.ts.snap | 65 ++++ __tests__/editable.test.ts | 361 ++++++++++++++++++ src/editable.ts | 19 +- 3 files changed, 442 insertions(+), 3 deletions(-) create mode 100644 __tests__/__snapshots__/editable.test.ts.snap create mode 100644 __tests__/editable.test.ts diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap new file mode 100644 index 00000000..637f61b6 --- /dev/null +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -0,0 +1,65 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Testing cursorCopy turn off copy cursor 1`] = ` +<div + class="copying" +/> +`; + +exports[`Testing cursorCopy turn off copy cursor 2`] = ` +<div + class="" +/> +`; + +exports[`Testing cursorCopy turn on and off copy cursor 1`] = ` +<div + class="" +/> +`; + +exports[`Testing cursorCopy turn on and off copy cursor 2`] = ` +<div + class="" +/> +`; + +exports[`Testing cursorCopy turn on copy cursor 1`] = `<div />`; + +exports[`Testing cursorCopy turn on copy cursor 2`] = ` +<div + class="copying" +/> +`; + +exports[`Testing cursorMove turn off move cursor 1`] = ` +<div + class="moving" +/> +`; + +exports[`Testing cursorMove turn off move cursor 2`] = ` +<div + class="" +/> +`; + +exports[`Testing cursorMove turn on and off move cursor 1`] = ` +<div + class="" +/> +`; + +exports[`Testing cursorMove turn on and off move cursor 2`] = ` +<div + class="" +/> +`; + +exports[`Testing cursorMove turn on move cursor 1`] = `<div />`; + +exports[`Testing cursorMove turn on move cursor 2`] = ` +<div + class="moving" +/> +`; diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts new file mode 100644 index 00000000..34dd2be2 --- /dev/null +++ b/__tests__/editable.test.ts @@ -0,0 +1,361 @@ +import { Operation } from '../src/circuit'; +import { exportedForTesting } from '../src/editable'; +import { RegisterType } from '../src/register'; + +const { + getDataId, + splitDataId, + cursorMove, + cursorCopy, + deleteAt, + insertBefore, + insertAfter, + getDropzonePosition, + getWireElemText, +} = exportedForTesting; + +// Utlities +describe('Testing getDataId', () => { + const elem = document.createElement('div'); + test('with with no data-id', () => { + expect(getDataId(elem)).toBe(''); + }); + test('with level 0 data-id', () => { + elem.setAttribute('data-id', '0'); + expect(getDataId(elem)).toBe('0'); + }); + + test('with level 1 data-id', () => { + elem.setAttribute('data-id', '0-1'); + expect(getDataId(elem)).toBe('0-1'); + }); +}); + +describe('Testing splitDataId', () => { + test('with empty dataId', () => { + expect(splitDataId('')).toStrictEqual([]); + }); + test('with level 0 data-id', () => { + expect(splitDataId('1')).toStrictEqual([1]); + }); + + test('with level 1 data-id', () => { + expect(splitDataId('1-2')).toStrictEqual([1, 2]); + }); +}); + +describe('Testing cursorMove', () => { + const container = document.createElement('div'); + test('turn on move cursor', () => { + expect(container).toMatchSnapshot(); + cursorMove(container, true); + expect(container).toMatchSnapshot(); + }); + test('turn off move cursor', () => { + expect(container).toMatchSnapshot(); + cursorMove(container, false); + expect(container).toMatchSnapshot(); + }); + test('turn on and off move cursor', () => { + expect(container).toMatchSnapshot(); + cursorMove(container, true); + cursorMove(container, false); + expect(container).toMatchSnapshot(); + }); +}); + +describe('Testing cursorCopy', () => { + const container = document.createElement('div'); + test('turn on copy cursor', () => { + expect(container).toMatchSnapshot(); + cursorCopy(container, true); + expect(container).toMatchSnapshot(); + }); + test('turn off copy cursor', () => { + expect(container).toMatchSnapshot(); + cursorCopy(container, false); + expect(container).toMatchSnapshot(); + }); + test('turn on and off copy cursor', () => { + expect(container).toMatchSnapshot(); + cursorCopy(container, true); + cursorCopy(container, false); + expect(container).toMatchSnapshot(); + }); +}); + +describe('Testing deleteAt', () => { + const operations: Operation[] = []; + beforeEach(() => { + Object.assign(operations, [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]); + }); + test('delete X at index 0', () => { + deleteAt(operations, 0); + expect(operations).toStrictEqual([ + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]); + }); + test('delete Y at index 1', () => { + deleteAt(operations, 1); + expect(operations).toStrictEqual([ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]); + }); + test('delete Z and X at index 2, 0', () => { + deleteAt(operations, 2); + deleteAt(operations, 0); + expect(operations).toStrictEqual([ + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]); + }); +}); + +describe('Testing insertBefore', () => { + test('insert before X', () => { + const operations = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + const newGate = { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + insertBefore(operations, 0, newGate); + expect(operations).toStrictEqual([ + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]); + }); +}); + +describe('Testing insertAfter', () => { + test('insert after X', () => { + const operations = [ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]; + const newGate = { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }; + insertAfter(operations, 0, newGate); + expect(operations).toStrictEqual([ + { + gate: 'X', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Y', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + { + gate: 'Z', + isMeasurement: false, + isConditional: false, + isControlled: false, + isAdjoint: false, + controls: [], + targets: [{ type: RegisterType.Qubit, qId: 0 }], + }, + ]); + }); +}); + +describe('Testing getDropzonePosition', () => { + let svgElem: SVGElement; + let dropzoneElem: SVGElement; + beforeEach(() => { + svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg') as SVGElement; + dropzoneElem = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGElement; + svgElem.append(dropzoneElem); + }); + test('get position of non-dropzone', () => { + expect(() => getDropzonePosition(dropzoneElem)).toThrowError('Position not found'); + }); + test('get position of dropzone on the left', () => { + dropzoneElem.setAttribute('data-dropzone-position', 'left'); + expect(getDropzonePosition(dropzoneElem)).toBe('left'); + }); + test('get position of dropzone on the right', () => { + dropzoneElem.setAttribute('data-dropzone-position', 'right'); + expect(getDropzonePosition(dropzoneElem)).toBe('right'); + }); +}); + +describe('Testing getWireElementText', () => { + let svgElem: SVGElement; + let groupElem: SVGGElement; + let textElem: SVGGElement; + beforeEach(() => { + svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg') as SVGElement; + groupElem = document.createElementNS('http://www.w3.org/2000/svg', 'g') as SVGGElement; + textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text') as SVGTextElement; + groupElem.append(textElem); + svgElem.append(groupElem); + }); + test('text element not exists', () => { + textElem.remove(); + expect(() => getWireElemText(groupElem)).toThrowError('Text not found'); + }); + test('get text element without textContent', () => { + expect(() => getWireElemText(groupElem)).toThrowError('Text not found'); + }); + test('get text element empty textContent', () => { + expect(() => getWireElemText(groupElem)).toThrowError('Text not found'); + }); + test('should return q0', () => { + textElem.textContent = 'q0'; + expect(getWireElemText(groupElem)).toEqual('q0'); + }); + test('should return q1', () => { + textElem.textContent = 'q1'; + expect(getWireElemText(groupElem)).toEqual('q1'); + }); +}); diff --git a/src/editable.ts b/src/editable.ts index 9e900205..0cfa2adf 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -247,7 +247,7 @@ const getDataId = (element: Element): string => { }; const splitDataId = (dataId: string): number[] => { - return dataId.split('-').map(Number); + return dataId === '' ? [] : dataId.split('-').map(Number); }; const getWireElemsY = (container: HTMLElement): Wires => { @@ -266,7 +266,8 @@ const getWireElemY = (wireElem: SVGGElement): number => { }; const getWireElemText = (wireElem: SVGGElement): string => { const textElem = wireElem.querySelector<SVGTextElement>('text'); - if (textElem == null || textElem.textContent == null) throw new Error('Text not found'); + if (textElem == null || textElem.textContent == null || textElem.textContent === '') + throw new Error('Text not found'); return textElem.textContent; }; @@ -309,4 +310,16 @@ const cursorCopy = (container: HTMLElement, value: boolean): void => { value ? container.classList.add('copying') : container.classList.remove('copying'); }; -export { addEditable }; +const exportedForTesting = { + getDataId, + splitDataId, + cursorMove, + cursorCopy, + deleteAt, + insertBefore, + insertAfter, + getDropzonePosition, + getWireElemText, +}; + +export { addEditable, exportedForTesting }; From 7c3d7329d92f4e39d4440cd8048cade877a40fbf Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 8 Jun 2022 12:57:51 -0400 Subject: [PATCH 005/108] Revert renderCircuit to private --- src/sqore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sqore.ts b/src/sqore.ts index e0d85dfc..bfb63e98 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -107,7 +107,7 @@ export class Sqore { * @param container HTML element for rendering visualization into. * @param circuit Circuit object to be rendered. */ - public renderCircuit(container: HTMLElement, circuit: Circuit, editable: boolean): void { + private renderCircuit(container: HTMLElement, circuit: Circuit, editable: boolean): void { // Create visualization components const composedSqore: ComposedSqore = this.compose(circuit); const svg: SVGElement = this.generateSvg(composedSqore); From 2a6a82570d4d24e5adb74c8ca323de8e1c33e82c Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 8 Jun 2022 13:34:45 -0400 Subject: [PATCH 006/108] Trim trailing whitespace --- src/editable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editable.ts b/src/editable.ts index 0cfa2adf..f3a217a6 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -54,7 +54,7 @@ const addCustomStyles = (container: HTMLElement): void => { } text { user-select: none; - } + } .copying { cursor: copy; } From 623a977ec61debf8346853f880c1b0eb62ab73bd Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 8 Jun 2022 16:55:06 -0400 Subject: [PATCH 007/108] Add license --- src/editable.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/editable.ts b/src/editable.ts index f3a217a6..0b530672 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + import { Operation } from './circuit'; import { leftPadding } from './constants'; import { box } from './formatters/formatUtils'; From 6f560124d65bc2f8f1a8aa8a9bd112e68b063a25 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 8 Jun 2022 17:25:37 -0400 Subject: [PATCH 008/108] Fix + add tests to getWireElemY --- __tests__/editable.test.ts | 32 ++++++++++++++++++++++++++++++++ src/editable.ts | 6 ++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 34dd2be2..d23f7a4d 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -12,6 +12,7 @@ const { insertAfter, getDropzonePosition, getWireElemText, + getWireElemY, } = exportedForTesting; // Utlities @@ -359,3 +360,34 @@ describe('Testing getWireElementText', () => { expect(getWireElemText(groupElem)).toEqual('q1'); }); }); + +describe('Testing getWireElemY', () => { + let svgElem: SVGElement; + let groupElem: SVGGElement; + let lineElem: SVGGElement; + beforeEach(() => { + svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg') as SVGElement; + groupElem = document.createElementNS('http://www.w3.org/2000/svg', 'g') as SVGGElement; + lineElem = document.createElementNS('http://www.w3.org/2000/svg', 'line') as SVGLineElement; + groupElem.append(lineElem); + svgElem.append(groupElem); + }); + test('line element not exists', () => { + lineElem.remove(); + expect(() => getWireElemY(groupElem)).toThrowError('y not found'); + }); + test('get y element without y value', () => { + expect(() => getWireElemY(groupElem)).toThrowError('y not found'); + }); + test('get text element empty textContent', () => { + expect(() => getWireElemY(groupElem)).toThrowError('y not found'); + }); + test('should return 40', () => { + lineElem.setAttribute('y1', '40'); + expect(getWireElemY(groupElem)).toEqual(40); + }); + test('should return 99', () => { + lineElem.setAttribute('y1', '99'); + expect(getWireElemY(groupElem)).toEqual(99); + }); +}); diff --git a/src/editable.ts b/src/editable.ts index 0b530672..0a72b6e2 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -264,9 +264,10 @@ const getWireElemsY = (container: HTMLElement): Wires => { const getWireElemY = (wireElem: SVGGElement): number => { const lineElem = wireElem.querySelector<SVGLineElement>('line'); - if (lineElem == null || lineElem.y1.baseVal.value == null) throw Error('y not found'); - return lineElem.y1.baseVal.value; + if (lineElem == null || lineElem.getAttribute('y1') == null) throw Error('y not found'); + return Number(lineElem.getAttribute('y1')); }; + const getWireElemText = (wireElem: SVGGElement): string => { const textElem = wireElem.querySelector<SVGTextElement>('text'); if (textElem == null || textElem.textContent == null || textElem.textContent === '') @@ -323,6 +324,7 @@ const exportedForTesting = { insertAfter, getDropzonePosition, getWireElemText, + getWireElemY, }; export { addEditable, exportedForTesting }; From 2a06b9555bf4f5ccf55d45fed94f827000768493 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 8 Jun 2022 19:10:18 -0400 Subject: [PATCH 009/108] Add tests for getGate + getParent --- __tests__/editable.test.ts | 358 +++++++++++++++++++++++++++++++++++++ src/editable.ts | 2 + 2 files changed, 360 insertions(+) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index d23f7a4d..46b0091f 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -13,6 +13,8 @@ const { getDropzonePosition, getWireElemText, getWireElemY, + getGate, + getParent, } = exportedForTesting; // Utlities @@ -391,3 +393,359 @@ describe('Testing getWireElemY', () => { expect(getWireElemY(groupElem)).toEqual(99); }); }); + +describe('Testing getParent', () => { + test('with level 0 gate', () => { + const operations = [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ]; + expect(getParent('0', operations)).toStrictEqual([ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ]); + }); + test('with level 1 gate', () => { + const operations = [ + { + gate: 'Foo', + conditionalRender: 3, + targets: [{ qId: 0 }, { qId: 1 }], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + }, + { + gate: 'RX', + displayArgs: '(0.25)', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 0 }], + }, + ], + }, + { + gate: 'X', + targets: [{ qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 2 }, { qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }, { qId: 3 }], + targets: [{ qId: 1 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }, { qId: 3 }], + targets: [{ qId: 2 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'measure', + isMeasurement: true, + controls: [{ qId: 0 }], + targets: [{ type: 1, qId: 0, cId: 0 }], + }, + { + gate: 'ApplyIfElseR', + isConditional: true, + controls: [{ type: 1, qId: 0, cId: 0 }], + targets: [], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + conditionalRender: 2, + }, + { + gate: 'Foo', + targets: [{ qId: 3 }], + conditionalRender: 2, + }, + ], + }, + { + gate: 'SWAP', + targets: [{ qId: 0 }, { qId: 2 }], + children: [ + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + ], + }, + { + gate: 'ZZ', + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'ZZ', + targets: [{ qId: 0 }, { qId: 1 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }, { qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + ]; + expect(getParent('0-1', operations)).toStrictEqual([ + { + gate: 'H', + targets: [{ qId: 1 }], + }, + { + gate: 'RX', + displayArgs: '(0.25)', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 0 }], + }, + ]); + }); +}); + +describe('Testing getGate', () => { + test('should return H gate', () => { + const operations = [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ]; + expect(getGate('0', operations)).toStrictEqual({ + gate: 'H', + targets: [{ qId: 0 }], + }); + }); + test('should return X gate', () => { + const operations = [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ]; + expect(getGate('1', operations)).toStrictEqual({ + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }); + }); + test('should return RX', () => { + const operations = [ + { + gate: 'Foo', + conditionalRender: 3, + targets: [{ qId: 0 }, { qId: 1 }], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + }, + { + gate: 'RX', + displayArgs: '(0.25)', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 0 }], + }, + ], + }, + { + gate: 'X', + targets: [{ qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 2 }, { qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }, { qId: 3 }], + targets: [{ qId: 1 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }, { qId: 3 }], + targets: [{ qId: 2 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'measure', + isMeasurement: true, + controls: [{ qId: 0 }], + targets: [{ type: 1, qId: 0, cId: 0 }], + }, + { + gate: 'ApplyIfElseR', + isConditional: true, + controls: [{ type: 1, qId: 0, cId: 0 }], + targets: [], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + conditionalRender: 2, + }, + { + gate: 'Foo', + targets: [{ qId: 3 }], + conditionalRender: 2, + }, + ], + }, + { + gate: 'SWAP', + targets: [{ qId: 0 }, { qId: 2 }], + children: [ + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + ], + }, + { + gate: 'ZZ', + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'ZZ', + targets: [{ qId: 0 }, { qId: 1 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }, { qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + ]; + expect(getGate('0-1', operations)).toStrictEqual({ + gate: 'RX', + displayArgs: '(0.25)', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 0 }], + }); + }); +}); diff --git a/src/editable.ts b/src/editable.ts index 0a72b6e2..8a55cd4a 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -325,6 +325,8 @@ const exportedForTesting = { getDropzonePosition, getWireElemText, getWireElemY, + getGate, + getParent, }; export { addEditable, exportedForTesting }; From 3e7dd43769a57b74e529bba8dc59cc0f80d557c3 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 8 Jun 2022 19:35:35 -0400 Subject: [PATCH 010/108] Add test for addCustomStyles --- __tests__/__snapshots__/editable.test.ts.snap | 35 ++++++++++++++ __tests__/editable.test.ts | 12 +++++ src/editable.ts | 47 +++++++++---------- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 637f61b6..7be5921b 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -1,5 +1,40 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Testing addCustomStyles verify css 1`] = ` +<div> + <style /> +</div> +`; + +exports[`Testing addCustomStyles verify css 2`] = ` +<div> + <style> + .dropzone { + fill: transparent; + stroke: transparent; + } + .dropzone:hover{ + fill: red; + opacity: 25%; + } + text { + user-select: none; + } + .copying { + cursor: copy; + } + .moving { + cursor: move; + } + .detail-panel { + display: flex; + align-content: center; + gap: 12px; + } + </style> +</div> +`; + exports[`Testing cursorCopy turn off copy cursor 1`] = ` <div class="copying" diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 46b0091f..6d00da2f 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -15,6 +15,7 @@ const { getWireElemY, getGate, getParent, + addCustomStyles, } = exportedForTesting; // Utlities @@ -749,3 +750,14 @@ describe('Testing getGate', () => { }); }); }); + +describe('Testing addCustomStyles', () => { + test('verify css', () => { + const container = document.createElement('div'); + const style = document.createElement('style'); + container.append(style); + expect(container).toMatchSnapshot(); + addCustomStyles(container); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/src/editable.ts b/src/editable.ts index 8a55cd4a..bcc1d683 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -46,30 +46,28 @@ const addEditable = (container: HTMLElement, sqore: Sqore): void => { const addCustomStyles = (container: HTMLElement): void => { const style = container.querySelector<HTMLStyleElement>('style'); if (style) { - style.innerHTML += ` - .dropzone { - fill: transparent; - stroke: transparent; - } - .dropzone:hover{ - fill: red; - opacity: 25%; - } - text { - user-select: none; - } - .copying { - cursor: copy; - } - .moving { - cursor: move; - } - .detail-panel { - display: flex; - align-content: center; - gap: 12px; - } - `; + style.innerHTML += `.dropzone { + fill: transparent; + stroke: transparent; + } + .dropzone:hover{ + fill: red; + opacity: 25%; + } + text { + user-select: none; + } + .copying { + cursor: copy; + } + .moving { + cursor: move; + } + .detail-panel { + display: flex; + align-content: center; + gap: 12px; + }`; } }; @@ -327,6 +325,7 @@ const exportedForTesting = { getWireElemY, getGate, getParent, + addCustomStyles, }; export { addEditable, exportedForTesting }; From b478d567ac1e2971cdc0d38ec8ee447ba57235c6 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 8 Jun 2022 19:41:00 -0400 Subject: [PATCH 011/108] Add test for addDocumentEvents --- __tests__/__snapshots__/editable.test.ts.snap | 4 ++++ __tests__/editable.test.ts | 11 +++++++++++ src/editable.ts | 1 + 3 files changed, 16 insertions(+) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 7be5921b..9d3bfe1e 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -35,6 +35,10 @@ exports[`Testing addCustomStyles verify css 2`] = ` </div> `; +exports[`Testing addDocumentEvents verify document events 1`] = `<div />`; + +exports[`Testing addDocumentEvents verify document events 2`] = `<div />`; + exports[`Testing cursorCopy turn off copy cursor 1`] = ` <div class="copying" diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 6d00da2f..22e249a3 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -16,6 +16,7 @@ const { getGate, getParent, addCustomStyles, + addDocumentEvents, } = exportedForTesting; // Utlities @@ -761,3 +762,13 @@ describe('Testing addCustomStyles', () => { expect(container).toMatchSnapshot(); }); }); + +// Untestable +describe('Testing addDocumentEvents', () => { + test('verify document events', () => { + const container = document.createElement('div'); + expect(container).toMatchSnapshot(); + addDocumentEvents(container); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/src/editable.ts b/src/editable.ts index bcc1d683..6b5d1871 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -326,6 +326,7 @@ const exportedForTesting = { getGate, getParent, addCustomStyles, + addDocumentEvents, }; export { addEditable, exportedForTesting }; From 42fb70250ae4344d7948b2936e634ac671470fa9 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 9 Jun 2022 10:04:00 -0400 Subject: [PATCH 012/108] Add more tests --- __tests__/__snapshots__/editable.test.ts.snap | 251 ++++++++++++++++++ __tests__/editable.test.ts | 127 +++++++++ src/editable.ts | 22 +- 3 files changed, 395 insertions(+), 5 deletions(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 9d3bfe1e..0d888290 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -39,6 +39,54 @@ exports[`Testing addDocumentEvents verify document events 1`] = `<div />`; exports[`Testing addDocumentEvents verify document events 2`] = `<div />`; +exports[`Testing createDropzone create dropzone on the left 1`] = ` +<rect + class="dropzone" + data-dropzone-position="left" + data-id="0" + height="20" + width="20" + x="0" + y="0" +/> +`; + +exports[`Testing createDropzone create dropzone on the right 1`] = ` +<rect + class="dropzone" + data-dropzone-position="right" + data-id="0" + height="20" + width="20" + x="0" + y="0" +/> +`; + +exports[`Testing createLeftDropzone create left dropzone 1`] = ` +<rect + class="dropzone" + data-dropzone-position="left" + data-id="0" + height="20" + width="10" + x="-10" + y="0" +/> +`; + +exports[`Testing createRightDropzone create dropzone right 1`] = ` +<rect + class="dropzone" + data-dropzone-position="right" + data-id="0" + height="20" + width="10" + x="20" + y="0" +/> +`; + exports[`Testing cursorCopy turn off copy cursor 1`] = ` <div class="copying" @@ -102,3 +150,206 @@ exports[`Testing cursorMove turn on move cursor 2`] = ` class="moving" /> `; + +exports[`Testing getGateElems get 2 gates 1`] = ` +Array [ + <g + class="gate" + data-id="0" + data-zoom-in="false" + data-zoom-out="false" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="80" + y="20" + /> + <text + font-size="14" + x="100" + y="40" + > + H + </text> + </g> + </g> + </g>, + <g + class="gate" + data-id="1" + data-zoom-in="false" + data-zoom-out="false" + > + <g> + <rect + class="gate-measure" + height="40" + width="40" + x="80" + y="80" + /> + <path + class="arc-measure" + d="M 115 102 A 15 12 0 0 0 85 102" + /> + <line + x1="100" + x2="112" + y1="108" + y2="88" + /> + </g> + </g>, +] +`; + +exports[`Testing getGateElems get 3 gates 1`] = ` +Array [ + <g + class="gate" + data-id="0" + data-zoom-in="false" + data-zoom-out="false" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="80" + y="20" + /> + <text + font-size="14" + x="100" + y="40" + > + H + </text> + </g> + </g> + </g>, + <g + class="gate" + data-id="1" + data-zoom-in="false" + data-zoom-out="false" + > + <line + x1="160" + x2="160" + y1="40" + y2="100" + /> + <circle + class="control-dot" + cx="160" + cy="40" + r="5" + /> + <g + class="oplus" + > + <circle + cx="160" + cy="100" + r="15" + /> + <line + x1="160" + x2="160" + y1="85" + y2="115" + /> + <line + x1="145" + x2="175" + y1="100" + y2="100" + /> + </g> + </g>, + <g + class="gate" + data-id="2" + data-zoom-in="false" + data-zoom-out="false" + > + <g> + <rect + class="gate-measure" + height="40" + width="40" + x="200" + y="80" + /> + <path + class="arc-measure" + d="M 235 102 A 15 12 0 0 0 205 102" + /> + <line + x1="220" + x2="232" + y1="108" + y2="88" + /> + </g> + </g>, +] +`; + +exports[`Testing getWireElems get 2 wires 1`] = ` +Array [ + <g> + <line + x1="40" + x2="260" + y1="40" + y2="40" + /> + <text + dominant-baseline="hanging" + font-size="75%" + text-anchor="start" + x="40" + y="24" + > + q0 + </text> + </g>, + <g> + <line + x1="40" + x2="260" + y1="100" + y2="100" + /> + <text + dominant-baseline="hanging" + font-size="75%" + text-anchor="start" + x="40" + y="84" + > + q1 + </text> + </g>, +] +`; + +exports[`Testing handleGateMouseDown copying, ctrlKey is true 1`] = ` +<div + class="copying" +/> +`; + +exports[`Testing handleGateMouseDown moving, ctrlKey is false 1`] = ` +<div + class="moving" +/> +`; diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 22e249a3..f50dd1a0 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -1,6 +1,7 @@ import { Operation } from '../src/circuit'; import { exportedForTesting } from '../src/editable'; import { RegisterType } from '../src/register'; +import { draw, STYLES } from '../src/index'; const { getDataId, @@ -17,6 +18,12 @@ const { getParent, addCustomStyles, addDocumentEvents, + handleGateMouseDown, + getGateElems, + getWireElems, + createDropzone, + createLeftDropzone, + createRightDropzone, } = exportedForTesting; // Utlities @@ -772,3 +779,123 @@ describe('Testing addDocumentEvents', () => { expect(container).toMatchSnapshot(); }); }); + +describe('Testing handleGateMouseDown', () => { + test('copying, ctrlKey is true', () => { + const container = document.createElement('div'); + const ev = new MouseEvent('mousedown', { ctrlKey: true }); + handleGateMouseDown(ev, container); + expect(container).toMatchSnapshot(); + }); + test('moving, ctrlKey is false', () => { + const container = document.createElement('div'); + const ev = new MouseEvent('mousedown', { ctrlKey: false }); + handleGateMouseDown(ev, container); + expect(container).toMatchSnapshot(); + }); +}); + +describe('Testing getGateElems', () => { + test('get 2 gates', () => { + const container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + draw(circuit, container, STYLES['default']); + const gateElems = getGateElems(container); + expect(gateElems).toHaveLength(2); + expect(gateElems).toMatchSnapshot(); + }); + test('get 3 gates', () => { + const container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + draw(circuit, container, STYLES['default']); + const gateElems = getGateElems(container); + expect(gateElems).toHaveLength(3); + expect(gateElems).toMatchSnapshot(); + }); +}); + +describe('Testing getWireElems', () => { + test('get 2 wires', () => { + const container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + draw(circuit, container, STYLES['default']); + const wireElems = getWireElems(container); + expect(wireElems).toHaveLength(2); + expect(wireElems).toMatchSnapshot(); + }); +}); + +describe('Testing createDropzone', () => { + test('create dropzone on the left', () => { + expect(createDropzone(0, 0, 20, 20, '0', 'left')).toMatchSnapshot(); + }); + test('create dropzone on the right', () => { + expect(createDropzone(0, 0, 20, 20, '0', 'right')).toMatchSnapshot(); + }); +}); + +describe('Testing createLeftDropzone', () => { + test('create left dropzone', () => { + expect(createLeftDropzone(0, 0, 20, '0')).toMatchSnapshot(); + }); +}); + +describe('Testing createRightDropzone', () => { + test('create dropzone right', () => { + expect(createRightDropzone(0, 0, 20, 20, '0')).toMatchSnapshot(); + }); +}); diff --git a/src/editable.ts b/src/editable.ts index 6b5d1871..2b395cca 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -210,11 +210,17 @@ const createDropzone = ( return dropzone; }; -const createLeftDropzone = (x: number, y: number, height: number, dataId: string): SVGElement => { - return createDropzone(x - leftPadding / 2, y, leftPadding / 2, height, dataId, 'left'); +const createLeftDropzone = (gateX: number, gateY: number, gateHeight: number, dataId: string): SVGElement => { + return createDropzone(gateX - leftPadding / 2, gateY, leftPadding / 2, gateHeight, dataId, 'left'); }; -const createRightDropzone = (x: number, y: number, width: number, height: number, dataId: string): SVGElement => { - return createDropzone(x + width, y, leftPadding / 2, height, dataId, 'right'); +const createRightDropzone = ( + gateX: number, + gateY: number, + gateWidth: number, + gateHeight: number, + dataId: string, +): SVGElement => { + return createDropzone(gateX + gateWidth, gateY, leftPadding / 2, gateHeight, dataId, 'right'); }; // Operation getters @@ -327,6 +333,12 @@ const exportedForTesting = { getParent, addCustomStyles, addDocumentEvents, + handleGateMouseDown, + getGateElems, + getWireElems, + createDropzone, + createLeftDropzone, + createRightDropzone, }; -export { addEditable, exportedForTesting }; +export { addEditable, exportedForTesting, getGateElems }; From be0685980bc658a86fa9813f73940abcf0bc6d5a Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 9 Jun 2022 10:23:32 -0400 Subject: [PATCH 013/108] add tests for getClosestWireY --- __tests__/editable.test.ts | 85 ++++++++++++++++++++++++++++++++++++++ src/editable.ts | 44 +++++++++++--------- 2 files changed, 110 insertions(+), 19 deletions(-) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index f50dd1a0..7ea1e307 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -24,6 +24,7 @@ const { createDropzone, createLeftDropzone, createRightDropzone, + getClosestWireY, } = exportedForTesting; // Utlities @@ -899,3 +900,87 @@ describe('Testing createRightDropzone', () => { expect(createRightDropzone(0, 0, 20, 20, '0')).toMatchSnapshot(); }); }); + +describe('Testing getClosestWireY', () => { + test('should return 40', () => { + const container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + const wires = { '40': 'q0', '100': 'q1' }; + draw(circuit, container, STYLES['default']); + expect(getClosestWireY(50, wires)).toEqual(40); + }); + test('should return 100', () => { + const container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + const wires = { '40': 'q0', '100': 'q1' }; + draw(circuit, container, STYLES['default']); + expect(getClosestWireY(85, wires)).toEqual(100); + }); + test('should return null', () => { + const container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + const wires = { '40': 'q0', '100': 'q1' }; + draw(circuit, container, STYLES['default']); + expect(getClosestWireY(120, wires)).toEqual(null); + }); +}); diff --git a/src/editable.ts b/src/editable.ts index 2b395cca..6b07be81 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -280,16 +280,15 @@ const getWireElemText = (wireElem: SVGGElement): string => { }; const getClosestWireY = (offsetY: number, wires: { [y: number]: string }): number | null => { - let wireY; - Object.entries(wires).forEach((wire) => { + for (const wire of Object.entries(wires)) { const y = wire[0]; const distance = Math.abs(offsetY - Number(y)); - // 15 is a magic number - if (distance < 15) { - wireY = y; + // 15 is an arbitrary number to determine the closeness of distance + if (distance <= 15) { + return Number(y); } - }); - return wireY || null; + } + return null; }; const getDropzonePosition = (element: SVGElement): string => { @@ -319,26 +318,33 @@ const cursorCopy = (container: HTMLElement, value: boolean): void => { }; const exportedForTesting = { - getDataId, - splitDataId, - cursorMove, - cursorCopy, - deleteAt, - insertBefore, - insertAfter, - getDropzonePosition, - getWireElemText, - getWireElemY, - getGate, - getParent, + // addEditable addCustomStyles, + // addDropzones addDocumentEvents, + // addDropzoneEvents + // addMouseEvents handleGateMouseDown, + // handleDropzoneMouseUp getGateElems, getWireElems, createDropzone, createLeftDropzone, createRightDropzone, + getParent, + getGate, + getDataId, + splitDataId, + // getWireElemsY + getWireElemY, + getWireElemText, + getClosestWireY, + getDropzonePosition, + insertBefore, + insertAfter, + deleteAt, + cursorMove, + cursorCopy, }; export { addEditable, exportedForTesting, getGateElems }; From 41bbf6897745bf2f871c741a7b0d1c21f71d457a Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 9 Jun 2022 10:47:08 -0400 Subject: [PATCH 014/108] Add tests for getWireElemsY + addDropzoneEvents --- __tests__/__snapshots__/editable.test.ts.snap | 26 ++ __tests__/editable.test.ts | 224 ++++++++++++++++++ src/editable.ts | 6 +- 3 files changed, 253 insertions(+), 3 deletions(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 0d888290..34cc9398 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -39,6 +39,32 @@ exports[`Testing addDocumentEvents verify document events 1`] = `<div />`; exports[`Testing addDocumentEvents verify document events 2`] = `<div />`; +exports[`Testing addDropzoneEvents add 1 event 1`] = ` +<div> + <svg> + <rect /> + </svg> +</div> +`; + +exports[`Testing addDropzoneEvents add 1 event 2`] = ` +<div> + <svg> + <rect /> + <rect /> + </svg> +</div> +`; + +exports[`Testing addDropzoneEvents add 2 events 1`] = ` +<div> + <svg> + <rect /> + <rect /> + </svg> +</div> +`; + exports[`Testing createDropzone create dropzone on the left 1`] = ` <rect class="dropzone" diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 7ea1e307..2c09a384 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -25,6 +25,8 @@ const { createLeftDropzone, createRightDropzone, getClosestWireY, + getWireElemsY, + addDropzoneEvents, } = exportedForTesting; // Utlities @@ -984,3 +986,225 @@ describe('Testing getClosestWireY', () => { expect(getClosestWireY(120, wires)).toEqual(null); }); }); + +describe('test getWireElemsY', () => { + test('get 2 wires', () => { + const container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + const expected = { '40': 'q0', '100': 'q1' }; + draw(circuit, container, STYLES['default']); + expect(getWireElemsY(container)).toStrictEqual(expected); + }); + test('get 4 wires', () => { + const container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], + operations: [ + { + gate: 'Foo', + conditionalRender: 3, + targets: [{ qId: 0 }, { qId: 1 }], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + }, + { + gate: 'RX', + displayArgs: '(0.25)', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 0 }], + }, + ], + }, + { + gate: 'X', + targets: [{ qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 2 }, { qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }, { qId: 3 }], + targets: [{ qId: 1 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }, { qId: 3 }], + targets: [{ qId: 2 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'measure', + isMeasurement: true, + controls: [{ qId: 0 }], + targets: [{ type: 1, qId: 0, cId: 0 }], + }, + { + gate: 'ApplyIfElseR', + isConditional: true, + controls: [{ type: 1, qId: 0, cId: 0 }], + targets: [], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + conditionalRender: 2, + }, + { + gate: 'Foo', + targets: [{ qId: 3 }], + conditionalRender: 2, + }, + ], + }, + { + gate: 'SWAP', + targets: [{ qId: 0 }, { qId: 2 }], + children: [ + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + ], + }, + { + gate: 'ZZ', + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'ZZ', + targets: [{ qId: 0 }, { qId: 1 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }, { qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + ], + }; + const expected = { '40': 'q0', '120': 'q1', '180': 'q2', '240': 'q3' }; + draw(circuit, container, STYLES['default']); + expect(getWireElemsY(container)).toStrictEqual(expected); + }); +}); + +describe('Testing addDropzoneEvents', () => { + interface Context { + container: HTMLElement; + operations: Operation[]; + wires: Wires; + renderFn: () => void; + } + + interface Wires { + [y: string]: string; + } + + test('add 1 event', () => { + const container = document.createElement('div'); + const svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + const dropzoneElem = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + svgElem.append(dropzoneElem); + container.append(svgElem); + interface Context { + container: HTMLElement; + operations: Operation[]; + wires: Wires; + renderFn: () => void; + } + + const context: Context = { + container: container, + operations: [], + wires: {}, + renderFn: () => { + return; + }, + }; + addDropzoneEvents(context); + expect(container).toMatchSnapshot(); + }); + test('add 2 events', () => { + const container = document.createElement('div'); + const svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + const dropzoneElem = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + const dropzoneElem1 = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + svgElem.append(dropzoneElem); + svgElem.append(dropzoneElem1); + container.append(svgElem); + interface Context { + container: HTMLElement; + operations: Operation[]; + wires: Wires; + renderFn: () => void; + } + + const context: Context = { + container: container, + operations: [], + wires: {}, + renderFn: () => { + return; + }, + }; + addDropzoneEvents(context); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/src/editable.ts b/src/editable.ts index 6b07be81..2e2a978f 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -322,7 +322,7 @@ const exportedForTesting = { addCustomStyles, // addDropzones addDocumentEvents, - // addDropzoneEvents + addDropzoneEvents, // addMouseEvents handleGateMouseDown, // handleDropzoneMouseUp @@ -335,7 +335,7 @@ const exportedForTesting = { getGate, getDataId, splitDataId, - // getWireElemsY + getWireElemsY, getWireElemY, getWireElemText, getClosestWireY, @@ -347,4 +347,4 @@ const exportedForTesting = { cursorCopy, }; -export { addEditable, exportedForTesting, getGateElems }; +export { addEditable, exportedForTesting }; From 6d9b5d58980a1aa3f0de42badb9beecc3ec2f7ec Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 9 Jun 2022 10:54:07 -0400 Subject: [PATCH 015/108] Add tests for addMouseEvents --- __tests__/__snapshots__/editable.test.ts.snap | 282 +++++++++++++++++- __tests__/editable.test.ts | 79 +++-- src/editable.ts | 2 +- 3 files changed, 337 insertions(+), 26 deletions(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 34cc9398..00bc4da5 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -47,7 +47,7 @@ exports[`Testing addDropzoneEvents add 1 event 1`] = ` </div> `; -exports[`Testing addDropzoneEvents add 1 event 2`] = ` +exports[`Testing addDropzoneEvents add 2 events 1`] = ` <div> <svg> <rect /> @@ -56,11 +56,283 @@ exports[`Testing addDropzoneEvents add 1 event 2`] = ` </div> `; -exports[`Testing addDropzoneEvents add 2 events 1`] = ` +exports[`Testing addMouseEvents verify mouse events 1`] = ` <div> - <svg> - <rect /> - <rect /> + <svg + class="qviz" + height="180" + id="6252074d-6246-4fd9-8dc4-f4e412dc688c" + style="max-width: fit-content;" + width="140" + > + <style> + + line, + circle, + rect { + stroke: #000000; + stroke-width: 1; + } + text { + fill: #000000; + dominant-baseline: middle; + text-anchor: middle; + font-family: Arial; + } + .control-dot { + fill: #000000; + } + .oplus line, .oplus circle { + fill: #FFFFFF; + stroke-width: 2; + } + .gate-unitary { + fill: #D9F1FA; + } + .gate-measure { + fill: #FFDE86; + } + rect.gate-swap { + fill: transparent; + stroke: transparent; + } + .arc-measure { + stroke: #000000; + fill: none; + stroke-width: 1; + } + .register-classical { + stroke-width: 0.5; + } + + .hidden { + display: none; + } + .classically-controlled-unknown { + opacity: 0.25; + } + + + .classically-controlled-one .classical-container, + .classically-controlled-one .classical-line { + stroke: #4059BD; + stroke-width: 1.3; + fill: #4059BD; + fill-opacity: 0.1; + } + .classically-controlled-zero .classical-container, + .classically-controlled-zero .classical-line { + stroke: #C40000; + stroke-width: 1.3; + fill: #C40000; + fill-opacity: 0.1; + } + + .classically-controlled-btn { + cursor: pointer; + } + .classically-controlled-unknown .classically-controlled-btn { + fill: #E5E5E5; + } + .classically-controlled-one .classically-controlled-btn { + fill: #4059BD; + } + .classically-controlled-zero .classically-controlled-btn { + fill: #C40000; + } + + .classically-controlled-btn text { + dominant-baseline: middle; + text-anchor: middle; + stroke: none; + font-family: Arial; + } + .classically-controlled-unknown .classically-controlled-btn text { + fill: #000000; + } + .classically-controlled-one .classically-controlled-btn text { + fill: #FFFFFF; + } + .classically-controlled-zero .classically-controlled-btn text { + fill: #FFFFFF; + } + + .qviz .gate-collapse, + .qviz .gate-expand { + opacity: 0; + transition: opacity 1s; + } + + .qviz:hover .gate-collapse, + .qviz:hover .gate-expand { + visibility: visible; + opacity: 0.2; + transition: visibility 1s; + transition: opacity 1s; + } + + .gate-expand, .gate-collapse { + cursor: pointer; + } + + .gate-collapse circle, + .gate-expand circle { + fill: white; + stroke-width: 2px; + stroke: black; + } + .gate-collapse path, + .gate-expand path { + stroke-width: 4px; + stroke: black; + } + + .gate:hover > .gate-collapse, + .gate:hover > .gate-expand { + visibility: visible; + opacity: 1; + transition: opacity 1s; + } + </style> + <g> + <text + dominant-baseline="middle" + font-size="16" + text-anchor="start" + x="20" + y="40" + > + |0⟩ + </text> + <text + dominant-baseline="middle" + font-size="16" + text-anchor="start" + x="20" + y="100" + > + |0⟩ + </text> + </g> + <g> + <g> + <line + x1="40" + x2="140" + y1="40" + y2="40" + /> + <text + dominant-baseline="hanging" + font-size="75%" + text-anchor="start" + x="40" + y="24" + > + q0 + </text> + </g> + <g> + <line + x1="40" + x2="140" + y1="100" + y2="100" + /> + <text + dominant-baseline="hanging" + font-size="75%" + text-anchor="start" + x="40" + y="84" + > + q1 + </text> + </g> + <g> + <line + class="register-classical" + x1="101" + x2="101" + y1="100" + y2="139" + /> + <line + class="register-classical" + x1="99" + x2="99" + y1="100" + y2="141" + /> + <line + class="register-classical" + x1="101" + x2="140" + y1="139" + y2="139" + /> + <line + class="register-classical" + x1="99" + x2="140" + y1="141" + y2="141" + /> + </g> + </g> + <g> + <g + class="gate" + data-id="0" + data-zoom-in="false" + data-zoom-out="false" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="80" + y="20" + /> + <text + font-size="14" + x="100" + y="40" + > + H + </text> + </g> + </g> + </g> + <g + class="gate" + data-id="1" + data-zoom-in="false" + data-zoom-out="false" + > + <g> + <rect + class="gate-measure" + height="40" + width="40" + x="80" + y="80" + /> + <path + class="arc-measure" + d="M 115 102 A 15 12 0 0 0 85 102" + /> + <line + x1="100" + x2="112" + y1="108" + y2="88" + /> + </g> + </g> + </g> </svg> </div> `; diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 2c09a384..9d9af652 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -4,29 +4,33 @@ import { RegisterType } from '../src/register'; import { draw, STYLES } from '../src/index'; const { - getDataId, - splitDataId, - cursorMove, - cursorCopy, - deleteAt, - insertBefore, - insertAfter, - getDropzonePosition, - getWireElemText, - getWireElemY, - getGate, - getParent, + // addEditable addCustomStyles, + // addDropzones addDocumentEvents, + addDropzoneEvents, + addMouseEvents, handleGateMouseDown, + // handleDropzoneMouseUp getGateElems, getWireElems, createDropzone, createLeftDropzone, createRightDropzone, - getClosestWireY, + getParent, + getGate, + getDataId, + splitDataId, getWireElemsY, - addDropzoneEvents, + getWireElemY, + getWireElemText, + getClosestWireY, + getDropzonePosition, + insertBefore, + insertAfter, + deleteAt, + cursorMove, + cursorCopy, } = exportedForTesting; // Utlities @@ -1163,12 +1167,6 @@ describe('Testing addDropzoneEvents', () => { const dropzoneElem = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); svgElem.append(dropzoneElem); container.append(svgElem); - interface Context { - container: HTMLElement; - operations: Operation[]; - wires: Wires; - renderFn: () => void; - } const context: Context = { container: container, @@ -1208,3 +1206,44 @@ describe('Testing addDropzoneEvents', () => { expect(container).toMatchSnapshot(); }); }); + +describe('Testing addMouseEvents', () => { + interface Context { + container: HTMLElement; + operations: Operation[]; + wires: Wires; + renderFn: () => void; + } + interface Wires { + [y: string]: string; + } + test('verify mouse events', () => { + const container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + draw(circuit, container, STYLES['default']); + const context: Context = { + container: container, + operations: [], + wires: {}, + renderFn: () => { + return; + }, + }; + addMouseEvents(context); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/src/editable.ts b/src/editable.ts index 2e2a978f..687c799b 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -323,7 +323,7 @@ const exportedForTesting = { // addDropzones addDocumentEvents, addDropzoneEvents, - // addMouseEvents + addMouseEvents, handleGateMouseDown, // handleDropzoneMouseUp getGateElems, From 692250c3039deaed4c927bba27c0d01cce660860 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 9 Jun 2022 11:03:28 -0400 Subject: [PATCH 016/108] Remove svg id in snapshot --- __tests__/__snapshots__/editable.test.ts.snap | 1 - __tests__/editable.test.ts | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 00bc4da5..b6ae0cf6 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -61,7 +61,6 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` <svg class="qviz" height="180" - id="6252074d-6246-4fd9-8dc4-f4e412dc688c" style="max-width: fit-content;" width="140" > diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 9d9af652..31c5cacb 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -1243,6 +1243,8 @@ describe('Testing addMouseEvents', () => { return; }, }; + const svgElem = container.querySelector('svg'); + if (svgElem != null) svgElem.removeAttribute('id'); addMouseEvents(context); expect(container).toMatchSnapshot(); }); From 0dc44fcd49f2194a811f08b56a0ea895f1ab56f2 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 9 Jun 2022 11:12:03 -0400 Subject: [PATCH 017/108] Trim trailing whitespace --- __tests__/__snapshots__/editable.test.ts.snap | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index b6ae0cf6..51dcc84a 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -65,7 +65,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` width="140" > <style> - + line, circle, rect { @@ -103,7 +103,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` .register-classical { stroke-width: 0.5; } - + .hidden { display: none; } @@ -111,7 +111,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` opacity: 0.25; } - + .classically-controlled-one .classical-container, .classically-controlled-one .classical-line { stroke: #4059BD; @@ -126,7 +126,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` fill: #C40000; fill-opacity: 0.1; } - + .classically-controlled-btn { cursor: pointer; } @@ -139,7 +139,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` .classically-controlled-zero .classically-controlled-btn { fill: #C40000; } - + .classically-controlled-btn text { dominant-baseline: middle; text-anchor: middle; @@ -155,7 +155,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` .classically-controlled-zero .classically-controlled-btn text { fill: #FFFFFF; } - + .qviz .gate-collapse, .qviz .gate-expand { opacity: 0; From c397bfd59976f8debaaff67419176bfd1df72be6 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 9 Jun 2022 11:20:28 -0400 Subject: [PATCH 018/108] Trim trailing whitespace --- __tests__/__snapshots__/editable.test.ts.snap | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 51dcc84a..b6ae0cf6 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -65,7 +65,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` width="140" > <style> - + line, circle, rect { @@ -103,7 +103,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` .register-classical { stroke-width: 0.5; } - + .hidden { display: none; } @@ -111,7 +111,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` opacity: 0.25; } - + .classically-controlled-one .classical-container, .classically-controlled-one .classical-line { stroke: #4059BD; @@ -126,7 +126,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` fill: #C40000; fill-opacity: 0.1; } - + .classically-controlled-btn { cursor: pointer; } @@ -139,7 +139,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` .classically-controlled-zero .classically-controlled-btn { fill: #C40000; } - + .classically-controlled-btn text { dominant-baseline: middle; text-anchor: middle; @@ -155,7 +155,7 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` .classically-controlled-zero .classically-controlled-btn text { fill: #FFFFFF; } - + .qviz .gate-collapse, .qviz .gate-expand { opacity: 0; From e544eeec791f8a8024562b21a184beec0a00b852 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 9 Jun 2022 14:43:57 -0400 Subject: [PATCH 019/108] Exclude __tests__/ from pre-commit hook --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 53148a4a..e2e23075 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,3 +39,4 @@ repos: language: system types: [text] stages: [commit, push, manual] + exclude: ^__tests__/ From f0507427153204d69c6319aab1faf98997493c1a Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 9 Jun 2022 19:31:21 -0400 Subject: [PATCH 020/108] Add callbackFn + documentation + tests --- __tests__/editable.test.ts | 47 +- example/script.js | 2 +- pnpm-lock.yaml | 6261 ++++++++++++++++++++++++++++++++++++ src/editable.ts | 18 +- src/index.ts | 7 +- src/sqore.ts | 43 +- 6 files changed, 6359 insertions(+), 19 deletions(-) create mode 100644 pnpm-lock.yaml diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 31c5cacb..156439c7 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -1,7 +1,8 @@ -import { Operation } from '../src/circuit'; +import { Circuit, Operation } from '../src/circuit'; import { exportedForTesting } from '../src/editable'; import { RegisterType } from '../src/register'; import { draw, STYLES } from '../src/index'; +import { Sqore } from '../src/sqore'; const { // addEditable @@ -19,6 +20,7 @@ const { createRightDropzone, getParent, getGate, + getRenderFn, getDataId, splitDataId, getWireElemsY, @@ -1249,3 +1251,46 @@ describe('Testing addMouseEvents', () => { expect(container).toMatchSnapshot(); }); }); + +describe('Testing getRenderFn', () => { + test('check console.log displaying "callbackFn is triggered"', () => { + Object.defineProperty(window.SVGElement.prototype, 'getBBox', { + writable: true, + value: () => ({ + x: 0, + y: 0, + width: 0, + height: 0, + }), + }); + const container = document.createElement('div'); + const circuit: Circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + const sqore = new Sqore(circuit, STYLES['default']); + const callbackFn = () => console.log('callbackFn is triggered'); + const renderFn = getRenderFn(container, sqore, callbackFn); + + jest.spyOn(console, 'log'); + renderFn(); + expect(console.log).toHaveBeenCalledWith('callbackFn is triggered'); + }); +}); diff --git a/example/script.js b/example/script.js index ae8c42c3..ef3ef492 100644 --- a/example/script.js +++ b/example/script.js @@ -12,7 +12,7 @@ if (typeof qviz != 'undefined') { const sampleDiv = document.getElementById('sample'); if (sampleDiv != null) { - qviz.draw(sample, sampleDiv, qviz.STYLES['Default'], 0, true); + qviz.draw(sample, sampleDiv, qviz.STYLES['Default'], 0, true, () => console.log('callbackFn')); } const teleportDiv = document.getElementById('teleport'); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..fda0d629 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,6261 @@ +lockfileVersion: 5.4 + +specifiers: + '@types/jest': ^26.0.4 + '@types/prettier': 2.6.0 + '@typescript-eslint/eslint-plugin': ^3.9.0 + '@typescript-eslint/parser': ^3.9.0 + canvas: ^2.6.1 + eslint: ^7.6.0 + eslint-config-prettier: ^6.11.0 + eslint-plugin-jest: ^23.20.0 + eslint-plugin-prettier: ^3.1.4 + jest: ^26.6.3 + prettier: 2.6.0 + terser-webpack-plugin: ^4.1.0 + ts-jest: ^26.1.2 + ts-loader: ^8.0.2 + typescript: ^3.9.6 + webpack: ^4.46.0 + webpack-cli: ^3.3.12 + +devDependencies: + '@types/jest': 26.0.24 + '@types/prettier': 2.6.0 + '@typescript-eslint/eslint-plugin': 3.10.1_kxujzhw6vbtdri44htsqryf25e + '@typescript-eslint/parser': 3.10.1_2de3j2mqba4wgeuiaqz2k7syrm + canvas: 2.9.1 + eslint: 7.32.0 + eslint-config-prettier: 6.15.0_eslint@7.32.0 + eslint-plugin-jest: 23.20.0_2de3j2mqba4wgeuiaqz2k7syrm + eslint-plugin-prettier: 3.4.1_dnozcfbeb5wiozlftdrslmvmgu + jest: 26.6.3_canvas@2.9.1 + prettier: 2.6.0 + terser-webpack-plugin: 4.2.3_webpack@4.46.0 + ts-jest: 26.5.6_eee4nuuc45mdmx5rmbx7hzjjtq + ts-loader: 8.4.0_ezrl6vhczkqqw35uifasf5iyga + typescript: 3.9.10 + webpack: 4.46.0_webpack-cli@3.3.12 + webpack-cli: 3.3.12_webpack@4.46.0 + +packages: + + /@ampproject/remapping/2.2.0: + resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.1.1 + '@jridgewell/trace-mapping': 0.3.13 + dev: true + + /@babel/code-frame/7.12.11: + resolution: {integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==} + dependencies: + '@babel/highlight': 7.17.12 + dev: true + + /@babel/code-frame/7.16.7: + resolution: {integrity: sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.17.12 + dev: true + + /@babel/compat-data/7.17.10: + resolution: {integrity: sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core/7.18.2: + resolution: {integrity: sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.0 + '@babel/code-frame': 7.16.7 + '@babel/generator': 7.18.2 + '@babel/helper-compilation-targets': 7.18.2_@babel+core@7.18.2 + '@babel/helper-module-transforms': 7.18.0 + '@babel/helpers': 7.18.2 + '@babel/parser': 7.18.4 + '@babel/template': 7.16.7 + '@babel/traverse': 7.18.2 + '@babel/types': 7.18.4 + convert-source-map: 1.8.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.1 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator/7.18.2: + resolution: {integrity: sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.18.4 + '@jridgewell/gen-mapping': 0.3.1 + jsesc: 2.5.2 + dev: true + + /@babel/helper-compilation-targets/7.18.2_@babel+core@7.18.2: + resolution: {integrity: sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.17.10 + '@babel/core': 7.18.2 + '@babel/helper-validator-option': 7.16.7 + browserslist: 4.20.4 + semver: 6.3.0 + dev: true + + /@babel/helper-environment-visitor/7.18.2: + resolution: {integrity: sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-function-name/7.17.9: + resolution: {integrity: sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.16.7 + '@babel/types': 7.18.4 + dev: true + + /@babel/helper-hoist-variables/7.16.7: + resolution: {integrity: sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.18.4 + dev: true + + /@babel/helper-module-imports/7.16.7: + resolution: {integrity: sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.18.4 + dev: true + + /@babel/helper-module-transforms/7.18.0: + resolution: {integrity: sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.18.2 + '@babel/helper-module-imports': 7.16.7 + '@babel/helper-simple-access': 7.18.2 + '@babel/helper-split-export-declaration': 7.16.7 + '@babel/helper-validator-identifier': 7.16.7 + '@babel/template': 7.16.7 + '@babel/traverse': 7.18.2 + '@babel/types': 7.18.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-plugin-utils/7.17.12: + resolution: {integrity: sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-simple-access/7.18.2: + resolution: {integrity: sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.18.4 + dev: true + + /@babel/helper-split-export-declaration/7.16.7: + resolution: {integrity: sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.18.4 + dev: true + + /@babel/helper-validator-identifier/7.16.7: + resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option/7.16.7: + resolution: {integrity: sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers/7.18.2: + resolution: {integrity: sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.16.7 + '@babel/traverse': 7.18.2 + '@babel/types': 7.18.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight/7.17.12: + resolution: {integrity: sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.16.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser/7.18.4: + resolution: {integrity: sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.18.4 + dev: true + + /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.18.2: + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.18.2: + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.18.2: + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.18.2: + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.18.2: + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.18.2: + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.18.2: + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.18.2: + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.18.2: + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.18.2: + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.18.2: + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.18.2: + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.18.2 + '@babel/helper-plugin-utils': 7.17.12 + dev: true + + /@babel/template/7.16.7: + resolution: {integrity: sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.16.7 + '@babel/parser': 7.18.4 + '@babel/types': 7.18.4 + dev: true + + /@babel/traverse/7.18.2: + resolution: {integrity: sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.16.7 + '@babel/generator': 7.18.2 + '@babel/helper-environment-visitor': 7.18.2 + '@babel/helper-function-name': 7.17.9 + '@babel/helper-hoist-variables': 7.16.7 + '@babel/helper-split-export-declaration': 7.16.7 + '@babel/parser': 7.18.4 + '@babel/types': 7.18.4 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types/7.18.4: + resolution: {integrity: sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.16.7 + to-fast-properties: 2.0.0 + dev: true + + /@bcoe/v8-coverage/0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + /@cnakazawa/watch/1.0.4: + resolution: {integrity: sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==} + engines: {node: '>=0.1.95'} + hasBin: true + dependencies: + exec-sh: 0.3.6 + minimist: 1.2.6 + dev: true + + /@eslint/eslintrc/0.4.3: + resolution: {integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 7.3.1 + globals: 13.15.0 + ignore: 4.0.6 + import-fresh: 3.3.0 + js-yaml: 3.14.1 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@gar/promisify/1.1.3: + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + dev: true + + /@humanwhocodes/config-array/0.5.0: + resolution: {integrity: sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/object-schema/1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + + /@istanbuljs/load-nyc-config/1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + dev: true + + /@istanbuljs/schema/0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jest/console/26.6.2: + resolution: {integrity: sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + '@types/node': 17.0.41 + chalk: 4.1.2 + jest-message-util: 26.6.2 + jest-util: 26.6.2 + slash: 3.0.0 + dev: true + + /@jest/core/26.6.3_canvas@2.9.1: + resolution: {integrity: sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/console': 26.6.2 + '@jest/reporters': 26.6.2 + '@jest/test-result': 26.6.2 + '@jest/transform': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 17.0.41 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.10 + jest-changed-files: 26.6.2 + jest-config: 26.6.3_canvas@2.9.1 + jest-haste-map: 26.6.2 + jest-message-util: 26.6.2 + jest-regex-util: 26.0.0 + jest-resolve: 26.6.2 + jest-resolve-dependencies: 26.6.3 + jest-runner: 26.6.3_canvas@2.9.1 + jest-runtime: 26.6.3_canvas@2.9.1 + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + jest-validate: 26.6.2 + jest-watcher: 26.6.2 + micromatch: 4.0.5 + p-each-series: 2.2.0 + rimraf: 3.0.2 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + dev: true + + /@jest/environment/26.6.2: + resolution: {integrity: sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/fake-timers': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 17.0.41 + jest-mock: 26.6.2 + dev: true + + /@jest/fake-timers/26.6.2: + resolution: {integrity: sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + '@sinonjs/fake-timers': 6.0.1 + '@types/node': 17.0.41 + jest-message-util: 26.6.2 + jest-mock: 26.6.2 + jest-util: 26.6.2 + dev: true + + /@jest/globals/26.6.2: + resolution: {integrity: sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/environment': 26.6.2 + '@jest/types': 26.6.2 + expect: 26.6.2 + dev: true + + /@jest/reporters/26.6.2: + resolution: {integrity: sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==} + engines: {node: '>= 10.14.2'} + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 26.6.2 + '@jest/test-result': 26.6.2 + '@jest/transform': 26.6.2 + '@jest/types': 26.6.2 + chalk: 4.1.2 + collect-v8-coverage: 1.0.1 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.10 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-instrument: 4.0.3 + istanbul-lib-report: 3.0.0 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.4 + jest-haste-map: 26.6.2 + jest-resolve: 26.6.2 + jest-util: 26.6.2 + jest-worker: 26.6.2 + slash: 3.0.0 + source-map: 0.6.1 + string-length: 4.0.2 + terminal-link: 2.1.1 + v8-to-istanbul: 7.1.2 + optionalDependencies: + node-notifier: 8.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/source-map/26.6.2: + resolution: {integrity: sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==} + engines: {node: '>= 10.14.2'} + dependencies: + callsites: 3.1.0 + graceful-fs: 4.2.10 + source-map: 0.6.1 + dev: true + + /@jest/test-result/26.6.2: + resolution: {integrity: sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/console': 26.6.2 + '@jest/types': 26.6.2 + '@types/istanbul-lib-coverage': 2.0.4 + collect-v8-coverage: 1.0.1 + dev: true + + /@jest/test-sequencer/26.6.3_canvas@2.9.1: + resolution: {integrity: sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/test-result': 26.6.2 + graceful-fs: 4.2.10 + jest-haste-map: 26.6.2 + jest-runner: 26.6.3_canvas@2.9.1 + jest-runtime: 26.6.3_canvas@2.9.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + dev: true + + /@jest/transform/26.6.2: + resolution: {integrity: sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==} + engines: {node: '>= 10.14.2'} + dependencies: + '@babel/core': 7.18.2 + '@jest/types': 26.6.2 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 1.8.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.10 + jest-haste-map: 26.6.2 + jest-regex-util: 26.0.0 + jest-util: 26.6.2 + micromatch: 4.0.5 + pirates: 4.0.5 + slash: 3.0.0 + source-map: 0.6.1 + write-file-atomic: 3.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/types/26.6.2: + resolution: {integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==} + engines: {node: '>= 10.14.2'} + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-reports': 3.0.1 + '@types/node': 17.0.41 + '@types/yargs': 15.0.14 + chalk: 4.1.2 + dev: true + + /@jridgewell/gen-mapping/0.1.1: + resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.1 + '@jridgewell/sourcemap-codec': 1.4.13 + dev: true + + /@jridgewell/gen-mapping/0.3.1: + resolution: {integrity: sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.1 + '@jridgewell/sourcemap-codec': 1.4.13 + '@jridgewell/trace-mapping': 0.3.13 + dev: true + + /@jridgewell/resolve-uri/3.0.7: + resolution: {integrity: sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array/1.1.1: + resolution: {integrity: sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/source-map/0.3.2: + resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==} + dependencies: + '@jridgewell/gen-mapping': 0.3.1 + '@jridgewell/trace-mapping': 0.3.13 + dev: true + + /@jridgewell/sourcemap-codec/1.4.13: + resolution: {integrity: sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==} + dev: true + + /@jridgewell/trace-mapping/0.3.13: + resolution: {integrity: sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==} + dependencies: + '@jridgewell/resolve-uri': 3.0.7 + '@jridgewell/sourcemap-codec': 1.4.13 + dev: true + + /@mapbox/node-pre-gyp/1.0.9: + resolution: {integrity: sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==} + hasBin: true + dependencies: + detect-libc: 2.0.1 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.6.7 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.3.7 + tar: 6.1.11 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@npmcli/fs/1.1.1: + resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.3.7 + dev: true + + /@npmcli/move-file/1.1.2: + resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} + engines: {node: '>=10'} + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + dev: true + + /@sinonjs/commons/1.8.3: + resolution: {integrity: sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==} + dependencies: + type-detect: 4.0.8 + dev: true + + /@sinonjs/fake-timers/6.0.1: + resolution: {integrity: sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==} + dependencies: + '@sinonjs/commons': 1.8.3 + dev: true + + /@tootallnate/once/1.1.2: + resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} + engines: {node: '>= 6'} + dev: true + + /@types/babel__core/7.1.19: + resolution: {integrity: sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==} + dependencies: + '@babel/parser': 7.18.4 + '@babel/types': 7.18.4 + '@types/babel__generator': 7.6.4 + '@types/babel__template': 7.4.1 + '@types/babel__traverse': 7.17.1 + dev: true + + /@types/babel__generator/7.6.4: + resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} + dependencies: + '@babel/types': 7.18.4 + dev: true + + /@types/babel__template/7.4.1: + resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} + dependencies: + '@babel/parser': 7.18.4 + '@babel/types': 7.18.4 + dev: true + + /@types/babel__traverse/7.17.1: + resolution: {integrity: sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==} + dependencies: + '@babel/types': 7.18.4 + dev: true + + /@types/eslint-visitor-keys/1.0.0: + resolution: {integrity: sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==} + dev: true + + /@types/graceful-fs/4.1.5: + resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} + dependencies: + '@types/node': 17.0.41 + dev: true + + /@types/istanbul-lib-coverage/2.0.4: + resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + dev: true + + /@types/istanbul-lib-report/3.0.0: + resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + dev: true + + /@types/istanbul-reports/3.0.1: + resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} + dependencies: + '@types/istanbul-lib-report': 3.0.0 + dev: true + + /@types/jest/26.0.24: + resolution: {integrity: sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==} + dependencies: + jest-diff: 26.6.2 + pretty-format: 26.6.2 + dev: true + + /@types/json-schema/7.0.11: + resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} + dev: true + + /@types/node/17.0.41: + resolution: {integrity: sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw==} + dev: true + + /@types/normalize-package-data/2.4.1: + resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} + dev: true + + /@types/prettier/2.6.0: + resolution: {integrity: sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==} + dev: true + + /@types/stack-utils/2.0.1: + resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} + dev: true + + /@types/yargs-parser/21.0.0: + resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} + dev: true + + /@types/yargs/15.0.14: + resolution: {integrity: sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==} + dependencies: + '@types/yargs-parser': 21.0.0 + dev: true + + /@typescript-eslint/eslint-plugin/3.10.1_kxujzhw6vbtdri44htsqryf25e: + resolution: {integrity: sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + '@typescript-eslint/parser': ^3.0.0 + eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/experimental-utils': 3.10.1_2de3j2mqba4wgeuiaqz2k7syrm + '@typescript-eslint/parser': 3.10.1_2de3j2mqba4wgeuiaqz2k7syrm + debug: 4.3.4 + eslint: 7.32.0 + functional-red-black-tree: 1.0.1 + regexpp: 3.2.0 + semver: 7.3.7 + tsutils: 3.21.0_typescript@3.9.10 + typescript: 3.9.10 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/experimental-utils/2.34.0_2de3j2mqba4wgeuiaqz2k7syrm: + resolution: {integrity: sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + peerDependencies: + eslint: '*' + dependencies: + '@types/json-schema': 7.0.11 + '@typescript-eslint/typescript-estree': 2.34.0_typescript@3.9.10 + eslint: 7.32.0 + eslint-scope: 5.1.1 + eslint-utils: 2.1.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/experimental-utils/3.10.1_2de3j2mqba4wgeuiaqz2k7syrm: + resolution: {integrity: sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: '*' + dependencies: + '@types/json-schema': 7.0.11 + '@typescript-eslint/types': 3.10.1 + '@typescript-eslint/typescript-estree': 3.10.1_typescript@3.9.10 + eslint: 7.32.0 + eslint-scope: 5.1.1 + eslint-utils: 2.1.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/parser/3.10.1_2de3j2mqba4wgeuiaqz2k7syrm: + resolution: {integrity: sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@types/eslint-visitor-keys': 1.0.0 + '@typescript-eslint/experimental-utils': 3.10.1_2de3j2mqba4wgeuiaqz2k7syrm + '@typescript-eslint/types': 3.10.1 + '@typescript-eslint/typescript-estree': 3.10.1_typescript@3.9.10 + eslint: 7.32.0 + eslint-visitor-keys: 1.3.0 + typescript: 3.9.10 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types/3.10.1: + resolution: {integrity: sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + dev: true + + /@typescript-eslint/typescript-estree/2.34.0_typescript@3.9.10: + resolution: {integrity: sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + debug: 4.3.4 + eslint-visitor-keys: 1.3.0 + glob: 7.2.3 + is-glob: 4.0.3 + lodash: 4.17.21 + semver: 7.3.7 + tsutils: 3.21.0_typescript@3.9.10 + typescript: 3.9.10 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree/3.10.1_typescript@3.9.10: + resolution: {integrity: sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 3.10.1 + '@typescript-eslint/visitor-keys': 3.10.1 + debug: 4.3.4 + glob: 7.2.3 + is-glob: 4.0.3 + lodash: 4.17.21 + semver: 7.3.7 + tsutils: 3.21.0_typescript@3.9.10 + typescript: 3.9.10 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/visitor-keys/3.10.1: + resolution: {integrity: sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + dependencies: + eslint-visitor-keys: 1.3.0 + dev: true + + /@webassemblyjs/ast/1.9.0: + resolution: {integrity: sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==} + dependencies: + '@webassemblyjs/helper-module-context': 1.9.0 + '@webassemblyjs/helper-wasm-bytecode': 1.9.0 + '@webassemblyjs/wast-parser': 1.9.0 + dev: true + + /@webassemblyjs/floating-point-hex-parser/1.9.0: + resolution: {integrity: sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==} + dev: true + + /@webassemblyjs/helper-api-error/1.9.0: + resolution: {integrity: sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==} + dev: true + + /@webassemblyjs/helper-buffer/1.9.0: + resolution: {integrity: sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==} + dev: true + + /@webassemblyjs/helper-code-frame/1.9.0: + resolution: {integrity: sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==} + dependencies: + '@webassemblyjs/wast-printer': 1.9.0 + dev: true + + /@webassemblyjs/helper-fsm/1.9.0: + resolution: {integrity: sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==} + dev: true + + /@webassemblyjs/helper-module-context/1.9.0: + resolution: {integrity: sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==} + dependencies: + '@webassemblyjs/ast': 1.9.0 + dev: true + + /@webassemblyjs/helper-wasm-bytecode/1.9.0: + resolution: {integrity: sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==} + dev: true + + /@webassemblyjs/helper-wasm-section/1.9.0: + resolution: {integrity: sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==} + dependencies: + '@webassemblyjs/ast': 1.9.0 + '@webassemblyjs/helper-buffer': 1.9.0 + '@webassemblyjs/helper-wasm-bytecode': 1.9.0 + '@webassemblyjs/wasm-gen': 1.9.0 + dev: true + + /@webassemblyjs/ieee754/1.9.0: + resolution: {integrity: sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: true + + /@webassemblyjs/leb128/1.9.0: + resolution: {integrity: sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==} + dependencies: + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/utf8/1.9.0: + resolution: {integrity: sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==} + dev: true + + /@webassemblyjs/wasm-edit/1.9.0: + resolution: {integrity: sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==} + dependencies: + '@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 + dev: true + + /@webassemblyjs/wasm-gen/1.9.0: + resolution: {integrity: sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==} + dependencies: + '@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 + dev: true + + /@webassemblyjs/wasm-opt/1.9.0: + resolution: {integrity: sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==} + dependencies: + '@webassemblyjs/ast': 1.9.0 + '@webassemblyjs/helper-buffer': 1.9.0 + '@webassemblyjs/wasm-gen': 1.9.0 + '@webassemblyjs/wasm-parser': 1.9.0 + dev: true + + /@webassemblyjs/wasm-parser/1.9.0: + resolution: {integrity: sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==} + dependencies: + '@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 + dev: true + + /@webassemblyjs/wast-parser/1.9.0: + resolution: {integrity: sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==} + dependencies: + '@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 + dev: true + + /@webassemblyjs/wast-printer/1.9.0: + resolution: {integrity: sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==} + dependencies: + '@webassemblyjs/ast': 1.9.0 + '@webassemblyjs/wast-parser': 1.9.0 + '@xtuc/long': 4.2.2 + dev: true + + /@xtuc/ieee754/1.2.0: + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + dev: true + + /@xtuc/long/4.2.2: + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + dev: true + + /abab/2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + dev: true + + /abbrev/1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: true + + /acorn-globals/6.0.0: + resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==} + dependencies: + acorn: 7.4.1 + acorn-walk: 7.2.0 + dev: true + + /acorn-jsx/5.3.2_acorn@7.4.1: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 7.4.1 + dev: true + + /acorn-walk/7.2.0: + resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn/6.4.2: + resolution: {integrity: sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /acorn/7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /acorn/8.7.1: + resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /agent-base/6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /aggregate-error/3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + dev: true + + /ajv-errors/1.0.1_ajv@6.12.6: + resolution: {integrity: sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==} + peerDependencies: + ajv: '>=5.0.0' + dependencies: + ajv: 6.12.6 + dev: true + + /ajv-keywords/3.5.2_ajv@6.12.6: + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + dependencies: + ajv: 6.12.6 + dev: true + + /ajv/6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ajv/8.11.0: + resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /ansi-colors/4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + + /ansi-escapes/4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-regex/4.1.1: + resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} + engines: {node: '>=6'} + dev: true + + /ansi-regex/5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles/3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /anymatch/2.0.0: + resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} + dependencies: + micromatch: 3.1.10 + normalize-path: 2.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /anymatch/3.1.2: + resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /aproba/1.2.0: + resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==} + dev: true + + /aproba/2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + dev: true + + /are-we-there-yet/2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.0 + dev: true + + /argparse/1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /arr-diff/4.0.0: + resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} + engines: {node: '>=0.10.0'} + dev: true + + /arr-flatten/1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + dev: true + + /arr-union/3.1.0: + resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} + engines: {node: '>=0.10.0'} + dev: true + + /array-unique/0.3.2: + resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} + engines: {node: '>=0.10.0'} + dev: true + + /asn1.js/5.4.1: + resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + dependencies: + bn.js: 4.12.0 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + safer-buffer: 2.1.2 + dev: true + + /assert/1.5.0: + resolution: {integrity: sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==} + dependencies: + object-assign: 4.1.1 + util: 0.10.3 + dev: true + + /assign-symbols/1.0.0: + resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} + engines: {node: '>=0.10.0'} + dev: true + + /astral-regex/2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: true + + /async-each/1.0.3: + resolution: {integrity: sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==} + dev: true + optional: true + + /asynckit/0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: true + + /atob/2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + dev: true + + /babel-jest/26.6.3_@babel+core@7.18.2: + resolution: {integrity: sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==} + engines: {node: '>= 10.14.2'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.18.2 + '@jest/transform': 26.6.2 + '@jest/types': 26.6.2 + '@types/babel__core': 7.1.19 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 26.6.2_@babel+core@7.18.2 + chalk: 4.1.2 + graceful-fs: 4.2.10 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-istanbul/6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.17.12 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.0 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-jest-hoist/26.6.2: + resolution: {integrity: sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==} + engines: {node: '>= 10.14.2'} + dependencies: + '@babel/template': 7.16.7 + '@babel/types': 7.18.4 + '@types/babel__core': 7.1.19 + '@types/babel__traverse': 7.17.1 + dev: true + + /babel-preset-current-node-syntax/1.0.1_@babel+core@7.18.2: + resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.18.2 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.18.2 + '@babel/plugin-syntax-bigint': 7.8.3_@babel+core@7.18.2 + '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.18.2 + '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.18.2 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.18.2 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.18.2 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.18.2 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.18.2 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.18.2 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.18.2 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.18.2 + '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.18.2 + dev: true + + /babel-preset-jest/26.6.2_@babel+core@7.18.2: + resolution: {integrity: sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==} + engines: {node: '>= 10.14.2'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.18.2 + babel-plugin-jest-hoist: 26.6.2 + babel-preset-current-node-syntax: 1.0.1_@babel+core@7.18.2 + dev: true + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /base/0.11.2: + resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} + engines: {node: '>=0.10.0'} + dependencies: + cache-base: 1.0.1 + class-utils: 0.3.6 + component-emitter: 1.3.0 + define-property: 1.0.0 + isobject: 3.0.1 + mixin-deep: 1.3.2 + pascalcase: 0.1.1 + dev: true + + /base64-js/1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /big.js/5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + dev: true + + /binary-extensions/1.13.1: + resolution: {integrity: sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==} + engines: {node: '>=0.10.0'} + dev: true + optional: true + + /binary-extensions/2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + optional: true + + /bindings/1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + dependencies: + file-uri-to-path: 1.0.0 + dev: true + optional: true + + /bluebird/3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + dev: true + + /bn.js/4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + dev: true + + /bn.js/5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + dev: true + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces/2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + dependencies: + 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.4 + snapdragon: 0.8.2 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /braces/2.3.2_supports-color@6.1.0: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} + engines: {node: '>=0.10.0'} + dependencies: + 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.4 + snapdragon: 0.8.2_supports-color@6.1.0 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /brorand/1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + dev: true + + /browser-process-hrtime/1.0.0: + resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} + dev: true + + /browserify-aes/1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.4 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + + /browserify-cipher/1.0.1: + resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} + dependencies: + browserify-aes: 1.2.0 + browserify-des: 1.0.2 + evp_bytestokey: 1.0.3 + dev: true + + /browserify-des/1.0.2: + resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} + dependencies: + cipher-base: 1.0.4 + des.js: 1.0.1 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + + /browserify-rsa/4.1.0: + resolution: {integrity: sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==} + dependencies: + bn.js: 5.2.1 + randombytes: 2.1.0 + dev: true + + /browserify-sign/4.2.1: + resolution: {integrity: sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==} + dependencies: + bn.js: 5.2.1 + browserify-rsa: 4.1.0 + create-hash: 1.2.0 + create-hmac: 1.1.7 + elliptic: 6.5.4 + inherits: 2.0.4 + parse-asn1: 5.1.6 + readable-stream: 3.6.0 + safe-buffer: 5.2.1 + dev: true + + /browserify-zlib/0.2.0: + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} + dependencies: + pako: 1.0.11 + dev: true + + /browserslist/4.20.4: + resolution: {integrity: sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001352 + electron-to-chromium: 1.4.150 + escalade: 3.1.1 + node-releases: 2.0.5 + picocolors: 1.0.0 + dev: true + + /bs-logger/0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + dependencies: + fast-json-stable-stringify: 2.1.0 + dev: true + + /bser/2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: true + + /buffer-from/1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /buffer-xor/1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + dev: true + + /buffer/4.9.2: + resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + isarray: 1.0.0 + dev: true + + /builtin-status-codes/3.0.0: + resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} + dev: true + + /cacache/12.0.4: + resolution: {integrity: sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==} + dependencies: + bluebird: 3.7.2 + chownr: 1.1.4 + figgy-pudding: 3.5.2 + glob: 7.2.3 + graceful-fs: 4.2.10 + infer-owner: 1.0.4 + lru-cache: 5.1.1 + mississippi: 3.0.0 + mkdirp: 0.5.6 + move-concurrently: 1.0.1 + promise-inflight: 1.0.1_bluebird@3.7.2 + rimraf: 2.7.1 + ssri: 6.0.2 + unique-filename: 1.1.1 + y18n: 4.0.3 + dev: true + + /cacache/15.3.0: + resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==} + engines: {node: '>= 10'} + dependencies: + '@npmcli/fs': 1.1.1 + '@npmcli/move-file': 1.1.2 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 7.2.3 + infer-owner: 1.0.4 + lru-cache: 6.0.0 + minipass: 3.1.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1_bluebird@3.7.2 + rimraf: 3.0.2 + ssri: 8.0.1 + tar: 6.1.11 + unique-filename: 1.1.1 + transitivePeerDependencies: + - bluebird + dev: true + + /cache-base/1.0.1: + resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} + engines: {node: '>=0.10.0'} + dependencies: + collection-visit: 1.0.0 + component-emitter: 1.3.0 + get-value: 2.0.6 + has-value: 1.0.0 + isobject: 3.0.1 + set-value: 2.0.1 + to-object-path: 0.3.0 + union-value: 1.0.1 + unset-value: 1.0.0 + dev: true + + /callsites/3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase/5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase/6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /caniuse-lite/1.0.30001352: + resolution: {integrity: sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA==} + dev: true + + /canvas/2.9.1: + resolution: {integrity: sha512-vSQti1uG/2gjv3x6QLOZw7TctfufaerTWbVe+NSduHxxLGB+qf3kFgQ6n66DSnuoINtVUjrLLIK2R+lxrBG07A==} + engines: {node: '>=6'} + requiresBuild: true + dependencies: + '@mapbox/node-pre-gyp': 1.0.9 + nan: 2.16.0 + simple-get: 3.1.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /capture-exit/2.0.0: + resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==} + engines: {node: 6.* || 8.* || >= 10.*} + dependencies: + rsvp: 4.8.5 + dev: true + + /chalk/2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk/4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /char-regex/1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + dev: true + + /chokidar/2.1.8: + resolution: {integrity: sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==} + deprecated: Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies + dependencies: + anymatch: 2.0.0 + async-each: 1.0.3 + braces: 2.3.2 + glob-parent: 3.1.0 + inherits: 2.0.4 + is-binary-path: 1.0.1 + is-glob: 4.0.3 + normalize-path: 3.0.0 + path-is-absolute: 1.0.1 + readdirp: 2.2.1 + upath: 1.2.0 + optionalDependencies: + fsevents: 1.2.13 + transitivePeerDependencies: + - supports-color + dev: true + optional: true + + /chokidar/3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + requiresBuild: true + dependencies: + anymatch: 3.1.2 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + optional: true + + /chownr/1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + dev: true + + /chownr/2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: true + + /chrome-trace-event/1.0.3: + resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + engines: {node: '>=6.0'} + dev: true + + /ci-info/2.0.0: + resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + dev: true + + /cipher-base/1.0.4: + resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + + /cjs-module-lexer/0.6.0: + resolution: {integrity: sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==} + dev: true + + /class-utils/0.3.6: + resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + define-property: 0.2.5 + isobject: 3.0.1 + static-extend: 0.1.2 + dev: true + + /clean-stack/2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: true + + /cliui/5.0.0: + resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==} + dependencies: + string-width: 3.1.0 + strip-ansi: 5.2.0 + wrap-ansi: 5.1.0 + dev: true + + /cliui/6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: true + + /co/4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: true + + /collect-v8-coverage/1.0.1: + resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} + dev: true + + /collection-visit/1.0.0: + resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} + engines: {node: '>=0.10.0'} + dependencies: + map-visit: 1.0.0 + object-visit: 1.0.1 + dev: true + + /color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert/2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name/1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /color-support/1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: true + + /combined-stream/1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: true + + /commander/2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true + + /commondir/1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: true + + /component-emitter/1.3.0: + resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} + dev: true + + /concat-map/0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /concat-stream/1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.7 + typedarray: 0.0.6 + dev: true + + /console-browserify/1.2.0: + resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} + dev: true + + /console-control-strings/1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + dev: true + + /constants-browserify/1.0.0: + resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} + dev: true + + /convert-source-map/1.8.0: + resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /copy-concurrently/1.0.5: + resolution: {integrity: sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==} + dependencies: + aproba: 1.2.0 + fs-write-stream-atomic: 1.0.10 + iferr: 0.1.5 + mkdirp: 0.5.6 + rimraf: 2.7.1 + run-queue: 1.0.3 + dev: true + + /copy-descriptor/0.1.1: + resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} + engines: {node: '>=0.10.0'} + dev: true + + /core-util-is/1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: true + + /create-ecdh/4.0.4: + resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + dependencies: + bn.js: 4.12.0 + elliptic: 6.5.4 + dev: true + + /create-hash/1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + dependencies: + cipher-base: 1.0.4 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + dev: true + + /create-hmac/1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + dependencies: + cipher-base: 1.0.4 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + dev: true + + /cross-spawn/6.0.5: + resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} + engines: {node: '>=4.8'} + dependencies: + nice-try: 1.0.5 + path-key: 2.0.1 + semver: 5.7.1 + shebang-command: 1.2.0 + which: 1.3.1 + dev: true + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /crypto-browserify/3.12.0: + resolution: {integrity: sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==} + dependencies: + browserify-cipher: 1.0.1 + browserify-sign: 4.2.1 + create-ecdh: 4.0.4 + create-hash: 1.2.0 + create-hmac: 1.1.7 + diffie-hellman: 5.0.3 + inherits: 2.0.4 + pbkdf2: 3.1.2 + public-encrypt: 4.0.3 + randombytes: 2.1.0 + randomfill: 1.0.4 + dev: true + + /cssom/0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + dev: true + + /cssom/0.4.4: + resolution: {integrity: sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==} + dev: true + + /cssstyle/2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + dependencies: + cssom: 0.3.8 + dev: true + + /cyclist/1.0.1: + resolution: {integrity: sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==} + dev: true + + /data-urls/2.0.0: + resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} + engines: {node: '>=10'} + dependencies: + abab: 2.0.6 + whatwg-mimetype: 2.3.0 + whatwg-url: 8.7.0 + dev: true + + /debug/2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: true + + /debug/2.6.9_supports-color@6.1.0: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + supports-color: 6.1.0 + dev: true + + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /decamelize/1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /decimal.js/10.3.1: + resolution: {integrity: sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==} + dev: true + + /decode-uri-component/0.2.0: + resolution: {integrity: sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==} + engines: {node: '>=0.10'} + dev: true + + /decompress-response/4.2.1: + resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} + engines: {node: '>=8'} + dependencies: + mimic-response: 2.1.0 + dev: true + + /deep-is/0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /deepmerge/4.2.2: + resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} + engines: {node: '>=0.10.0'} + dev: true + + /define-property/0.2.5: + resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 0.1.6 + dev: true + + /define-property/1.0.0: + resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.2 + dev: true + + /define-property/2.0.2: + resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-descriptor: 1.0.2 + isobject: 3.0.1 + dev: true + + /delayed-stream/1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: true + + /delegates/1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dev: true + + /des.js/1.0.1: + resolution: {integrity: sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: true + + /detect-file/1.0.0: + resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} + engines: {node: '>=0.10.0'} + dev: true + + /detect-libc/2.0.1: + resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==} + engines: {node: '>=8'} + dev: true + + /detect-newline/3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + dev: true + + /diff-sequences/26.6.2: + resolution: {integrity: sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==} + engines: {node: '>= 10.14.2'} + dev: true + + /diffie-hellman/5.0.3: + resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + dependencies: + bn.js: 4.12.0 + miller-rabin: 4.0.1 + randombytes: 2.1.0 + dev: true + + /doctrine/3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /domain-browser/1.2.0: + resolution: {integrity: sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==} + engines: {node: '>=0.4', npm: '>=1.2'} + dev: true + + /domexception/2.0.1: + resolution: {integrity: sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==} + engines: {node: '>=8'} + dependencies: + webidl-conversions: 5.0.0 + dev: true + + /duplexify/3.7.1: + resolution: {integrity: sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==} + dependencies: + end-of-stream: 1.4.4 + inherits: 2.0.4 + readable-stream: 2.3.7 + stream-shift: 1.0.1 + dev: true + + /electron-to-chromium/1.4.150: + resolution: {integrity: sha512-MP3oBer0X7ZeS9GJ0H6lmkn561UxiwOIY9TTkdxVY7lI9G6GVCKfgJaHaDcakwdKxBXA4T3ybeswH/WBIN/KTA==} + dev: true + + /elliptic/6.5.4: + resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: true + + /emittery/0.7.2: + resolution: {integrity: sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==} + engines: {node: '>=10'} + dev: true + + /emoji-regex/7.0.3: + resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==} + dev: true + + /emoji-regex/8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emojis-list/3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + dev: true + + /end-of-stream/1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: true + + /enhanced-resolve/4.5.0: + resolution: {integrity: sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==} + engines: {node: '>=6.9.0'} + dependencies: + graceful-fs: 4.2.10 + memory-fs: 0.5.0 + tapable: 1.1.3 + dev: true + + /enquirer/2.3.6: + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.3 + dev: true + + /errno/0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + dependencies: + prr: 1.0.1 + dev: true + + /error-ex/1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /escalade/3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /escape-string-regexp/1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp/2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: true + + /escape-string-regexp/4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /escodegen/2.0.0: + resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==} + engines: {node: '>=6.0'} + hasBin: true + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionator: 0.8.3 + optionalDependencies: + source-map: 0.6.1 + dev: true + + /eslint-config-prettier/6.15.0_eslint@7.32.0: + resolution: {integrity: sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==} + hasBin: true + peerDependencies: + eslint: '>=3.14.1' + dependencies: + eslint: 7.32.0 + get-stdin: 6.0.0 + dev: true + + /eslint-plugin-jest/23.20.0_2de3j2mqba4wgeuiaqz2k7syrm: + resolution: {integrity: sha512-+6BGQt85OREevBDWCvhqj1yYA4+BFK4XnRZSGJionuEYmcglMZYLNNBBemwzbqUAckURaHdJSBcjHPyrtypZOw==} + engines: {node: '>=8'} + peerDependencies: + eslint: '>=5' + dependencies: + '@typescript-eslint/experimental-utils': 2.34.0_2de3j2mqba4wgeuiaqz2k7syrm + eslint: 7.32.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-plugin-prettier/3.4.1_dnozcfbeb5wiozlftdrslmvmgu: + resolution: {integrity: sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==} + engines: {node: '>=6.0.0'} + peerDependencies: + eslint: '>=5.0.0' + eslint-config-prettier: '*' + prettier: '>=1.13.0' + peerDependenciesMeta: + eslint-config-prettier: + optional: true + dependencies: + eslint: 7.32.0 + eslint-config-prettier: 6.15.0_eslint@7.32.0 + prettier: 2.6.0 + prettier-linter-helpers: 1.0.0 + dev: true + + /eslint-scope/4.0.3: + resolution: {integrity: sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==} + engines: {node: '>=4.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-scope/5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-utils/2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + dependencies: + eslint-visitor-keys: 1.3.0 + dev: true + + /eslint-visitor-keys/1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + dev: true + + /eslint-visitor-keys/2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: true + + /eslint/7.32.0: + resolution: {integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==} + engines: {node: ^10.12.0 || >=12.0.0} + hasBin: true + dependencies: + '@babel/code-frame': 7.12.11 + '@eslint/eslintrc': 0.4.3 + '@humanwhocodes/config-array': 0.5.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + enquirer: 2.3.6 + escape-string-regexp: 4.0.0 + eslint-scope: 5.1.1 + eslint-utils: 2.1.0 + eslint-visitor-keys: 2.1.0 + espree: 7.3.1 + esquery: 1.4.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 5.1.2 + globals: 13.15.0 + ignore: 4.0.6 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + js-yaml: 3.14.1 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.1 + progress: 2.0.3 + regexpp: 3.2.0 + semver: 7.3.7 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + table: 6.8.0 + text-table: 0.2.0 + v8-compile-cache: 2.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree/7.3.1: + resolution: {integrity: sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + acorn: 7.4.1 + acorn-jsx: 5.3.2_acorn@7.4.1 + eslint-visitor-keys: 1.3.0 + dev: true + + /esprima/4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /esquery/1.4.0: + resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse/4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse/4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse/5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils/2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /events/3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: true + + /evp_bytestokey/1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + dev: true + + /exec-sh/0.3.6: + resolution: {integrity: sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==} + dev: true + + /execa/1.0.0: + resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} + engines: {node: '>=6'} + dependencies: + cross-spawn: 6.0.5 + get-stream: 4.1.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + dev: true + + /execa/4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /exit/0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + dev: true + + /expand-brackets/2.1.4: + resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} + engines: {node: '>=0.10.0'} + dependencies: + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /expand-brackets/2.1.4_supports-color@6.1.0: + resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} + engines: {node: '>=0.10.0'} + dependencies: + debug: 2.6.9_supports-color@6.1.0 + define-property: 0.2.5 + extend-shallow: 2.0.1 + posix-character-classes: 0.1.1 + regex-not: 1.0.2 + snapdragon: 0.8.2_supports-color@6.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /expand-tilde/2.0.2: + resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} + engines: {node: '>=0.10.0'} + dependencies: + homedir-polyfill: 1.0.3 + dev: true + + /expect/26.6.2: + resolution: {integrity: sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + ansi-styles: 4.3.0 + jest-get-type: 26.3.0 + jest-matcher-utils: 26.6.2 + jest-message-util: 26.6.2 + jest-regex-util: 26.0.0 + dev: true + + /extend-shallow/2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: true + + /extend-shallow/3.0.2: + resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} + engines: {node: '>=0.10.0'} + dependencies: + assign-symbols: 1.0.0 + is-extendable: 1.0.1 + dev: true + + /extglob/2.0.4: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + dependencies: + 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.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /extglob/2.0.4_supports-color@6.1.0: + resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} + engines: {node: '>=0.10.0'} + dependencies: + array-unique: 0.3.2 + define-property: 1.0.0 + expand-brackets: 2.1.4_supports-color@6.1.0 + extend-shallow: 2.0.1 + fragment-cache: 0.2.1 + regex-not: 1.0.2 + snapdragon: 0.8.2_supports-color@6.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /fast-deep-equal/3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff/1.2.0: + resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} + dev: true + + /fast-json-stable-stringify/2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein/2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fb-watchman/2.0.1: + resolution: {integrity: sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==} + dependencies: + bser: 2.1.1 + dev: true + + /figgy-pudding/3.5.2: + resolution: {integrity: sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==} + dev: true + + /file-entry-cache/6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.0.4 + dev: true + + /file-uri-to-path/1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + dev: true + optional: true + + /fill-range/4.0.0: + resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-number: 3.0.0 + repeat-string: 1.6.1 + to-regex-range: 2.1.1 + dev: true + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-cache-dir/2.1.0: + resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==} + engines: {node: '>=6'} + dependencies: + commondir: 1.0.1 + make-dir: 2.1.0 + pkg-dir: 3.0.0 + dev: true + + /find-cache-dir/3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + dev: true + + /find-up/3.0.0: + resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} + engines: {node: '>=6'} + dependencies: + locate-path: 3.0.0 + dev: true + + /find-up/4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /findup-sync/3.0.0_supports-color@6.1.0: + resolution: {integrity: sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==} + engines: {node: '>= 0.10'} + dependencies: + detect-file: 1.0.0 + is-glob: 4.0.3 + micromatch: 3.1.10_supports-color@6.1.0 + resolve-dir: 1.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /flat-cache/3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.5 + rimraf: 3.0.2 + dev: true + + /flatted/3.2.5: + resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} + dev: true + + /flush-write-stream/1.1.1: + resolution: {integrity: sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==} + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.7 + dev: true + + /for-in/1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + dev: true + + /form-data/3.0.1: + resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + + /fragment-cache/0.2.1: + resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} + engines: {node: '>=0.10.0'} + dependencies: + map-cache: 0.2.2 + dev: true + + /from2/2.3.0: + resolution: {integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==} + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.7 + dev: true + + /fs-minipass/2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.1.6 + dev: true + + /fs-write-stream-atomic/1.0.10: + resolution: {integrity: sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==} + dependencies: + graceful-fs: 4.2.10 + iferr: 0.1.5 + imurmurhash: 0.1.4 + readable-stream: 2.3.7 + dev: true + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents/1.2.13: + resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==} + engines: {node: '>= 4.0'} + os: [darwin] + deprecated: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2. + requiresBuild: true + dependencies: + bindings: 1.5.0 + nan: 2.16.0 + dev: true + optional: true + + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /functional-red-black-tree/1.0.1: + resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} + dev: true + + /gauge/3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: true + + /gensync/1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-caller-file/2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-package-type/0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: true + + /get-stdin/6.0.0: + resolution: {integrity: sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==} + engines: {node: '>=4'} + dev: true + + /get-stream/4.1.0: + resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} + engines: {node: '>=6'} + dependencies: + pump: 3.0.0 + dev: true + + /get-stream/5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: true + + /get-value/2.0.6: + resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} + engines: {node: '>=0.10.0'} + dev: true + + /glob-parent/3.1.0: + resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==} + dependencies: + is-glob: 3.1.0 + path-dirname: 1.0.2 + dev: true + optional: true + + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /global-modules/1.0.0: + resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==} + engines: {node: '>=0.10.0'} + dependencies: + global-prefix: 1.0.2 + is-windows: 1.0.2 + resolve-dir: 1.0.1 + dev: true + + /global-modules/2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + dependencies: + global-prefix: 3.0.0 + dev: true + + /global-prefix/1.0.2: + resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} + engines: {node: '>=0.10.0'} + dependencies: + expand-tilde: 2.0.2 + homedir-polyfill: 1.0.3 + ini: 1.3.8 + is-windows: 1.0.2 + which: 1.3.1 + dev: true + + /global-prefix/3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + dev: true + + /globals/11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals/13.15.0: + resolution: {integrity: sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /graceful-fs/4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + dev: true + + /growly/1.3.0: + resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} + dev: true + optional: true + + /has-flag/3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-unicode/2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + dev: true + + /has-value/0.3.1: + resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} + engines: {node: '>=0.10.0'} + dependencies: + get-value: 2.0.6 + has-values: 0.1.4 + isobject: 2.1.0 + dev: true + + /has-value/1.0.0: + resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} + engines: {node: '>=0.10.0'} + dependencies: + get-value: 2.0.6 + has-values: 1.0.0 + isobject: 3.0.1 + dev: true + + /has-values/0.1.4: + resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} + engines: {node: '>=0.10.0'} + dev: true + + /has-values/1.0.0: + resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + dev: true + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /hash-base/3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.0 + safe-buffer: 5.2.1 + dev: true + + /hash.js/1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + dev: true + + /hmac-drbg/1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + dev: true + + /homedir-polyfill/1.0.3: + resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} + engines: {node: '>=0.10.0'} + dependencies: + parse-passwd: 1.0.0 + dev: true + + /hosted-git-info/2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /html-encoding-sniffer/2.0.1: + resolution: {integrity: sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==} + engines: {node: '>=10'} + dependencies: + whatwg-encoding: 1.0.5 + dev: true + + /html-escaper/2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /http-proxy-agent/4.0.1: + resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 1.1.2 + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /https-browserify/1.0.0: + resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} + dev: true + + /https-proxy-agent/5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /human-signals/1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + dev: true + + /iconv-lite/0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /ieee754/1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + + /iferr/0.1.5: + resolution: {integrity: sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==} + dev: true + + /ignore/4.0.6: + resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} + engines: {node: '>= 4'} + dev: true + + /import-fresh/3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /import-local/2.0.0: + resolution: {integrity: sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + pkg-dir: 3.0.0 + resolve-cwd: 2.0.0 + dev: true + + /import-local/3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + dev: true + + /imurmurhash/0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string/4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /infer-owner/1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + dev: true + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.1: + resolution: {integrity: sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==} + dev: true + + /inherits/2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /ini/1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /interpret/1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + dev: true + + /is-accessor-descriptor/0.1.6: + resolution: {integrity: sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /is-accessor-descriptor/1.0.0: + resolution: {integrity: sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 6.0.3 + dev: true + + /is-arrayish/0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-binary-path/1.0.1: + resolution: {integrity: sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==} + engines: {node: '>=0.10.0'} + dependencies: + binary-extensions: 1.13.1 + dev: true + optional: true + + /is-binary-path/2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + optional: true + + /is-buffer/1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + dev: true + + /is-ci/2.0.0: + resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} + hasBin: true + dependencies: + ci-info: 2.0.0 + dev: true + + /is-core-module/2.9.0: + resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} + dependencies: + has: 1.0.3 + dev: true + + /is-data-descriptor/0.1.4: + resolution: {integrity: sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /is-data-descriptor/1.0.0: + resolution: {integrity: sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 6.0.3 + dev: true + + /is-descriptor/0.1.6: + resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} + engines: {node: '>=0.10.0'} + dependencies: + is-accessor-descriptor: 0.1.6 + is-data-descriptor: 0.1.4 + kind-of: 5.1.0 + dev: true + + /is-descriptor/1.0.2: + resolution: {integrity: sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==} + engines: {node: '>=0.10.0'} + dependencies: + is-accessor-descriptor: 1.0.0 + is-data-descriptor: 1.0.0 + kind-of: 6.0.3 + dev: true + + /is-docker/2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + dev: true + optional: true + + /is-extendable/0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: true + + /is-extendable/1.0.1: + resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} + engines: {node: '>=0.10.0'} + dependencies: + is-plain-object: 2.0.4 + dev: true + + /is-extglob/2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point/2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + dev: true + + /is-fullwidth-code-point/3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-generator-fn/2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + dev: true + + /is-glob/3.1.0: + resolution: {integrity: sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + optional: true + + /is-glob/4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number/3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-plain-object/2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /is-potential-custom-element-name/1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + dev: true + + /is-stream/1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-stream/2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-typedarray/1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: true + + /is-windows/1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: true + + /is-wsl/1.1.0: + resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==} + engines: {node: '>=4'} + dev: true + + /is-wsl/2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + dev: true + optional: true + + /isarray/1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: true + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /isobject/2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + dependencies: + isarray: 1.0.0 + dev: true + + /isobject/3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: true + + /istanbul-lib-coverage/3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-instrument/4.0.3: + resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.18.2 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-instrument/5.2.0: + resolution: {integrity: sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.18.2 + '@babel/parser': 7.18.4 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-report/3.0.0: + resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} + engines: {node: '>=8'} + dependencies: + istanbul-lib-coverage: 3.2.0 + make-dir: 3.1.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps/4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports/3.1.4: + resolution: {integrity: sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.0 + dev: true + + /jest-changed-files/26.6.2: + resolution: {integrity: sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + execa: 4.1.0 + throat: 5.0.0 + dev: true + + /jest-cli/26.6.3_canvas@2.9.1: + resolution: {integrity: sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==} + engines: {node: '>= 10.14.2'} + hasBin: true + dependencies: + '@jest/core': 26.6.3_canvas@2.9.1 + '@jest/test-result': 26.6.2 + '@jest/types': 26.6.2 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.10 + import-local: 3.1.0 + is-ci: 2.0.0 + jest-config: 26.6.3_canvas@2.9.1 + jest-util: 26.6.2 + jest-validate: 26.6.2 + prompts: 2.4.2 + yargs: 15.4.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + dev: true + + /jest-config/26.6.3_canvas@2.9.1: + resolution: {integrity: sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==} + engines: {node: '>= 10.14.2'} + peerDependencies: + ts-node: '>=9.0.0' + peerDependenciesMeta: + ts-node: + optional: true + dependencies: + '@babel/core': 7.18.2 + '@jest/test-sequencer': 26.6.3_canvas@2.9.1 + '@jest/types': 26.6.2 + babel-jest: 26.6.3_@babel+core@7.18.2 + chalk: 4.1.2 + deepmerge: 4.2.2 + glob: 7.2.3 + graceful-fs: 4.2.10 + jest-environment-jsdom: 26.6.2_canvas@2.9.1 + jest-environment-node: 26.6.2 + jest-get-type: 26.3.0 + jest-jasmine2: 26.6.3_canvas@2.9.1 + jest-regex-util: 26.0.0 + jest-resolve: 26.6.2 + jest-util: 26.6.2 + jest-validate: 26.6.2 + micromatch: 4.0.5 + pretty-format: 26.6.2 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /jest-diff/26.6.2: + resolution: {integrity: sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==} + engines: {node: '>= 10.14.2'} + dependencies: + chalk: 4.1.2 + diff-sequences: 26.6.2 + jest-get-type: 26.3.0 + pretty-format: 26.6.2 + dev: true + + /jest-docblock/26.0.0: + resolution: {integrity: sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==} + engines: {node: '>= 10.14.2'} + dependencies: + detect-newline: 3.1.0 + dev: true + + /jest-each/26.6.2: + resolution: {integrity: sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + chalk: 4.1.2 + jest-get-type: 26.3.0 + jest-util: 26.6.2 + pretty-format: 26.6.2 + dev: true + + /jest-environment-jsdom/26.6.2_canvas@2.9.1: + resolution: {integrity: sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/environment': 26.6.2 + '@jest/fake-timers': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 17.0.41 + jest-mock: 26.6.2 + jest-util: 26.6.2 + jsdom: 16.7.0_canvas@2.9.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + dev: true + + /jest-environment-node/26.6.2: + resolution: {integrity: sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/environment': 26.6.2 + '@jest/fake-timers': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 17.0.41 + jest-mock: 26.6.2 + jest-util: 26.6.2 + dev: true + + /jest-get-type/26.3.0: + resolution: {integrity: sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==} + engines: {node: '>= 10.14.2'} + dev: true + + /jest-haste-map/26.6.2: + resolution: {integrity: sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + '@types/graceful-fs': 4.1.5 + '@types/node': 17.0.41 + anymatch: 3.1.2 + fb-watchman: 2.0.1 + graceful-fs: 4.2.10 + jest-regex-util: 26.0.0 + jest-serializer: 26.6.2 + jest-util: 26.6.2 + jest-worker: 26.6.2 + micromatch: 4.0.5 + sane: 4.1.0 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.2 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-jasmine2/26.6.3_canvas@2.9.1: + resolution: {integrity: sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==} + engines: {node: '>= 10.14.2'} + dependencies: + '@babel/traverse': 7.18.2 + '@jest/environment': 26.6.2 + '@jest/source-map': 26.6.2 + '@jest/test-result': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 17.0.41 + chalk: 4.1.2 + co: 4.6.0 + expect: 26.6.2 + is-generator-fn: 2.1.0 + jest-each: 26.6.2 + jest-matcher-utils: 26.6.2 + jest-message-util: 26.6.2 + jest-runtime: 26.6.3_canvas@2.9.1 + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + pretty-format: 26.6.2 + throat: 5.0.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + dev: true + + /jest-leak-detector/26.6.2: + resolution: {integrity: sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==} + engines: {node: '>= 10.14.2'} + dependencies: + jest-get-type: 26.3.0 + pretty-format: 26.6.2 + dev: true + + /jest-matcher-utils/26.6.2: + resolution: {integrity: sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==} + engines: {node: '>= 10.14.2'} + dependencies: + chalk: 4.1.2 + jest-diff: 26.6.2 + jest-get-type: 26.3.0 + pretty-format: 26.6.2 + dev: true + + /jest-message-util/26.6.2: + resolution: {integrity: sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==} + engines: {node: '>= 10.14.2'} + dependencies: + '@babel/code-frame': 7.16.7 + '@jest/types': 26.6.2 + '@types/stack-utils': 2.0.1 + chalk: 4.1.2 + graceful-fs: 4.2.10 + micromatch: 4.0.5 + pretty-format: 26.6.2 + slash: 3.0.0 + stack-utils: 2.0.5 + dev: true + + /jest-mock/26.6.2: + resolution: {integrity: sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + '@types/node': 17.0.41 + dev: true + + /jest-pnp-resolver/1.2.2_jest-resolve@26.6.2: + resolution: {integrity: sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 26.6.2 + dev: true + + /jest-regex-util/26.0.0: + resolution: {integrity: sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==} + engines: {node: '>= 10.14.2'} + dev: true + + /jest-resolve-dependencies/26.6.3: + resolution: {integrity: sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + jest-regex-util: 26.0.0 + jest-snapshot: 26.6.2 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-resolve/26.6.2: + resolution: {integrity: sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + chalk: 4.1.2 + graceful-fs: 4.2.10 + jest-pnp-resolver: 1.2.2_jest-resolve@26.6.2 + jest-util: 26.6.2 + read-pkg-up: 7.0.1 + resolve: 1.22.0 + slash: 3.0.0 + dev: true + + /jest-runner/26.6.3_canvas@2.9.1: + resolution: {integrity: sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/console': 26.6.2 + '@jest/environment': 26.6.2 + '@jest/test-result': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 17.0.41 + chalk: 4.1.2 + emittery: 0.7.2 + exit: 0.1.2 + graceful-fs: 4.2.10 + jest-config: 26.6.3_canvas@2.9.1 + jest-docblock: 26.0.0 + jest-haste-map: 26.6.2 + jest-leak-detector: 26.6.2 + jest-message-util: 26.6.2 + jest-resolve: 26.6.2 + jest-runtime: 26.6.3_canvas@2.9.1 + jest-util: 26.6.2 + jest-worker: 26.6.2 + source-map-support: 0.5.21 + throat: 5.0.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + dev: true + + /jest-runtime/26.6.3_canvas@2.9.1: + resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==} + engines: {node: '>= 10.14.2'} + hasBin: true + dependencies: + '@jest/console': 26.6.2 + '@jest/environment': 26.6.2 + '@jest/fake-timers': 26.6.2 + '@jest/globals': 26.6.2 + '@jest/source-map': 26.6.2 + '@jest/test-result': 26.6.2 + '@jest/transform': 26.6.2 + '@jest/types': 26.6.2 + '@types/yargs': 15.0.14 + chalk: 4.1.2 + cjs-module-lexer: 0.6.0 + collect-v8-coverage: 1.0.1 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.10 + jest-config: 26.6.3_canvas@2.9.1 + jest-haste-map: 26.6.2 + jest-message-util: 26.6.2 + jest-mock: 26.6.2 + jest-regex-util: 26.0.0 + jest-resolve: 26.6.2 + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + jest-validate: 26.6.2 + slash: 3.0.0 + strip-bom: 4.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + dev: true + + /jest-serializer/26.6.2: + resolution: {integrity: sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==} + engines: {node: '>= 10.14.2'} + dependencies: + '@types/node': 17.0.41 + graceful-fs: 4.2.10 + dev: true + + /jest-snapshot/26.6.2: + resolution: {integrity: sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==} + engines: {node: '>= 10.14.2'} + dependencies: + '@babel/types': 7.18.4 + '@jest/types': 26.6.2 + '@types/babel__traverse': 7.17.1 + '@types/prettier': 2.6.0 + chalk: 4.1.2 + expect: 26.6.2 + graceful-fs: 4.2.10 + jest-diff: 26.6.2 + jest-get-type: 26.3.0 + jest-haste-map: 26.6.2 + jest-matcher-utils: 26.6.2 + jest-message-util: 26.6.2 + jest-resolve: 26.6.2 + natural-compare: 1.4.0 + pretty-format: 26.6.2 + semver: 7.3.7 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-util/26.6.2: + resolution: {integrity: sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + '@types/node': 17.0.41 + chalk: 4.1.2 + graceful-fs: 4.2.10 + is-ci: 2.0.0 + micromatch: 4.0.5 + dev: true + + /jest-validate/26.6.2: + resolution: {integrity: sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/types': 26.6.2 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 26.3.0 + leven: 3.1.0 + pretty-format: 26.6.2 + dev: true + + /jest-watcher/26.6.2: + resolution: {integrity: sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==} + engines: {node: '>= 10.14.2'} + dependencies: + '@jest/test-result': 26.6.2 + '@jest/types': 26.6.2 + '@types/node': 17.0.41 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + jest-util: 26.6.2 + string-length: 4.0.2 + dev: true + + /jest-worker/26.6.2: + resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 17.0.41 + merge-stream: 2.0.0 + supports-color: 7.2.0 + dev: true + + /jest/26.6.3_canvas@2.9.1: + resolution: {integrity: sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==} + engines: {node: '>= 10.14.2'} + hasBin: true + dependencies: + '@jest/core': 26.6.3_canvas@2.9.1 + import-local: 3.1.0 + jest-cli: 26.6.3_canvas@2.9.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + dev: true + + /js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml/3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /jsdom/16.7.0_canvas@2.9.1: + resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==} + engines: {node: '>=10'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + abab: 2.0.6 + acorn: 8.7.1 + acorn-globals: 6.0.0 + canvas: 2.9.1 + cssom: 0.4.4 + cssstyle: 2.3.0 + data-urls: 2.0.0 + decimal.js: 10.3.1 + domexception: 2.0.1 + escodegen: 2.0.0 + form-data: 3.0.1 + html-encoding-sniffer: 2.0.1 + http-proxy-agent: 4.0.1 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.0 + parse5: 6.0.1 + saxes: 5.0.1 + symbol-tree: 3.2.4 + tough-cookie: 4.0.0 + w3c-hr-time: 1.0.2 + w3c-xmlserializer: 2.0.0 + webidl-conversions: 6.1.0 + whatwg-encoding: 1.0.5 + whatwg-mimetype: 2.3.0 + whatwg-url: 8.7.0 + ws: 7.5.8 + xml-name-validator: 3.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /jsesc/2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /json-parse-better-errors/1.0.2: + resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} + dev: true + + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse/0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-schema-traverse/1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-stable-stringify-without-jsonify/1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5/1.0.1: + resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} + hasBin: true + dependencies: + minimist: 1.2.6 + dev: true + + /json5/2.2.1: + resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /kind-of/3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + dev: true + + /kind-of/4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + dev: true + + /kind-of/5.1.0: + resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} + engines: {node: '>=0.10.0'} + dev: true + + /kind-of/6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /kleur/3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: true + + /leven/3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: true + + /levn/0.3.0: + resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + dev: true + + /levn/0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lines-and-columns/1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /loader-runner/2.4.0: + resolution: {integrity: sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==} + engines: {node: '>=4.3.0 <5.0.0 || >=5.10'} + dev: true + + /loader-utils/1.4.0: + resolution: {integrity: sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==} + engines: {node: '>=4.0.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 1.0.1 + dev: true + + /loader-utils/2.0.2: + resolution: {integrity: sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==} + engines: {node: '>=8.9.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.1 + dev: true + + /locate-path/3.0.0: + resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} + engines: {node: '>=6'} + dependencies: + p-locate: 3.0.0 + path-exists: 3.0.0 + dev: true + + /locate-path/5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /lodash.merge/4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash.truncate/4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + dev: true + + /lodash/4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /lru-cache/5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /make-dir/2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + dependencies: + pify: 4.0.1 + semver: 5.7.1 + dev: true + + /make-dir/3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.0 + dev: true + + /make-error/1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /makeerror/1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + dependencies: + tmpl: 1.0.5 + dev: true + + /map-cache/0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + dev: true + + /map-visit/1.0.0: + resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} + engines: {node: '>=0.10.0'} + dependencies: + object-visit: 1.0.1 + dev: true + + /md5.js/1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + + /memory-fs/0.4.1: + resolution: {integrity: sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==} + dependencies: + errno: 0.1.8 + readable-stream: 2.3.7 + dev: true + + /memory-fs/0.5.0: + resolution: {integrity: sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==} + engines: {node: '>=4.3.0 <5.0.0 || >=5.10'} + dependencies: + errno: 0.1.8 + readable-stream: 2.3.7 + dev: true + + /merge-stream/2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /micromatch/3.1.10: + resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2 + define-property: 2.0.2 + extend-shallow: 3.0.2 + extglob: 2.0.4 + fragment-cache: 0.2.1 + kind-of: 6.0.3 + nanomatch: 1.2.13 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /micromatch/3.1.10_supports-color@6.1.0: + resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 4.0.0 + array-unique: 0.3.2 + braces: 2.3.2_supports-color@6.1.0 + define-property: 2.0.2 + extend-shallow: 3.0.2 + extglob: 2.0.4_supports-color@6.1.0 + fragment-cache: 0.2.1 + kind-of: 6.0.3 + nanomatch: 1.2.13_supports-color@6.1.0 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2_supports-color@6.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /miller-rabin/4.0.1: + resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} + hasBin: true + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + dev: true + + /mime-db/1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: true + + /mime-types/2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + + /mimic-fn/2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-response/2.1.0: + resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} + engines: {node: '>=8'} + dev: true + + /minimalistic-assert/1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + dev: true + + /minimalistic-crypto-utils/1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + dev: true + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist/1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + dev: true + + /minipass-collect/1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.1.6 + dev: true + + /minipass-flush/1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.1.6 + dev: true + + /minipass-pipeline/1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + dependencies: + minipass: 3.1.6 + dev: true + + /minipass/3.1.6: + resolution: {integrity: sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: true + + /minizlib/2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.1.6 + yallist: 4.0.0 + dev: true + + /mississippi/3.0.0: + resolution: {integrity: sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==} + engines: {node: '>=4.0.0'} + dependencies: + concat-stream: 1.6.2 + duplexify: 3.7.1 + end-of-stream: 1.4.4 + flush-write-stream: 1.1.1 + from2: 2.3.0 + parallel-transform: 1.2.0 + pump: 3.0.0 + pumpify: 1.5.1 + stream-each: 1.2.3 + through2: 2.0.5 + dev: true + + /mixin-deep/1.3.2: + resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} + engines: {node: '>=0.10.0'} + dependencies: + for-in: 1.0.2 + is-extendable: 1.0.1 + dev: true + + /mkdirp/0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.6 + dev: true + + /mkdirp/1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /move-concurrently/1.0.1: + resolution: {integrity: sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==} + dependencies: + aproba: 1.2.0 + copy-concurrently: 1.0.5 + fs-write-stream-atomic: 1.0.10 + mkdirp: 0.5.6 + rimraf: 2.7.1 + run-queue: 1.0.3 + dev: true + + /ms/2.0.0: + resolution: {integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=} + dev: true + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /nan/2.16.0: + resolution: {integrity: sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==} + dev: true + + /nanomatch/1.2.13: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + dependencies: + 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.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /nanomatch/1.2.13_supports-color@6.1.0: + resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} + engines: {node: '>=0.10.0'} + dependencies: + 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.3 + object.pick: 1.3.0 + regex-not: 1.0.2 + snapdragon: 0.8.2_supports-color@6.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /natural-compare/1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /neo-async/2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: true + + /nice-try/1.0.5: + resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + dev: true + + /node-fetch/2.6.7: + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + + /node-int64/0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: true + + /node-libs-browser/2.2.1: + resolution: {integrity: sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==} + dependencies: + assert: 1.5.0 + browserify-zlib: 0.2.0 + buffer: 4.9.2 + console-browserify: 1.2.0 + constants-browserify: 1.0.0 + crypto-browserify: 3.12.0 + domain-browser: 1.2.0 + events: 3.3.0 + https-browserify: 1.0.0 + os-browserify: 0.3.0 + path-browserify: 0.0.1 + process: 0.11.10 + punycode: 1.4.1 + querystring-es3: 0.2.1 + readable-stream: 2.3.7 + stream-browserify: 2.0.2 + stream-http: 2.8.3 + string_decoder: 1.3.0 + timers-browserify: 2.0.12 + tty-browserify: 0.0.0 + url: 0.11.0 + util: 0.11.1 + vm-browserify: 1.1.2 + dev: true + + /node-notifier/8.0.2: + resolution: {integrity: sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==} + requiresBuild: true + dependencies: + growly: 1.3.0 + is-wsl: 2.2.0 + semver: 7.3.7 + shellwords: 0.1.1 + uuid: 8.3.2 + which: 2.0.2 + dev: true + optional: true + + /node-releases/2.0.5: + resolution: {integrity: sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==} + dev: true + + /nopt/5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: true + + /normalize-package-data/2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.0 + semver: 5.7.1 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path/2.1.1: + resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} + engines: {node: '>=0.10.0'} + dependencies: + remove-trailing-separator: 1.1.0 + dev: true + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-run-path/2.0.2: + resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + engines: {node: '>=4'} + dependencies: + path-key: 2.0.1 + dev: true + + /npm-run-path/4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /npmlog/5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + dev: true + + /nwsapi/2.2.0: + resolution: {integrity: sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==} + dev: true + + /object-assign/4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-copy/0.1.0: + resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} + engines: {node: '>=0.10.0'} + dependencies: + copy-descriptor: 0.1.1 + define-property: 0.2.5 + kind-of: 3.2.2 + dev: true + + /object-visit/1.0.1: + resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /object.pick/1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime/5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /optionator/0.8.3: + resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.3.0 + prelude-ls: 1.1.2 + type-check: 0.3.2 + word-wrap: 1.2.3 + dev: true + + /optionator/0.9.1: + resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.3 + dev: true + + /os-browserify/0.3.0: + resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} + dev: true + + /p-each-series/2.2.0: + resolution: {integrity: sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==} + engines: {node: '>=8'} + dev: true + + /p-finally/1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + dev: true + + /p-limit/2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit/3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate/3.0.0: + resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} + engines: {node: '>=6'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate/4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-map/4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + dev: true + + /p-try/2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /pako/1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + dev: true + + /parallel-transform/1.2.0: + resolution: {integrity: sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==} + dependencies: + cyclist: 1.0.1 + inherits: 2.0.4 + readable-stream: 2.3.7 + dev: true + + /parent-module/1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-asn1/5.1.6: + resolution: {integrity: sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==} + dependencies: + asn1.js: 5.4.1 + browserify-aes: 1.2.0 + evp_bytestokey: 1.0.3 + pbkdf2: 3.1.2 + safe-buffer: 5.2.1 + dev: true + + /parse-json/5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.16.7 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parse-passwd/1.0.0: + resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} + engines: {node: '>=0.10.0'} + dev: true + + /parse5/6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + dev: true + + /pascalcase/0.1.1: + resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} + engines: {node: '>=0.10.0'} + dev: true + + /path-browserify/0.0.1: + resolution: {integrity: sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==} + dev: true + + /path-dirname/1.0.2: + resolution: {integrity: sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==} + dev: true + optional: true + + /path-exists/3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + dev: true + + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key/2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + dev: true + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /pbkdf2/3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} + dependencies: + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + dev: true + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pify/4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + dev: true + + /pirates/4.0.5: + resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==} + engines: {node: '>= 6'} + dev: true + + /pkg-dir/3.0.0: + resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==} + engines: {node: '>=6'} + dependencies: + find-up: 3.0.0 + dev: true + + /pkg-dir/4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true + + /posix-character-classes/0.1.1: + resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} + engines: {node: '>=0.10.0'} + dev: true + + /prelude-ls/1.1.2: + resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} + engines: {node: '>= 0.8.0'} + dev: true + + /prelude-ls/1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-linter-helpers/1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.2.0 + dev: true + + /prettier/2.6.0: + resolution: {integrity: sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /pretty-format/26.6.2: + resolution: {integrity: sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==} + engines: {node: '>= 10'} + dependencies: + '@jest/types': 26.6.2 + ansi-regex: 5.0.1 + ansi-styles: 4.3.0 + react-is: 17.0.2 + dev: true + + /process-nextick-args/2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: true + + /process/0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: true + + /progress/2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + dev: true + + /promise-inflight/1.0.1_bluebird@3.7.2: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + dependencies: + bluebird: 3.7.2 + dev: true + + /prompts/2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: true + + /prr/1.0.1: + resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + dev: true + + /psl/1.8.0: + resolution: {integrity: sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==} + dev: true + + /public-encrypt/4.0.3: + resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} + dependencies: + bn.js: 4.12.0 + browserify-rsa: 4.1.0 + create-hash: 1.2.0 + parse-asn1: 5.1.6 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: true + + /pump/2.0.1: + resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + + /pump/3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + + /pumpify/1.5.1: + resolution: {integrity: sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==} + dependencies: + duplexify: 3.7.1 + inherits: 2.0.4 + pump: 2.0.1 + dev: true + + /punycode/1.3.2: + resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==} + dev: true + + /punycode/1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + dev: true + + /punycode/2.1.1: + resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + engines: {node: '>=6'} + dev: true + + /querystring-es3/0.2.1: + resolution: {integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==} + engines: {node: '>=0.4.x'} + dev: true + + /querystring/0.2.0: + resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==} + engines: {node: '>=0.4.x'} + deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. + dev: true + + /randombytes/2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /randomfill/1.0.4: + resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + dependencies: + randombytes: 2.1.0 + safe-buffer: 5.2.1 + dev: true + + /react-is/17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + dev: true + + /read-pkg-up/7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg/5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.1 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + + /readable-stream/2.3.7: + resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: true + + /readable-stream/3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /readdirp/2.2.1: + resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} + engines: {node: '>=0.10'} + dependencies: + graceful-fs: 4.2.10 + micromatch: 3.1.10 + readable-stream: 2.3.7 + transitivePeerDependencies: + - supports-color + dev: true + optional: true + + /readdirp/3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + optional: true + + /regex-not/1.0.2: + resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + safe-regex: 1.1.0 + dev: true + + /regexpp/3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: true + + /remove-trailing-separator/1.1.0: + resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} + dev: true + + /repeat-element/1.1.4: + resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} + engines: {node: '>=0.10.0'} + dev: true + + /repeat-string/1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + dev: true + + /require-directory/2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /require-from-string/2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /require-main-filename/2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + dev: true + + /resolve-cwd/2.0.0: + resolution: {integrity: sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg==} + engines: {node: '>=4'} + dependencies: + resolve-from: 3.0.0 + dev: true + + /resolve-cwd/3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + dependencies: + resolve-from: 5.0.0 + dev: true + + /resolve-dir/1.0.1: + resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} + engines: {node: '>=0.10.0'} + dependencies: + expand-tilde: 2.0.2 + global-modules: 1.0.0 + dev: true + + /resolve-from/3.0.0: + resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} + engines: {node: '>=4'} + dev: true + + /resolve-from/4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from/5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve-url/0.2.1: + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} + deprecated: https://github.com/lydell/resolve-url#deprecated + dev: true + + /resolve/1.22.0: + resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} + hasBin: true + dependencies: + is-core-module: 2.9.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /ret/0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + dev: true + + /rimraf/2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /ripemd160/2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + dev: true + + /rsvp/4.8.5: + resolution: {integrity: sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==} + engines: {node: 6.* || >= 7.*} + dev: true + + /run-queue/1.0.3: + resolution: {integrity: sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==} + dependencies: + aproba: 1.2.0 + dev: true + + /safe-buffer/5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: true + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /safe-regex/1.1.0: + resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} + dependencies: + ret: 0.1.15 + dev: true + + /safer-buffer/2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true + + /sane/4.1.0: + resolution: {integrity: sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==} + engines: {node: 6.* || 8.* || >= 10.*} + deprecated: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added + hasBin: true + dependencies: + '@cnakazawa/watch': 1.0.4 + anymatch: 2.0.0 + capture-exit: 2.0.0 + exec-sh: 0.3.6 + execa: 1.0.0 + fb-watchman: 2.0.1 + micromatch: 3.1.10 + minimist: 1.2.6 + walker: 1.0.8 + transitivePeerDependencies: + - supports-color + dev: true + + /saxes/5.0.1: + resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} + engines: {node: '>=10'} + dependencies: + xmlchars: 2.2.0 + dev: true + + /schema-utils/1.0.0: + resolution: {integrity: sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==} + engines: {node: '>= 4'} + dependencies: + ajv: 6.12.6 + ajv-errors: 1.0.1_ajv@6.12.6 + ajv-keywords: 3.5.2_ajv@6.12.6 + dev: true + + /schema-utils/3.1.1: + resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.11 + ajv: 6.12.6 + ajv-keywords: 3.5.2_ajv@6.12.6 + dev: true + + /semver/5.7.1: + resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + hasBin: true + dev: true + + /semver/6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + hasBin: true + dev: true + + /semver/7.3.7: + resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /serialize-javascript/4.0.0: + resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} + dependencies: + randombytes: 2.1.0 + dev: true + + /serialize-javascript/5.0.1: + resolution: {integrity: sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==} + dependencies: + randombytes: 2.1.0 + dev: true + + /set-blocking/2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: true + + /set-value/2.0.1: + resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-extendable: 0.1.1 + is-plain-object: 2.0.4 + split-string: 3.1.0 + dev: true + + /setimmediate/1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + dev: true + + /sha.js/2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: true + + /shebang-command/1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: true + + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex/1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + dev: true + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /shellwords/0.1.1: + resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} + dev: true + optional: true + + /signal-exit/3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /simple-concat/1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + dev: true + + /simple-get/3.1.1: + resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} + dependencies: + decompress-response: 4.2.1 + once: 1.4.0 + simple-concat: 1.0.1 + dev: true + + /sisteransi/1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + + /slash/3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slice-ansi/4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /snapdragon-node/2.1.1: + resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 1.0.0 + isobject: 3.0.1 + snapdragon-util: 3.0.1 + dev: true + + /snapdragon-util/3.0.1: + resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /snapdragon/0.8.2: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + dependencies: + base: 0.11.2 + debug: 2.6.9 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /snapdragon/0.8.2_supports-color@6.1.0: + resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} + engines: {node: '>=0.10.0'} + dependencies: + base: 0.11.2 + debug: 2.6.9_supports-color@6.1.0 + define-property: 0.2.5 + extend-shallow: 2.0.1 + map-cache: 0.2.2 + source-map: 0.5.7 + source-map-resolve: 0.5.3 + use: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /source-list-map/2.0.1: + resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==} + dev: true + + /source-map-resolve/0.5.3: + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.0 + resolve-url: 0.2.1 + source-map-url: 0.4.1 + urix: 0.1.0 + dev: true + + /source-map-support/0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map-url/0.4.1: + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated + dev: true + + /source-map/0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map/0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + dev: true + + /spdx-correct/3.1.1: + resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.11 + dev: true + + /spdx-exceptions/2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse/3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.11 + dev: true + + /spdx-license-ids/3.0.11: + resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==} + dev: true + + /split-string/3.1.0: + resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 3.0.2 + dev: true + + /sprintf-js/1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /ssri/6.0.2: + resolution: {integrity: sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==} + dependencies: + figgy-pudding: 3.5.2 + dev: true + + /ssri/8.0.1: + resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.1.6 + dev: true + + /stack-utils/2.0.5: + resolution: {integrity: sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 2.0.0 + dev: true + + /static-extend/0.1.2: + resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 0.2.5 + object-copy: 0.1.0 + dev: true + + /stream-browserify/2.0.2: + resolution: {integrity: sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==} + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.7 + dev: true + + /stream-each/1.2.3: + resolution: {integrity: sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==} + dependencies: + end-of-stream: 1.4.4 + stream-shift: 1.0.1 + dev: true + + /stream-http/2.8.3: + resolution: {integrity: sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==} + dependencies: + builtin-status-codes: 3.0.0 + inherits: 2.0.4 + readable-stream: 2.3.7 + to-arraybuffer: 1.0.1 + xtend: 4.0.2 + dev: true + + /stream-shift/1.0.1: + resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} + dev: true + + /string-length/4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + dev: true + + /string-width/3.1.0: + resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==} + engines: {node: '>=6'} + dependencies: + emoji-regex: 7.0.3 + is-fullwidth-code-point: 2.0.0 + strip-ansi: 5.2.0 + dev: true + + /string-width/4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string_decoder/1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /string_decoder/1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-ansi/5.2.0: + resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} + engines: {node: '>=6'} + dependencies: + ansi-regex: 4.1.1 + dev: true + + /strip-ansi/6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-bom/4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + + /strip-eof/1.0.0: + resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} + engines: {node: '>=0.10.0'} + dev: true + + /strip-final-newline/2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-json-comments/3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /supports-color/5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color/6.1.0: + resolution: {integrity: sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==} + engines: {node: '>=6'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color/7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-hyperlinks/2.2.0: + resolution: {integrity: sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + dev: true + + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /symbol-tree/3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + dev: true + + /table/6.8.0: + resolution: {integrity: sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==} + engines: {node: '>=10.0.0'} + dependencies: + ajv: 8.11.0 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /tapable/1.1.3: + resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==} + engines: {node: '>=6'} + dev: true + + /tar/6.1.11: + resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} + engines: {node: '>= 10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 3.1.6 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: true + + /terminal-link/2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.2.0 + dev: true + + /terser-webpack-plugin/1.4.5_webpack@4.46.0: + resolution: {integrity: sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==} + engines: {node: '>= 6.9.0'} + peerDependencies: + webpack: ^4.0.0 + dependencies: + cacache: 12.0.4 + find-cache-dir: 2.1.0 + is-wsl: 1.1.0 + schema-utils: 1.0.0 + serialize-javascript: 4.0.0 + source-map: 0.6.1 + terser: 4.8.0 + webpack: 4.46.0_webpack-cli@3.3.12 + webpack-sources: 1.4.3 + worker-farm: 1.7.0 + dev: true + + /terser-webpack-plugin/4.2.3_webpack@4.46.0: + resolution: {integrity: sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==} + engines: {node: '>= 10.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + dependencies: + cacache: 15.3.0 + find-cache-dir: 3.3.2 + jest-worker: 26.6.2 + p-limit: 3.1.0 + schema-utils: 3.1.1 + serialize-javascript: 5.0.1 + source-map: 0.6.1 + terser: 5.14.0 + webpack: 4.46.0_webpack-cli@3.3.12 + webpack-sources: 1.4.3 + transitivePeerDependencies: + - bluebird + dev: true + + /terser/4.8.0: + resolution: {integrity: sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + acorn: 8.7.1 + commander: 2.20.3 + source-map: 0.6.1 + source-map-support: 0.5.21 + dev: true + + /terser/5.14.0: + resolution: {integrity: sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.2 + acorn: 8.7.1 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + + /test-exclude/6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + + /text-table/0.2.0: + resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=} + dev: true + + /throat/5.0.0: + resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==} + dev: true + + /through2/2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + dependencies: + readable-stream: 2.3.7 + xtend: 4.0.2 + dev: true + + /timers-browserify/2.0.12: + resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} + engines: {node: '>=0.6.0'} + dependencies: + setimmediate: 1.0.5 + dev: true + + /tmpl/1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + dev: true + + /to-arraybuffer/1.0.1: + resolution: {integrity: sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=} + dev: true + + /to-fast-properties/2.0.0: + resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} + engines: {node: '>=4'} + dev: true + + /to-object-path/0.3.0: + resolution: {integrity: sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /to-regex-range/2.1.1: + resolution: {integrity: sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 3.0.0 + repeat-string: 1.6.1 + dev: true + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /to-regex/3.0.2: + resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} + engines: {node: '>=0.10.0'} + dependencies: + define-property: 2.0.2 + extend-shallow: 3.0.2 + regex-not: 1.0.2 + safe-regex: 1.1.0 + dev: true + + /tough-cookie/4.0.0: + resolution: {integrity: sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==} + engines: {node: '>=6'} + dependencies: + psl: 1.8.0 + punycode: 2.1.1 + universalify: 0.1.2 + dev: true + + /tr46/0.0.3: + resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=} + dev: true + + /tr46/2.1.0: + resolution: {integrity: sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==} + engines: {node: '>=8'} + dependencies: + punycode: 2.1.1 + dev: true + + /ts-jest/26.5.6_eee4nuuc45mdmx5rmbx7hzjjtq: + resolution: {integrity: sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==} + engines: {node: '>= 10'} + hasBin: true + peerDependencies: + jest: '>=26 <27' + typescript: '>=3.8 <5.0' + dependencies: + bs-logger: 0.2.6 + buffer-from: 1.1.2 + fast-json-stable-stringify: 2.1.0 + jest: 26.6.3_canvas@2.9.1 + jest-util: 26.6.2 + json5: 2.2.1 + lodash: 4.17.21 + make-error: 1.3.6 + mkdirp: 1.0.4 + semver: 7.3.7 + typescript: 3.9.10 + yargs-parser: 20.2.9 + dev: true + + /ts-loader/8.4.0_ezrl6vhczkqqw35uifasf5iyga: + resolution: {integrity: sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==} + engines: {node: '>=10.0.0'} + peerDependencies: + typescript: '*' + webpack: '*' + dependencies: + chalk: 4.1.2 + enhanced-resolve: 4.5.0 + loader-utils: 2.0.2 + micromatch: 4.0.5 + semver: 7.3.7 + typescript: 3.9.10 + webpack: 4.46.0_webpack-cli@3.3.12 + dev: true + + /tslib/1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tsutils/3.21.0_typescript@3.9.10: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 3.9.10 + dev: true + + /tty-browserify/0.0.0: + resolution: {integrity: sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=} + dev: true + + /type-check/0.3.2: + resolution: {integrity: sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.1.2 + dev: true + + /type-check/0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-detect/4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest/0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest/0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /type-fest/0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest/0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /typedarray-to-buffer/3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + dependencies: + is-typedarray: 1.0.0 + dev: true + + /typedarray/0.0.6: + resolution: {integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=} + dev: true + + /typescript/3.9.10: + resolution: {integrity: sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /union-value/1.0.1: + resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} + engines: {node: '>=0.10.0'} + dependencies: + arr-union: 3.1.0 + get-value: 2.0.6 + is-extendable: 0.1.1 + set-value: 2.0.1 + dev: true + + /unique-filename/1.1.1: + resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==} + dependencies: + unique-slug: 2.0.2 + dev: true + + /unique-slug/2.0.2: + resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==} + dependencies: + imurmurhash: 0.1.4 + dev: true + + /universalify/0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: true + + /unset-value/1.0.0: + resolution: {integrity: sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=} + engines: {node: '>=0.10.0'} + dependencies: + has-value: 0.3.1 + isobject: 3.0.1 + dev: true + + /upath/1.2.0: + resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} + engines: {node: '>=4'} + dev: true + optional: true + + /uri-js/4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.1.1 + dev: true + + /urix/0.1.0: + resolution: {integrity: sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=} + deprecated: Please see https://github.com/lydell/urix#deprecated + dev: true + + /url/0.11.0: + resolution: {integrity: sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=} + dependencies: + punycode: 1.3.2 + querystring: 0.2.0 + dev: true + + /use/3.1.1: + resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} + engines: {node: '>=0.10.0'} + dev: true + + /util-deprecate/1.0.2: + resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} + dev: true + + /util/0.10.3: + resolution: {integrity: sha1-evsa/lCAUkZInj23/g7TeTNqwPk=} + dependencies: + inherits: 2.0.1 + dev: true + + /util/0.11.1: + resolution: {integrity: sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==} + dependencies: + inherits: 2.0.3 + dev: true + + /uuid/8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: true + optional: true + + /v8-compile-cache/2.3.0: + resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} + dev: true + + /v8-to-istanbul/7.1.2: + resolution: {integrity: sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==} + engines: {node: '>=10.10.0'} + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + convert-source-map: 1.8.0 + source-map: 0.7.4 + dev: true + + /validate-npm-package-license/3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.1.1 + spdx-expression-parse: 3.0.1 + dev: true + + /vm-browserify/1.1.2: + resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} + dev: true + + /w3c-hr-time/1.0.2: + resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} + dependencies: + browser-process-hrtime: 1.0.0 + dev: true + + /w3c-xmlserializer/2.0.0: + resolution: {integrity: sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==} + engines: {node: '>=10'} + dependencies: + xml-name-validator: 3.0.0 + dev: true + + /walker/1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + dependencies: + makeerror: 1.0.12 + dev: true + + /watchpack-chokidar2/2.0.1: + resolution: {integrity: sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==} + requiresBuild: true + dependencies: + chokidar: 2.1.8 + transitivePeerDependencies: + - supports-color + dev: true + optional: true + + /watchpack/1.7.5: + resolution: {integrity: sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==} + dependencies: + graceful-fs: 4.2.10 + neo-async: 2.6.2 + optionalDependencies: + chokidar: 3.5.3 + watchpack-chokidar2: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /webidl-conversions/3.0.1: + resolution: {integrity: sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=} + dev: true + + /webidl-conversions/5.0.0: + resolution: {integrity: sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==} + engines: {node: '>=8'} + dev: true + + /webidl-conversions/6.1.0: + resolution: {integrity: sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==} + engines: {node: '>=10.4'} + dev: true + + /webpack-cli/3.3.12_webpack@4.46.0: + resolution: {integrity: sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==} + engines: {node: '>=6.11.5'} + hasBin: true + peerDependencies: + webpack: 4.x.x + dependencies: + chalk: 2.4.2 + cross-spawn: 6.0.5 + enhanced-resolve: 4.5.0 + findup-sync: 3.0.0_supports-color@6.1.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.3.0 + webpack: 4.46.0_webpack-cli@3.3.12 + yargs: 13.3.2 + dev: true + + /webpack-sources/1.4.3: + resolution: {integrity: sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==} + dependencies: + source-list-map: 2.0.1 + source-map: 0.6.1 + dev: true + + /webpack/4.46.0_webpack-cli@3.3.12: + resolution: {integrity: sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==} + engines: {node: '>=6.11.5'} + hasBin: true + peerDependencies: + webpack-cli: '*' + webpack-command: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + webpack-command: + optional: true + dependencies: + '@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.2 + ajv: 6.12.6 + ajv-keywords: 3.5.2_ajv@6.12.6 + chrome-trace-event: 1.0.3 + enhanced-resolve: 4.5.0 + eslint-scope: 4.0.3 + json-parse-better-errors: 1.0.2 + loader-runner: 2.4.0 + loader-utils: 1.4.0 + memory-fs: 0.4.1 + micromatch: 3.1.10 + mkdirp: 0.5.6 + neo-async: 2.6.2 + node-libs-browser: 2.2.1 + schema-utils: 1.0.0 + tapable: 1.1.3 + terser-webpack-plugin: 1.4.5_webpack@4.46.0 + watchpack: 1.7.5 + webpack-cli: 3.3.12_webpack@4.46.0 + webpack-sources: 1.4.3 + transitivePeerDependencies: + - supports-color + dev: true + + /whatwg-encoding/1.0.5: + resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} + dependencies: + iconv-lite: 0.4.24 + dev: true + + /whatwg-mimetype/2.3.0: + resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} + dev: true + + /whatwg-url/5.0.0: + resolution: {integrity: sha1-lmRU6HZUYuN2RNNib2dCzotwll0=} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: true + + /whatwg-url/8.7.0: + resolution: {integrity: sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==} + engines: {node: '>=10'} + dependencies: + lodash: 4.17.21 + tr46: 2.1.0 + webidl-conversions: 6.1.0 + dev: true + + /which-module/2.0.0: + resolution: {integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=} + dev: true + + /which/1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wide-align/1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + dependencies: + string-width: 4.2.3 + dev: true + + /word-wrap/1.2.3: + resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} + engines: {node: '>=0.10.0'} + dev: true + + /worker-farm/1.7.0: + resolution: {integrity: sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==} + dependencies: + errno: 0.1.8 + dev: true + + /wrap-ansi/5.1.0: + resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==} + engines: {node: '>=6'} + dependencies: + ansi-styles: 3.2.1 + string-width: 3.1.0 + strip-ansi: 5.2.0 + dev: true + + /wrap-ansi/6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrappy/1.0.2: + resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} + dev: true + + /write-file-atomic/3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.7 + typedarray-to-buffer: 3.1.5 + dev: true + + /ws/7.5.8: + resolution: {integrity: sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /xml-name-validator/3.0.0: + resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} + dev: true + + /xmlchars/2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + dev: true + + /xtend/4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + dev: true + + /y18n/4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + dev: true + + /yallist/3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yargs-parser/13.1.2: + resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: true + + /yargs-parser/18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: true + + /yargs-parser/20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: true + + /yargs/13.3.2: + resolution: {integrity: sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==} + dependencies: + cliui: 5.0.0 + find-up: 3.0.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 3.1.0 + which-module: 2.0.0 + y18n: 4.0.3 + yargs-parser: 13.1.2 + dev: true + + /yargs/15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.0 + y18n: 4.0.3 + yargs-parser: 18.1.3 + dev: true + + /yocto-queue/0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/src/editable.ts b/src/editable.ts index 687c799b..c78b28c2 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -24,15 +24,16 @@ let _sourceTarget: SVGElement | null; * * @param container HTML element for rendering visualization into. * @param sqore Sqore object + * @param callbackFn User-provided callback function triggered when circuit is changed * */ -const addEditable = (container: HTMLElement, sqore: Sqore): void => { +const addEditable = (container: HTMLElement, sqore: Sqore, callbackFn?: () => void): void => { const context: Context = { container: container, operations: sqore.circuit.operations, wires: getWireElemsY(container), - renderFn: () => sqore.draw(container, 0, true), + renderFn: getRenderFn(container, sqore, callbackFn), }; addCustomStyles(container); addDropzones(container); @@ -74,7 +75,7 @@ const addCustomStyles = (container: HTMLElement): void => { const addDropzones = (container: HTMLElement): void => { const gateElems = getGateElems(container); gateElems.forEach((gateElem) => { - const { x, y, width, height } = gateElem.getBBox({ stroke: true }); + const { x, y, width, height } = gateElem.getBBox(); const dataId = getDataId(gateElem); gateElem.append(createLeftDropzone(x, y, height, dataId)); gateElem.append(createRightDropzone(x, y, width, height, dataId)); @@ -147,7 +148,6 @@ const handleDropzoneMouseUp = (ev: MouseEvent, context: Context): void | false = // Not allow Measure gate to move vertically if (wireY != null && newGate.gate !== 'measure') { - console.log(wires[wireY]); // wires[wireY] returns qubit name (i.e: 'q0') // this remove 'q' and assign an index (i.e: 0) const index = Number(wires[wireY].slice(1)); @@ -249,6 +249,13 @@ const getGate = (dataId: string, operations: Operation[]): Operation => { }; // Utilities +const getRenderFn = (container: HTMLElement, sqore: Sqore, callbackFn?: () => void): (() => void) => { + return () => { + sqore.draw(container, 0, true, callbackFn); + if (callbackFn) callbackFn(); + }; +}; + const getDataId = (element: Element): string => { return element.getAttribute('data-id') || ''; }; @@ -320,7 +327,7 @@ const cursorCopy = (container: HTMLElement, value: boolean): void => { const exportedForTesting = { // addEditable addCustomStyles, - // addDropzones + addDropzones, addDocumentEvents, addDropzoneEvents, addMouseEvents, @@ -334,6 +341,7 @@ const exportedForTesting = { getParent, getGate, getDataId, + getRenderFn, splitDataId, getWireElemsY, getWireElemY, diff --git a/src/index.ts b/src/index.ts index 8a9093bc..49973b3f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,17 +12,20 @@ import { StyleConfig } from './styles'; * @param container HTML element for rendering visualization into. * @param style Custom visualization style. * @param renderDepth Initial layer depth at which to render gates. + * @param isEditable Optional value enabling/disabling editable feature + * @param callbackFn Optional function to trigger when changing elements in circuit */ export const draw = ( circuit: Circuit, container: HTMLElement, style: StyleConfig | string = {}, renderDepth = 0, - editable = false, + isEditable?: boolean, + callbackFn?: () => void, ): void => { const sqore = new Sqore(circuit, style); - sqore.draw(container, renderDepth, editable); + sqore.draw(container, renderDepth, isEditable, callbackFn); }; export { STYLES } from './styles'; diff --git a/src/sqore.ts b/src/sqore.ts index bfb63e98..990ea3dc 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -56,8 +56,10 @@ export class Sqore { * * @param container HTML element for rendering visualization into. * @param renderDepth Initial layer depth at which to render gates. + * @param isEditable Optional value enabling/disabling editable feature + * @param callbackFn Optional function to trigger when changing elements in circuit */ - draw(container: HTMLElement, renderDepth = 0, editable = false): void { + draw(container: HTMLElement, renderDepth = 0, isEditable?: boolean, callbackFn?: () => void): void { // Inject into container if (container == null) throw new Error(`Container not provided.`); @@ -79,7 +81,7 @@ export class Sqore { const id: string = circuit.operations[0].dataAttributes['id']; this.expandOperation(circuit.operations, id); } - this.renderCircuit(container, circuit, editable); + this.renderCircuit(container, circuit, isEditable, callbackFn); } /** @@ -106,17 +108,24 @@ export class Sqore { * * @param container HTML element for rendering visualization into. * @param circuit Circuit object to be rendered. + * @param isEditable Optional value enabling/disabling editable feature + * @param callbackFn Optional function to trigger when changing elements in circuit */ - private renderCircuit(container: HTMLElement, circuit: Circuit, editable: boolean): void { + private renderCircuit( + container: HTMLElement, + circuit: Circuit, + isEditable?: boolean, + callbackFn?: () => void, + ): void { // Create visualization components const composedSqore: ComposedSqore = this.compose(circuit); const svg: SVGElement = this.generateSvg(composedSqore); container.innerHTML = ''; container.appendChild(svg); - this.addGateClickHandlers(container, circuit, editable); + this.addGateClickHandlers(container, circuit, isEditable, callbackFn); - if (editable) { - addEditable(container, this); + if (isEditable) { + addEditable(container, this, callbackFn); } } @@ -233,11 +242,18 @@ export class Sqore { * * @param container HTML element containing visualized circuit. * @param circuit Circuit to be visualized. + * @param isEditable Optional value enabling/disabling editable feature + * @param callbackFn Optional function to trigger when changing elements in circuit * */ - private addGateClickHandlers(container: HTMLElement, circuit: Circuit, editable: boolean): void { + private addGateClickHandlers( + container: HTMLElement, + circuit: Circuit, + isEditable?: boolean, + callbackFn?: () => void, + ): void { this.addClassicalControlHandlers(container); - this.addZoomHandlers(container, circuit, editable); + this.addZoomHandlers(container, circuit, isEditable, callbackFn); } /** @@ -293,9 +309,16 @@ export class Sqore { * * @param container HTML element containing visualized circuit. * @param circuit Circuit to be visualized. + * @param isEditable Optional value enabling/disabling editable feature + * @param callbackFn Optional function to trigger when changing elements in circuit * */ - private addZoomHandlers(container: HTMLElement, circuit: Circuit, editable: boolean): void { + private addZoomHandlers( + container: HTMLElement, + circuit: Circuit, + isEditable?: boolean, + callbackFn?: () => void, + ): void { container.querySelectorAll('.gate .gate-control').forEach((ctrl) => { // Zoom in on clicked gate ctrl.addEventListener('click', (ev: Event) => { @@ -306,7 +329,7 @@ export class Sqore { } else if (ctrl.classList.contains('gate-expand')) { this.expandOperation(circuit.operations, gateId); } - this.renderCircuit(container, circuit, editable); + this.renderCircuit(container, circuit, isEditable, callbackFn); ev.stopPropagation(); } }); From bf12e14dc3c92e312ceb10264ef55d0bae7d9c3c Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 9 Jun 2022 19:33:52 -0400 Subject: [PATCH 021/108] Remove pnpm-lock --- pnpm-lock.yaml | 6261 ------------------------------------------------ 1 file changed, 6261 deletions(-) delete mode 100644 pnpm-lock.yaml diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index fda0d629..00000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,6261 +0,0 @@ -lockfileVersion: 5.4 - -specifiers: - '@types/jest': ^26.0.4 - '@types/prettier': 2.6.0 - '@typescript-eslint/eslint-plugin': ^3.9.0 - '@typescript-eslint/parser': ^3.9.0 - canvas: ^2.6.1 - eslint: ^7.6.0 - eslint-config-prettier: ^6.11.0 - eslint-plugin-jest: ^23.20.0 - eslint-plugin-prettier: ^3.1.4 - jest: ^26.6.3 - prettier: 2.6.0 - terser-webpack-plugin: ^4.1.0 - ts-jest: ^26.1.2 - ts-loader: ^8.0.2 - typescript: ^3.9.6 - webpack: ^4.46.0 - webpack-cli: ^3.3.12 - -devDependencies: - '@types/jest': 26.0.24 - '@types/prettier': 2.6.0 - '@typescript-eslint/eslint-plugin': 3.10.1_kxujzhw6vbtdri44htsqryf25e - '@typescript-eslint/parser': 3.10.1_2de3j2mqba4wgeuiaqz2k7syrm - canvas: 2.9.1 - eslint: 7.32.0 - eslint-config-prettier: 6.15.0_eslint@7.32.0 - eslint-plugin-jest: 23.20.0_2de3j2mqba4wgeuiaqz2k7syrm - eslint-plugin-prettier: 3.4.1_dnozcfbeb5wiozlftdrslmvmgu - jest: 26.6.3_canvas@2.9.1 - prettier: 2.6.0 - terser-webpack-plugin: 4.2.3_webpack@4.46.0 - ts-jest: 26.5.6_eee4nuuc45mdmx5rmbx7hzjjtq - ts-loader: 8.4.0_ezrl6vhczkqqw35uifasf5iyga - typescript: 3.9.10 - webpack: 4.46.0_webpack-cli@3.3.12 - webpack-cli: 3.3.12_webpack@4.46.0 - -packages: - - /@ampproject/remapping/2.2.0: - resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.1.1 - '@jridgewell/trace-mapping': 0.3.13 - dev: true - - /@babel/code-frame/7.12.11: - resolution: {integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==} - dependencies: - '@babel/highlight': 7.17.12 - dev: true - - /@babel/code-frame/7.16.7: - resolution: {integrity: sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.17.12 - dev: true - - /@babel/compat-data/7.17.10: - resolution: {integrity: sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core/7.18.2: - resolution: {integrity: sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.0 - '@babel/code-frame': 7.16.7 - '@babel/generator': 7.18.2 - '@babel/helper-compilation-targets': 7.18.2_@babel+core@7.18.2 - '@babel/helper-module-transforms': 7.18.0 - '@babel/helpers': 7.18.2 - '@babel/parser': 7.18.4 - '@babel/template': 7.16.7 - '@babel/traverse': 7.18.2 - '@babel/types': 7.18.4 - convert-source-map: 1.8.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.1 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/generator/7.18.2: - resolution: {integrity: sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.18.4 - '@jridgewell/gen-mapping': 0.3.1 - jsesc: 2.5.2 - dev: true - - /@babel/helper-compilation-targets/7.18.2_@babel+core@7.18.2: - resolution: {integrity: sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.17.10 - '@babel/core': 7.18.2 - '@babel/helper-validator-option': 7.16.7 - browserslist: 4.20.4 - semver: 6.3.0 - dev: true - - /@babel/helper-environment-visitor/7.18.2: - resolution: {integrity: sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-function-name/7.17.9: - resolution: {integrity: sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.16.7 - '@babel/types': 7.18.4 - dev: true - - /@babel/helper-hoist-variables/7.16.7: - resolution: {integrity: sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.18.4 - dev: true - - /@babel/helper-module-imports/7.16.7: - resolution: {integrity: sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.18.4 - dev: true - - /@babel/helper-module-transforms/7.18.0: - resolution: {integrity: sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.18.2 - '@babel/helper-module-imports': 7.16.7 - '@babel/helper-simple-access': 7.18.2 - '@babel/helper-split-export-declaration': 7.16.7 - '@babel/helper-validator-identifier': 7.16.7 - '@babel/template': 7.16.7 - '@babel/traverse': 7.18.2 - '@babel/types': 7.18.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-plugin-utils/7.17.12: - resolution: {integrity: sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-simple-access/7.18.2: - resolution: {integrity: sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.18.4 - dev: true - - /@babel/helper-split-export-declaration/7.16.7: - resolution: {integrity: sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.18.4 - dev: true - - /@babel/helper-validator-identifier/7.16.7: - resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option/7.16.7: - resolution: {integrity: sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers/7.18.2: - resolution: {integrity: sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.16.7 - '@babel/traverse': 7.18.2 - '@babel/types': 7.18.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/highlight/7.17.12: - resolution: {integrity: sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.16.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - - /@babel/parser/7.18.4: - resolution: {integrity: sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.18.4 - dev: true - - /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.18.2: - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.18.2: - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.18.2: - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.18.2: - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.18.2: - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.18.2: - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.18.2: - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.18.2: - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.18.2: - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.18.2: - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.18.2: - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.18.2: - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.18.2 - '@babel/helper-plugin-utils': 7.17.12 - dev: true - - /@babel/template/7.16.7: - resolution: {integrity: sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.16.7 - '@babel/parser': 7.18.4 - '@babel/types': 7.18.4 - dev: true - - /@babel/traverse/7.18.2: - resolution: {integrity: sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.16.7 - '@babel/generator': 7.18.2 - '@babel/helper-environment-visitor': 7.18.2 - '@babel/helper-function-name': 7.17.9 - '@babel/helper-hoist-variables': 7.16.7 - '@babel/helper-split-export-declaration': 7.16.7 - '@babel/parser': 7.18.4 - '@babel/types': 7.18.4 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types/7.18.4: - resolution: {integrity: sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.16.7 - to-fast-properties: 2.0.0 - dev: true - - /@bcoe/v8-coverage/0.2.3: - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - dev: true - - /@cnakazawa/watch/1.0.4: - resolution: {integrity: sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==} - engines: {node: '>=0.1.95'} - hasBin: true - dependencies: - exec-sh: 0.3.6 - minimist: 1.2.6 - dev: true - - /@eslint/eslintrc/0.4.3: - resolution: {integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 7.3.1 - globals: 13.15.0 - ignore: 4.0.6 - import-fresh: 3.3.0 - js-yaml: 3.14.1 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@gar/promisify/1.1.3: - resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} - dev: true - - /@humanwhocodes/config-array/0.5.0: - resolution: {integrity: sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/object-schema/1.2.1: - resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} - dev: true - - /@istanbuljs/load-nyc-config/1.1.0: - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - dev: true - - /@istanbuljs/schema/0.1.3: - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - dev: true - - /@jest/console/26.6.2: - resolution: {integrity: sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/types': 26.6.2 - '@types/node': 17.0.41 - chalk: 4.1.2 - jest-message-util: 26.6.2 - jest-util: 26.6.2 - slash: 3.0.0 - dev: true - - /@jest/core/26.6.3_canvas@2.9.1: - resolution: {integrity: sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/console': 26.6.2 - '@jest/reporters': 26.6.2 - '@jest/test-result': 26.6.2 - '@jest/transform': 26.6.2 - '@jest/types': 26.6.2 - '@types/node': 17.0.41 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.10 - jest-changed-files: 26.6.2 - jest-config: 26.6.3_canvas@2.9.1 - jest-haste-map: 26.6.2 - jest-message-util: 26.6.2 - jest-regex-util: 26.0.0 - jest-resolve: 26.6.2 - jest-resolve-dependencies: 26.6.3 - jest-runner: 26.6.3_canvas@2.9.1 - jest-runtime: 26.6.3_canvas@2.9.1 - jest-snapshot: 26.6.2 - jest-util: 26.6.2 - jest-validate: 26.6.2 - jest-watcher: 26.6.2 - micromatch: 4.0.5 - p-each-series: 2.2.0 - rimraf: 3.0.2 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - ts-node - - utf-8-validate - dev: true - - /@jest/environment/26.6.2: - resolution: {integrity: sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/fake-timers': 26.6.2 - '@jest/types': 26.6.2 - '@types/node': 17.0.41 - jest-mock: 26.6.2 - dev: true - - /@jest/fake-timers/26.6.2: - resolution: {integrity: sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/types': 26.6.2 - '@sinonjs/fake-timers': 6.0.1 - '@types/node': 17.0.41 - jest-message-util: 26.6.2 - jest-mock: 26.6.2 - jest-util: 26.6.2 - dev: true - - /@jest/globals/26.6.2: - resolution: {integrity: sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/environment': 26.6.2 - '@jest/types': 26.6.2 - expect: 26.6.2 - dev: true - - /@jest/reporters/26.6.2: - resolution: {integrity: sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==} - engines: {node: '>= 10.14.2'} - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 26.6.2 - '@jest/test-result': 26.6.2 - '@jest/transform': 26.6.2 - '@jest/types': 26.6.2 - chalk: 4.1.2 - collect-v8-coverage: 1.0.1 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.10 - istanbul-lib-coverage: 3.2.0 - istanbul-lib-instrument: 4.0.3 - istanbul-lib-report: 3.0.0 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.4 - jest-haste-map: 26.6.2 - jest-resolve: 26.6.2 - jest-util: 26.6.2 - jest-worker: 26.6.2 - slash: 3.0.0 - source-map: 0.6.1 - string-length: 4.0.2 - terminal-link: 2.1.1 - v8-to-istanbul: 7.1.2 - optionalDependencies: - node-notifier: 8.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/source-map/26.6.2: - resolution: {integrity: sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==} - engines: {node: '>= 10.14.2'} - dependencies: - callsites: 3.1.0 - graceful-fs: 4.2.10 - source-map: 0.6.1 - dev: true - - /@jest/test-result/26.6.2: - resolution: {integrity: sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/console': 26.6.2 - '@jest/types': 26.6.2 - '@types/istanbul-lib-coverage': 2.0.4 - collect-v8-coverage: 1.0.1 - dev: true - - /@jest/test-sequencer/26.6.3_canvas@2.9.1: - resolution: {integrity: sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/test-result': 26.6.2 - graceful-fs: 4.2.10 - jest-haste-map: 26.6.2 - jest-runner: 26.6.3_canvas@2.9.1 - jest-runtime: 26.6.3_canvas@2.9.1 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - ts-node - - utf-8-validate - dev: true - - /@jest/transform/26.6.2: - resolution: {integrity: sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==} - engines: {node: '>= 10.14.2'} - dependencies: - '@babel/core': 7.18.2 - '@jest/types': 26.6.2 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 1.8.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.10 - jest-haste-map: 26.6.2 - jest-regex-util: 26.0.0 - jest-util: 26.6.2 - micromatch: 4.0.5 - pirates: 4.0.5 - slash: 3.0.0 - source-map: 0.6.1 - write-file-atomic: 3.0.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/types/26.6.2: - resolution: {integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==} - engines: {node: '>= 10.14.2'} - dependencies: - '@types/istanbul-lib-coverage': 2.0.4 - '@types/istanbul-reports': 3.0.1 - '@types/node': 17.0.41 - '@types/yargs': 15.0.14 - chalk: 4.1.2 - dev: true - - /@jridgewell/gen-mapping/0.1.1: - resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.1 - '@jridgewell/sourcemap-codec': 1.4.13 - dev: true - - /@jridgewell/gen-mapping/0.3.1: - resolution: {integrity: sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.1 - '@jridgewell/sourcemap-codec': 1.4.13 - '@jridgewell/trace-mapping': 0.3.13 - dev: true - - /@jridgewell/resolve-uri/3.0.7: - resolution: {integrity: sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array/1.1.1: - resolution: {integrity: sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/source-map/0.3.2: - resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==} - dependencies: - '@jridgewell/gen-mapping': 0.3.1 - '@jridgewell/trace-mapping': 0.3.13 - dev: true - - /@jridgewell/sourcemap-codec/1.4.13: - resolution: {integrity: sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==} - dev: true - - /@jridgewell/trace-mapping/0.3.13: - resolution: {integrity: sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==} - dependencies: - '@jridgewell/resolve-uri': 3.0.7 - '@jridgewell/sourcemap-codec': 1.4.13 - dev: true - - /@mapbox/node-pre-gyp/1.0.9: - resolution: {integrity: sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==} - hasBin: true - dependencies: - detect-libc: 2.0.1 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.6.7 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.3.7 - tar: 6.1.11 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /@npmcli/fs/1.1.1: - resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} - dependencies: - '@gar/promisify': 1.1.3 - semver: 7.3.7 - dev: true - - /@npmcli/move-file/1.1.2: - resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} - engines: {node: '>=10'} - dependencies: - mkdirp: 1.0.4 - rimraf: 3.0.2 - dev: true - - /@sinonjs/commons/1.8.3: - resolution: {integrity: sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==} - dependencies: - type-detect: 4.0.8 - dev: true - - /@sinonjs/fake-timers/6.0.1: - resolution: {integrity: sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==} - dependencies: - '@sinonjs/commons': 1.8.3 - dev: true - - /@tootallnate/once/1.1.2: - resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} - engines: {node: '>= 6'} - dev: true - - /@types/babel__core/7.1.19: - resolution: {integrity: sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==} - dependencies: - '@babel/parser': 7.18.4 - '@babel/types': 7.18.4 - '@types/babel__generator': 7.6.4 - '@types/babel__template': 7.4.1 - '@types/babel__traverse': 7.17.1 - dev: true - - /@types/babel__generator/7.6.4: - resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} - dependencies: - '@babel/types': 7.18.4 - dev: true - - /@types/babel__template/7.4.1: - resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} - dependencies: - '@babel/parser': 7.18.4 - '@babel/types': 7.18.4 - dev: true - - /@types/babel__traverse/7.17.1: - resolution: {integrity: sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==} - dependencies: - '@babel/types': 7.18.4 - dev: true - - /@types/eslint-visitor-keys/1.0.0: - resolution: {integrity: sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==} - dev: true - - /@types/graceful-fs/4.1.5: - resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} - dependencies: - '@types/node': 17.0.41 - dev: true - - /@types/istanbul-lib-coverage/2.0.4: - resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} - dev: true - - /@types/istanbul-lib-report/3.0.0: - resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} - dependencies: - '@types/istanbul-lib-coverage': 2.0.4 - dev: true - - /@types/istanbul-reports/3.0.1: - resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} - dependencies: - '@types/istanbul-lib-report': 3.0.0 - dev: true - - /@types/jest/26.0.24: - resolution: {integrity: sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==} - dependencies: - jest-diff: 26.6.2 - pretty-format: 26.6.2 - dev: true - - /@types/json-schema/7.0.11: - resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} - dev: true - - /@types/node/17.0.41: - resolution: {integrity: sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw==} - dev: true - - /@types/normalize-package-data/2.4.1: - resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} - dev: true - - /@types/prettier/2.6.0: - resolution: {integrity: sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==} - dev: true - - /@types/stack-utils/2.0.1: - resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} - dev: true - - /@types/yargs-parser/21.0.0: - resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} - dev: true - - /@types/yargs/15.0.14: - resolution: {integrity: sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==} - dependencies: - '@types/yargs-parser': 21.0.0 - dev: true - - /@typescript-eslint/eslint-plugin/3.10.1_kxujzhw6vbtdri44htsqryf25e: - resolution: {integrity: sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==} - engines: {node: ^10.12.0 || >=12.0.0} - peerDependencies: - '@typescript-eslint/parser': ^3.0.0 - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/experimental-utils': 3.10.1_2de3j2mqba4wgeuiaqz2k7syrm - '@typescript-eslint/parser': 3.10.1_2de3j2mqba4wgeuiaqz2k7syrm - debug: 4.3.4 - eslint: 7.32.0 - functional-red-black-tree: 1.0.1 - regexpp: 3.2.0 - semver: 7.3.7 - tsutils: 3.21.0_typescript@3.9.10 - typescript: 3.9.10 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/experimental-utils/2.34.0_2de3j2mqba4wgeuiaqz2k7syrm: - resolution: {integrity: sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==} - engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} - peerDependencies: - eslint: '*' - dependencies: - '@types/json-schema': 7.0.11 - '@typescript-eslint/typescript-estree': 2.34.0_typescript@3.9.10 - eslint: 7.32.0 - eslint-scope: 5.1.1 - eslint-utils: 2.1.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/experimental-utils/3.10.1_2de3j2mqba4wgeuiaqz2k7syrm: - resolution: {integrity: sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==} - engines: {node: ^10.12.0 || >=12.0.0} - peerDependencies: - eslint: '*' - dependencies: - '@types/json-schema': 7.0.11 - '@typescript-eslint/types': 3.10.1 - '@typescript-eslint/typescript-estree': 3.10.1_typescript@3.9.10 - eslint: 7.32.0 - eslint-scope: 5.1.1 - eslint-utils: 2.1.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/parser/3.10.1_2de3j2mqba4wgeuiaqz2k7syrm: - resolution: {integrity: sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==} - engines: {node: ^10.12.0 || >=12.0.0} - peerDependencies: - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@types/eslint-visitor-keys': 1.0.0 - '@typescript-eslint/experimental-utils': 3.10.1_2de3j2mqba4wgeuiaqz2k7syrm - '@typescript-eslint/types': 3.10.1 - '@typescript-eslint/typescript-estree': 3.10.1_typescript@3.9.10 - eslint: 7.32.0 - eslint-visitor-keys: 1.3.0 - typescript: 3.9.10 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types/3.10.1: - resolution: {integrity: sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==} - engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} - dev: true - - /@typescript-eslint/typescript-estree/2.34.0_typescript@3.9.10: - resolution: {integrity: sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==} - engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - debug: 4.3.4 - eslint-visitor-keys: 1.3.0 - glob: 7.2.3 - is-glob: 4.0.3 - lodash: 4.17.21 - semver: 7.3.7 - tsutils: 3.21.0_typescript@3.9.10 - typescript: 3.9.10 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree/3.10.1_typescript@3.9.10: - resolution: {integrity: sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==} - engines: {node: ^10.12.0 || >=12.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 3.10.1 - '@typescript-eslint/visitor-keys': 3.10.1 - debug: 4.3.4 - glob: 7.2.3 - is-glob: 4.0.3 - lodash: 4.17.21 - semver: 7.3.7 - tsutils: 3.21.0_typescript@3.9.10 - typescript: 3.9.10 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/visitor-keys/3.10.1: - resolution: {integrity: sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==} - engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} - dependencies: - eslint-visitor-keys: 1.3.0 - dev: true - - /@webassemblyjs/ast/1.9.0: - resolution: {integrity: sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==} - dependencies: - '@webassemblyjs/helper-module-context': 1.9.0 - '@webassemblyjs/helper-wasm-bytecode': 1.9.0 - '@webassemblyjs/wast-parser': 1.9.0 - dev: true - - /@webassemblyjs/floating-point-hex-parser/1.9.0: - resolution: {integrity: sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==} - dev: true - - /@webassemblyjs/helper-api-error/1.9.0: - resolution: {integrity: sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==} - dev: true - - /@webassemblyjs/helper-buffer/1.9.0: - resolution: {integrity: sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==} - dev: true - - /@webassemblyjs/helper-code-frame/1.9.0: - resolution: {integrity: sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==} - dependencies: - '@webassemblyjs/wast-printer': 1.9.0 - dev: true - - /@webassemblyjs/helper-fsm/1.9.0: - resolution: {integrity: sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==} - dev: true - - /@webassemblyjs/helper-module-context/1.9.0: - resolution: {integrity: sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==} - dependencies: - '@webassemblyjs/ast': 1.9.0 - dev: true - - /@webassemblyjs/helper-wasm-bytecode/1.9.0: - resolution: {integrity: sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==} - dev: true - - /@webassemblyjs/helper-wasm-section/1.9.0: - resolution: {integrity: sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==} - dependencies: - '@webassemblyjs/ast': 1.9.0 - '@webassemblyjs/helper-buffer': 1.9.0 - '@webassemblyjs/helper-wasm-bytecode': 1.9.0 - '@webassemblyjs/wasm-gen': 1.9.0 - dev: true - - /@webassemblyjs/ieee754/1.9.0: - resolution: {integrity: sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==} - dependencies: - '@xtuc/ieee754': 1.2.0 - dev: true - - /@webassemblyjs/leb128/1.9.0: - resolution: {integrity: sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==} - dependencies: - '@xtuc/long': 4.2.2 - dev: true - - /@webassemblyjs/utf8/1.9.0: - resolution: {integrity: sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==} - dev: true - - /@webassemblyjs/wasm-edit/1.9.0: - resolution: {integrity: sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==} - dependencies: - '@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 - dev: true - - /@webassemblyjs/wasm-gen/1.9.0: - resolution: {integrity: sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==} - dependencies: - '@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 - dev: true - - /@webassemblyjs/wasm-opt/1.9.0: - resolution: {integrity: sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==} - dependencies: - '@webassemblyjs/ast': 1.9.0 - '@webassemblyjs/helper-buffer': 1.9.0 - '@webassemblyjs/wasm-gen': 1.9.0 - '@webassemblyjs/wasm-parser': 1.9.0 - dev: true - - /@webassemblyjs/wasm-parser/1.9.0: - resolution: {integrity: sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==} - dependencies: - '@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 - dev: true - - /@webassemblyjs/wast-parser/1.9.0: - resolution: {integrity: sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==} - dependencies: - '@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 - dev: true - - /@webassemblyjs/wast-printer/1.9.0: - resolution: {integrity: sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==} - dependencies: - '@webassemblyjs/ast': 1.9.0 - '@webassemblyjs/wast-parser': 1.9.0 - '@xtuc/long': 4.2.2 - dev: true - - /@xtuc/ieee754/1.2.0: - resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} - dev: true - - /@xtuc/long/4.2.2: - resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - dev: true - - /abab/2.0.6: - resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} - dev: true - - /abbrev/1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: true - - /acorn-globals/6.0.0: - resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==} - dependencies: - acorn: 7.4.1 - acorn-walk: 7.2.0 - dev: true - - /acorn-jsx/5.3.2_acorn@7.4.1: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 7.4.1 - dev: true - - /acorn-walk/7.2.0: - resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} - engines: {node: '>=0.4.0'} - dev: true - - /acorn/6.4.2: - resolution: {integrity: sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /acorn/7.4.1: - resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /acorn/8.7.1: - resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /agent-base/6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /aggregate-error/3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - dev: true - - /ajv-errors/1.0.1_ajv@6.12.6: - resolution: {integrity: sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==} - peerDependencies: - ajv: '>=5.0.0' - dependencies: - ajv: 6.12.6 - dev: true - - /ajv-keywords/3.5.2_ajv@6.12.6: - resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} - peerDependencies: - ajv: ^6.9.1 - dependencies: - ajv: 6.12.6 - dev: true - - /ajv/6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ajv/8.11.0: - resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: true - - /ansi-colors/4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true - - /ansi-escapes/4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: true - - /ansi-regex/4.1.1: - resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} - engines: {node: '>=6'} - dev: true - - /ansi-regex/5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true - - /ansi-styles/3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles/4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - - /anymatch/2.0.0: - resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} - dependencies: - micromatch: 3.1.10 - normalize-path: 2.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /anymatch/3.1.2: - resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /aproba/1.2.0: - resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==} - dev: true - - /aproba/2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - dev: true - - /are-we-there-yet/2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.0 - dev: true - - /argparse/1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - dev: true - - /arr-diff/4.0.0: - resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} - engines: {node: '>=0.10.0'} - dev: true - - /arr-flatten/1.1.0: - resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} - engines: {node: '>=0.10.0'} - dev: true - - /arr-union/3.1.0: - resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} - engines: {node: '>=0.10.0'} - dev: true - - /array-unique/0.3.2: - resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} - engines: {node: '>=0.10.0'} - dev: true - - /asn1.js/5.4.1: - resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} - dependencies: - bn.js: 4.12.0 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - safer-buffer: 2.1.2 - dev: true - - /assert/1.5.0: - resolution: {integrity: sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==} - dependencies: - object-assign: 4.1.1 - util: 0.10.3 - dev: true - - /assign-symbols/1.0.0: - resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} - engines: {node: '>=0.10.0'} - dev: true - - /astral-regex/2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - dev: true - - /async-each/1.0.3: - resolution: {integrity: sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==} - dev: true - optional: true - - /asynckit/0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true - - /atob/2.1.2: - resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} - engines: {node: '>= 4.5.0'} - hasBin: true - dev: true - - /babel-jest/26.6.3_@babel+core@7.18.2: - resolution: {integrity: sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==} - engines: {node: '>= 10.14.2'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.18.2 - '@jest/transform': 26.6.2 - '@jest/types': 26.6.2 - '@types/babel__core': 7.1.19 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 26.6.2_@babel+core@7.18.2 - chalk: 4.1.2 - graceful-fs: 4.2.10 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-istanbul/6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - dependencies: - '@babel/helper-plugin-utils': 7.17.12 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.0 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-jest-hoist/26.6.2: - resolution: {integrity: sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==} - engines: {node: '>= 10.14.2'} - dependencies: - '@babel/template': 7.16.7 - '@babel/types': 7.18.4 - '@types/babel__core': 7.1.19 - '@types/babel__traverse': 7.17.1 - dev: true - - /babel-preset-current-node-syntax/1.0.1_@babel+core@7.18.2: - resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.18.2 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.18.2 - '@babel/plugin-syntax-bigint': 7.8.3_@babel+core@7.18.2 - '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.18.2 - '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.18.2 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.18.2 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.18.2 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.18.2 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.18.2 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.18.2 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.18.2 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.18.2 - '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.18.2 - dev: true - - /babel-preset-jest/26.6.2_@babel+core@7.18.2: - resolution: {integrity: sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==} - engines: {node: '>= 10.14.2'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.18.2 - babel-plugin-jest-hoist: 26.6.2 - babel-preset-current-node-syntax: 1.0.1_@babel+core@7.18.2 - dev: true - - /balanced-match/1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /base/0.11.2: - resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} - engines: {node: '>=0.10.0'} - dependencies: - cache-base: 1.0.1 - class-utils: 0.3.6 - component-emitter: 1.3.0 - define-property: 1.0.0 - isobject: 3.0.1 - mixin-deep: 1.3.2 - pascalcase: 0.1.1 - dev: true - - /base64-js/1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true - - /big.js/5.2.2: - resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} - dev: true - - /binary-extensions/1.13.1: - resolution: {integrity: sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==} - engines: {node: '>=0.10.0'} - dev: true - optional: true - - /binary-extensions/2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: true - optional: true - - /bindings/1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - dependencies: - file-uri-to-path: 1.0.0 - dev: true - optional: true - - /bluebird/3.7.2: - resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} - dev: true - - /bn.js/4.12.0: - resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} - dev: true - - /bn.js/5.2.1: - resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - dev: true - - /brace-expansion/1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /braces/2.3.2: - resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} - engines: {node: '>=0.10.0'} - dependencies: - 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.4 - snapdragon: 0.8.2 - snapdragon-node: 2.1.1 - split-string: 3.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /braces/2.3.2_supports-color@6.1.0: - resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} - engines: {node: '>=0.10.0'} - dependencies: - 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.4 - snapdragon: 0.8.2_supports-color@6.1.0 - snapdragon-node: 2.1.1 - split-string: 3.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /braces/3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - - /brorand/1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - dev: true - - /browser-process-hrtime/1.0.0: - resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} - dev: true - - /browserify-aes/1.2.0: - resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} - dependencies: - buffer-xor: 1.0.3 - cipher-base: 1.0.4 - create-hash: 1.2.0 - evp_bytestokey: 1.0.3 - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - - /browserify-cipher/1.0.1: - resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} - dependencies: - browserify-aes: 1.2.0 - browserify-des: 1.0.2 - evp_bytestokey: 1.0.3 - dev: true - - /browserify-des/1.0.2: - resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} - dependencies: - cipher-base: 1.0.4 - des.js: 1.0.1 - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - - /browserify-rsa/4.1.0: - resolution: {integrity: sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==} - dependencies: - bn.js: 5.2.1 - randombytes: 2.1.0 - dev: true - - /browserify-sign/4.2.1: - resolution: {integrity: sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==} - dependencies: - bn.js: 5.2.1 - browserify-rsa: 4.1.0 - create-hash: 1.2.0 - create-hmac: 1.1.7 - elliptic: 6.5.4 - inherits: 2.0.4 - parse-asn1: 5.1.6 - readable-stream: 3.6.0 - safe-buffer: 5.2.1 - dev: true - - /browserify-zlib/0.2.0: - resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} - dependencies: - pako: 1.0.11 - dev: true - - /browserslist/4.20.4: - resolution: {integrity: sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001352 - electron-to-chromium: 1.4.150 - escalade: 3.1.1 - node-releases: 2.0.5 - picocolors: 1.0.0 - dev: true - - /bs-logger/0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - dependencies: - fast-json-stable-stringify: 2.1.0 - dev: true - - /bser/2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - dependencies: - node-int64: 0.4.0 - dev: true - - /buffer-from/1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - - /buffer-xor/1.0.3: - resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} - dev: true - - /buffer/4.9.2: - resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - isarray: 1.0.0 - dev: true - - /builtin-status-codes/3.0.0: - resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} - dev: true - - /cacache/12.0.4: - resolution: {integrity: sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==} - dependencies: - bluebird: 3.7.2 - chownr: 1.1.4 - figgy-pudding: 3.5.2 - glob: 7.2.3 - graceful-fs: 4.2.10 - infer-owner: 1.0.4 - lru-cache: 5.1.1 - mississippi: 3.0.0 - mkdirp: 0.5.6 - move-concurrently: 1.0.1 - promise-inflight: 1.0.1_bluebird@3.7.2 - rimraf: 2.7.1 - ssri: 6.0.2 - unique-filename: 1.1.1 - y18n: 4.0.3 - dev: true - - /cacache/15.3.0: - resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==} - engines: {node: '>= 10'} - dependencies: - '@npmcli/fs': 1.1.1 - '@npmcli/move-file': 1.1.2 - chownr: 2.0.0 - fs-minipass: 2.1.0 - glob: 7.2.3 - infer-owner: 1.0.4 - lru-cache: 6.0.0 - minipass: 3.1.6 - minipass-collect: 1.0.2 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - mkdirp: 1.0.4 - p-map: 4.0.0 - promise-inflight: 1.0.1_bluebird@3.7.2 - rimraf: 3.0.2 - ssri: 8.0.1 - tar: 6.1.11 - unique-filename: 1.1.1 - transitivePeerDependencies: - - bluebird - dev: true - - /cache-base/1.0.1: - resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} - engines: {node: '>=0.10.0'} - dependencies: - collection-visit: 1.0.0 - component-emitter: 1.3.0 - get-value: 2.0.6 - has-value: 1.0.0 - isobject: 3.0.1 - set-value: 2.0.1 - to-object-path: 0.3.0 - union-value: 1.0.1 - unset-value: 1.0.0 - dev: true - - /callsites/3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /camelcase/5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true - - /camelcase/6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - dev: true - - /caniuse-lite/1.0.30001352: - resolution: {integrity: sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA==} - dev: true - - /canvas/2.9.1: - resolution: {integrity: sha512-vSQti1uG/2gjv3x6QLOZw7TctfufaerTWbVe+NSduHxxLGB+qf3kFgQ6n66DSnuoINtVUjrLLIK2R+lxrBG07A==} - engines: {node: '>=6'} - requiresBuild: true - dependencies: - '@mapbox/node-pre-gyp': 1.0.9 - nan: 2.16.0 - simple-get: 3.1.1 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /capture-exit/2.0.0: - resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==} - engines: {node: 6.* || 8.* || >= 10.*} - dependencies: - rsvp: 4.8.5 - dev: true - - /chalk/2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk/4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /char-regex/1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - dev: true - - /chokidar/2.1.8: - resolution: {integrity: sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==} - deprecated: Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies - dependencies: - anymatch: 2.0.0 - async-each: 1.0.3 - braces: 2.3.2 - glob-parent: 3.1.0 - inherits: 2.0.4 - is-binary-path: 1.0.1 - is-glob: 4.0.3 - normalize-path: 3.0.0 - path-is-absolute: 1.0.1 - readdirp: 2.2.1 - upath: 1.2.0 - optionalDependencies: - fsevents: 1.2.13 - transitivePeerDependencies: - - supports-color - dev: true - optional: true - - /chokidar/3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - requiresBuild: true - dependencies: - anymatch: 3.1.2 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.2 - dev: true - optional: true - - /chownr/1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - dev: true - - /chownr/2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - dev: true - - /chrome-trace-event/1.0.3: - resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} - engines: {node: '>=6.0'} - dev: true - - /ci-info/2.0.0: - resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} - dev: true - - /cipher-base/1.0.4: - resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - - /cjs-module-lexer/0.6.0: - resolution: {integrity: sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==} - dev: true - - /class-utils/0.3.6: - resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} - engines: {node: '>=0.10.0'} - dependencies: - arr-union: 3.1.0 - define-property: 0.2.5 - isobject: 3.0.1 - static-extend: 0.1.2 - dev: true - - /clean-stack/2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: true - - /cliui/5.0.0: - resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==} - dependencies: - string-width: 3.1.0 - strip-ansi: 5.2.0 - wrap-ansi: 5.1.0 - dev: true - - /cliui/6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - dev: true - - /co/4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - dev: true - - /collect-v8-coverage/1.0.1: - resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} - dev: true - - /collection-visit/1.0.0: - resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} - engines: {node: '>=0.10.0'} - dependencies: - map-visit: 1.0.0 - object-visit: 1.0.1 - dev: true - - /color-convert/1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert/2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - - /color-name/1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name/1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - - /color-support/1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - dev: true - - /combined-stream/1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: true - - /commander/2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true - - /commondir/1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - dev: true - - /component-emitter/1.3.0: - resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} - dev: true - - /concat-map/0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /concat-stream/1.6.2: - resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} - engines: {'0': node >= 0.8} - dependencies: - buffer-from: 1.1.2 - inherits: 2.0.4 - readable-stream: 2.3.7 - typedarray: 0.0.6 - dev: true - - /console-browserify/1.2.0: - resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} - dev: true - - /console-control-strings/1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - dev: true - - /constants-browserify/1.0.0: - resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} - dev: true - - /convert-source-map/1.8.0: - resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} - dependencies: - safe-buffer: 5.1.2 - dev: true - - /copy-concurrently/1.0.5: - resolution: {integrity: sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==} - dependencies: - aproba: 1.2.0 - fs-write-stream-atomic: 1.0.10 - iferr: 0.1.5 - mkdirp: 0.5.6 - rimraf: 2.7.1 - run-queue: 1.0.3 - dev: true - - /copy-descriptor/0.1.1: - resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} - engines: {node: '>=0.10.0'} - dev: true - - /core-util-is/1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true - - /create-ecdh/4.0.4: - resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} - dependencies: - bn.js: 4.12.0 - elliptic: 6.5.4 - dev: true - - /create-hash/1.2.0: - resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} - dependencies: - cipher-base: 1.0.4 - inherits: 2.0.4 - md5.js: 1.3.5 - ripemd160: 2.0.2 - sha.js: 2.4.11 - dev: true - - /create-hmac/1.1.7: - resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} - dependencies: - cipher-base: 1.0.4 - create-hash: 1.2.0 - inherits: 2.0.4 - ripemd160: 2.0.2 - safe-buffer: 5.2.1 - sha.js: 2.4.11 - dev: true - - /cross-spawn/6.0.5: - resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} - engines: {node: '>=4.8'} - dependencies: - nice-try: 1.0.5 - path-key: 2.0.1 - semver: 5.7.1 - shebang-command: 1.2.0 - which: 1.3.1 - dev: true - - /cross-spawn/7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /crypto-browserify/3.12.0: - resolution: {integrity: sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==} - dependencies: - browserify-cipher: 1.0.1 - browserify-sign: 4.2.1 - create-ecdh: 4.0.4 - create-hash: 1.2.0 - create-hmac: 1.1.7 - diffie-hellman: 5.0.3 - inherits: 2.0.4 - pbkdf2: 3.1.2 - public-encrypt: 4.0.3 - randombytes: 2.1.0 - randomfill: 1.0.4 - dev: true - - /cssom/0.3.8: - resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} - dev: true - - /cssom/0.4.4: - resolution: {integrity: sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==} - dev: true - - /cssstyle/2.3.0: - resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} - engines: {node: '>=8'} - dependencies: - cssom: 0.3.8 - dev: true - - /cyclist/1.0.1: - resolution: {integrity: sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==} - dev: true - - /data-urls/2.0.0: - resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} - engines: {node: '>=10'} - dependencies: - abab: 2.0.6 - whatwg-mimetype: 2.3.0 - whatwg-url: 8.7.0 - dev: true - - /debug/2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: true - - /debug/2.6.9_supports-color@6.1.0: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - supports-color: 6.1.0 - dev: true - - /debug/4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /decamelize/1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /decimal.js/10.3.1: - resolution: {integrity: sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==} - dev: true - - /decode-uri-component/0.2.0: - resolution: {integrity: sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==} - engines: {node: '>=0.10'} - dev: true - - /decompress-response/4.2.1: - resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} - engines: {node: '>=8'} - dependencies: - mimic-response: 2.1.0 - dev: true - - /deep-is/0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /deepmerge/4.2.2: - resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} - engines: {node: '>=0.10.0'} - dev: true - - /define-property/0.2.5: - resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} - engines: {node: '>=0.10.0'} - dependencies: - is-descriptor: 0.1.6 - dev: true - - /define-property/1.0.0: - resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} - engines: {node: '>=0.10.0'} - dependencies: - is-descriptor: 1.0.2 - dev: true - - /define-property/2.0.2: - resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} - engines: {node: '>=0.10.0'} - dependencies: - is-descriptor: 1.0.2 - isobject: 3.0.1 - dev: true - - /delayed-stream/1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: true - - /delegates/1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - dev: true - - /des.js/1.0.1: - resolution: {integrity: sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==} - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - dev: true - - /detect-file/1.0.0: - resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} - engines: {node: '>=0.10.0'} - dev: true - - /detect-libc/2.0.1: - resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==} - engines: {node: '>=8'} - dev: true - - /detect-newline/3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - dev: true - - /diff-sequences/26.6.2: - resolution: {integrity: sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==} - engines: {node: '>= 10.14.2'} - dev: true - - /diffie-hellman/5.0.3: - resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} - dependencies: - bn.js: 4.12.0 - miller-rabin: 4.0.1 - randombytes: 2.1.0 - dev: true - - /doctrine/3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /domain-browser/1.2.0: - resolution: {integrity: sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==} - engines: {node: '>=0.4', npm: '>=1.2'} - dev: true - - /domexception/2.0.1: - resolution: {integrity: sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==} - engines: {node: '>=8'} - dependencies: - webidl-conversions: 5.0.0 - dev: true - - /duplexify/3.7.1: - resolution: {integrity: sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==} - dependencies: - end-of-stream: 1.4.4 - inherits: 2.0.4 - readable-stream: 2.3.7 - stream-shift: 1.0.1 - dev: true - - /electron-to-chromium/1.4.150: - resolution: {integrity: sha512-MP3oBer0X7ZeS9GJ0H6lmkn561UxiwOIY9TTkdxVY7lI9G6GVCKfgJaHaDcakwdKxBXA4T3ybeswH/WBIN/KTA==} - dev: true - - /elliptic/6.5.4: - resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} - dependencies: - bn.js: 4.12.0 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - dev: true - - /emittery/0.7.2: - resolution: {integrity: sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==} - engines: {node: '>=10'} - dev: true - - /emoji-regex/7.0.3: - resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==} - dev: true - - /emoji-regex/8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true - - /emojis-list/3.0.0: - resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} - engines: {node: '>= 4'} - dev: true - - /end-of-stream/1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - dependencies: - once: 1.4.0 - dev: true - - /enhanced-resolve/4.5.0: - resolution: {integrity: sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==} - engines: {node: '>=6.9.0'} - dependencies: - graceful-fs: 4.2.10 - memory-fs: 0.5.0 - tapable: 1.1.3 - dev: true - - /enquirer/2.3.6: - resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} - engines: {node: '>=8.6'} - dependencies: - ansi-colors: 4.1.3 - dev: true - - /errno/0.1.8: - resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} - hasBin: true - dependencies: - prr: 1.0.1 - dev: true - - /error-ex/1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /escalade/3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - dev: true - - /escape-string-regexp/1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp/2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - dev: true - - /escape-string-regexp/4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /escodegen/2.0.0: - resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==} - engines: {node: '>=6.0'} - hasBin: true - dependencies: - esprima: 4.0.1 - estraverse: 5.3.0 - esutils: 2.0.3 - optionator: 0.8.3 - optionalDependencies: - source-map: 0.6.1 - dev: true - - /eslint-config-prettier/6.15.0_eslint@7.32.0: - resolution: {integrity: sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==} - hasBin: true - peerDependencies: - eslint: '>=3.14.1' - dependencies: - eslint: 7.32.0 - get-stdin: 6.0.0 - dev: true - - /eslint-plugin-jest/23.20.0_2de3j2mqba4wgeuiaqz2k7syrm: - resolution: {integrity: sha512-+6BGQt85OREevBDWCvhqj1yYA4+BFK4XnRZSGJionuEYmcglMZYLNNBBemwzbqUAckURaHdJSBcjHPyrtypZOw==} - engines: {node: '>=8'} - peerDependencies: - eslint: '>=5' - dependencies: - '@typescript-eslint/experimental-utils': 2.34.0_2de3j2mqba4wgeuiaqz2k7syrm - eslint: 7.32.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-prettier/3.4.1_dnozcfbeb5wiozlftdrslmvmgu: - resolution: {integrity: sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==} - engines: {node: '>=6.0.0'} - peerDependencies: - eslint: '>=5.0.0' - eslint-config-prettier: '*' - prettier: '>=1.13.0' - peerDependenciesMeta: - eslint-config-prettier: - optional: true - dependencies: - eslint: 7.32.0 - eslint-config-prettier: 6.15.0_eslint@7.32.0 - prettier: 2.6.0 - prettier-linter-helpers: 1.0.0 - dev: true - - /eslint-scope/4.0.3: - resolution: {integrity: sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==} - engines: {node: '>=4.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope/5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-utils/2.1.0: - resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} - engines: {node: '>=6'} - dependencies: - eslint-visitor-keys: 1.3.0 - dev: true - - /eslint-visitor-keys/1.3.0: - resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} - engines: {node: '>=4'} - dev: true - - /eslint-visitor-keys/2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint/7.32.0: - resolution: {integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==} - engines: {node: ^10.12.0 || >=12.0.0} - hasBin: true - dependencies: - '@babel/code-frame': 7.12.11 - '@eslint/eslintrc': 0.4.3 - '@humanwhocodes/config-array': 0.5.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - enquirer: 2.3.6 - escape-string-regexp: 4.0.0 - eslint-scope: 5.1.1 - eslint-utils: 2.1.0 - eslint-visitor-keys: 2.1.0 - espree: 7.3.1 - esquery: 1.4.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - functional-red-black-tree: 1.0.1 - glob-parent: 5.1.2 - globals: 13.15.0 - ignore: 4.0.6 - import-fresh: 3.3.0 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - js-yaml: 3.14.1 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.1 - progress: 2.0.3 - regexpp: 3.2.0 - semver: 7.3.7 - strip-ansi: 6.0.1 - strip-json-comments: 3.1.1 - table: 6.8.0 - text-table: 0.2.0 - v8-compile-cache: 2.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree/7.3.1: - resolution: {integrity: sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - acorn: 7.4.1 - acorn-jsx: 5.3.2_acorn@7.4.1 - eslint-visitor-keys: 1.3.0 - dev: true - - /esprima/4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /esquery/1.4.0: - resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse/4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse/4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse/5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /esutils/2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /events/3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - dev: true - - /evp_bytestokey/1.0.3: - resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} - dependencies: - md5.js: 1.3.5 - safe-buffer: 5.2.1 - dev: true - - /exec-sh/0.3.6: - resolution: {integrity: sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==} - dev: true - - /execa/1.0.0: - resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} - engines: {node: '>=6'} - dependencies: - cross-spawn: 6.0.5 - get-stream: 4.1.0 - is-stream: 1.1.0 - npm-run-path: 2.0.2 - p-finally: 1.0.0 - signal-exit: 3.0.7 - strip-eof: 1.0.0 - dev: true - - /execa/4.1.0: - resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 5.2.0 - human-signals: 1.1.1 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /exit/0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} - dev: true - - /expand-brackets/2.1.4: - resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} - engines: {node: '>=0.10.0'} - dependencies: - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - posix-character-classes: 0.1.1 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /expand-brackets/2.1.4_supports-color@6.1.0: - resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} - engines: {node: '>=0.10.0'} - dependencies: - debug: 2.6.9_supports-color@6.1.0 - define-property: 0.2.5 - extend-shallow: 2.0.1 - posix-character-classes: 0.1.1 - regex-not: 1.0.2 - snapdragon: 0.8.2_supports-color@6.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /expand-tilde/2.0.2: - resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} - engines: {node: '>=0.10.0'} - dependencies: - homedir-polyfill: 1.0.3 - dev: true - - /expect/26.6.2: - resolution: {integrity: sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/types': 26.6.2 - ansi-styles: 4.3.0 - jest-get-type: 26.3.0 - jest-matcher-utils: 26.6.2 - jest-message-util: 26.6.2 - jest-regex-util: 26.0.0 - dev: true - - /extend-shallow/2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} - dependencies: - is-extendable: 0.1.1 - dev: true - - /extend-shallow/3.0.2: - resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} - engines: {node: '>=0.10.0'} - dependencies: - assign-symbols: 1.0.0 - is-extendable: 1.0.1 - dev: true - - /extglob/2.0.4: - resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} - engines: {node: '>=0.10.0'} - dependencies: - 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.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /extglob/2.0.4_supports-color@6.1.0: - resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} - engines: {node: '>=0.10.0'} - dependencies: - array-unique: 0.3.2 - define-property: 1.0.0 - expand-brackets: 2.1.4_supports-color@6.1.0 - extend-shallow: 2.0.1 - fragment-cache: 0.2.1 - regex-not: 1.0.2 - snapdragon: 0.8.2_supports-color@6.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /fast-deep-equal/3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-diff/1.2.0: - resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} - dev: true - - /fast-json-stable-stringify/2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein/2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fb-watchman/2.0.1: - resolution: {integrity: sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==} - dependencies: - bser: 2.1.1 - dev: true - - /figgy-pudding/3.5.2: - resolution: {integrity: sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==} - dev: true - - /file-entry-cache/6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.0.4 - dev: true - - /file-uri-to-path/1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - dev: true - optional: true - - /fill-range/4.0.0: - resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 2.0.1 - is-number: 3.0.0 - repeat-string: 1.6.1 - to-regex-range: 2.1.1 - dev: true - - /fill-range/7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /find-cache-dir/2.1.0: - resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==} - engines: {node: '>=6'} - dependencies: - commondir: 1.0.1 - make-dir: 2.1.0 - pkg-dir: 3.0.0 - dev: true - - /find-cache-dir/3.3.2: - resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} - engines: {node: '>=8'} - dependencies: - commondir: 1.0.1 - make-dir: 3.1.0 - pkg-dir: 4.2.0 - dev: true - - /find-up/3.0.0: - resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} - engines: {node: '>=6'} - dependencies: - locate-path: 3.0.0 - dev: true - - /find-up/4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /findup-sync/3.0.0_supports-color@6.1.0: - resolution: {integrity: sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==} - engines: {node: '>= 0.10'} - dependencies: - detect-file: 1.0.0 - is-glob: 4.0.3 - micromatch: 3.1.10_supports-color@6.1.0 - resolve-dir: 1.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /flat-cache/3.0.4: - resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.2.5 - rimraf: 3.0.2 - dev: true - - /flatted/3.2.5: - resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} - dev: true - - /flush-write-stream/1.1.1: - resolution: {integrity: sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==} - dependencies: - inherits: 2.0.4 - readable-stream: 2.3.7 - dev: true - - /for-in/1.0.2: - resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} - engines: {node: '>=0.10.0'} - dev: true - - /form-data/3.0.1: - resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: true - - /fragment-cache/0.2.1: - resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} - engines: {node: '>=0.10.0'} - dependencies: - map-cache: 0.2.2 - dev: true - - /from2/2.3.0: - resolution: {integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==} - dependencies: - inherits: 2.0.4 - readable-stream: 2.3.7 - dev: true - - /fs-minipass/2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.1.6 - dev: true - - /fs-write-stream-atomic/1.0.10: - resolution: {integrity: sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==} - dependencies: - graceful-fs: 4.2.10 - iferr: 0.1.5 - imurmurhash: 0.1.4 - readable-stream: 2.3.7 - dev: true - - /fs.realpath/1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents/1.2.13: - resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==} - engines: {node: '>= 4.0'} - os: [darwin] - deprecated: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2. - requiresBuild: true - dependencies: - bindings: 1.5.0 - nan: 2.16.0 - dev: true - optional: true - - /fsevents/2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind/1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true - - /functional-red-black-tree/1.0.1: - resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} - dev: true - - /gauge/3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - dev: true - - /gensync/1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-caller-file/2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true - - /get-package-type/0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - dev: true - - /get-stdin/6.0.0: - resolution: {integrity: sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==} - engines: {node: '>=4'} - dev: true - - /get-stream/4.1.0: - resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} - engines: {node: '>=6'} - dependencies: - pump: 3.0.0 - dev: true - - /get-stream/5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} - engines: {node: '>=8'} - dependencies: - pump: 3.0.0 - dev: true - - /get-value/2.0.6: - resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} - engines: {node: '>=0.10.0'} - dev: true - - /glob-parent/3.1.0: - resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==} - dependencies: - is-glob: 3.1.0 - path-dirname: 1.0.2 - dev: true - optional: true - - /glob-parent/5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob/7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /global-modules/1.0.0: - resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==} - engines: {node: '>=0.10.0'} - dependencies: - global-prefix: 1.0.2 - is-windows: 1.0.2 - resolve-dir: 1.0.1 - dev: true - - /global-modules/2.0.0: - resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} - engines: {node: '>=6'} - dependencies: - global-prefix: 3.0.0 - dev: true - - /global-prefix/1.0.2: - resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} - engines: {node: '>=0.10.0'} - dependencies: - expand-tilde: 2.0.2 - homedir-polyfill: 1.0.3 - ini: 1.3.8 - is-windows: 1.0.2 - which: 1.3.1 - dev: true - - /global-prefix/3.0.0: - resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} - engines: {node: '>=6'} - dependencies: - ini: 1.3.8 - kind-of: 6.0.3 - which: 1.3.1 - dev: true - - /globals/11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globals/13.15.0: - resolution: {integrity: sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /graceful-fs/4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - dev: true - - /growly/1.3.0: - resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} - dev: true - optional: true - - /has-flag/3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag/4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /has-unicode/2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - dev: true - - /has-value/0.3.1: - resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} - engines: {node: '>=0.10.0'} - dependencies: - get-value: 2.0.6 - has-values: 0.1.4 - isobject: 2.1.0 - dev: true - - /has-value/1.0.0: - resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} - engines: {node: '>=0.10.0'} - dependencies: - get-value: 2.0.6 - has-values: 1.0.0 - isobject: 3.0.1 - dev: true - - /has-values/0.1.4: - resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} - engines: {node: '>=0.10.0'} - dev: true - - /has-values/1.0.0: - resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} - engines: {node: '>=0.10.0'} - dependencies: - is-number: 3.0.0 - kind-of: 4.0.0 - dev: true - - /has/1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.1 - dev: true - - /hash-base/3.1.0: - resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} - engines: {node: '>=4'} - dependencies: - inherits: 2.0.4 - readable-stream: 3.6.0 - safe-buffer: 5.2.1 - dev: true - - /hash.js/1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - dev: true - - /hmac-drbg/1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - dependencies: - hash.js: 1.1.7 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - dev: true - - /homedir-polyfill/1.0.3: - resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} - engines: {node: '>=0.10.0'} - dependencies: - parse-passwd: 1.0.0 - dev: true - - /hosted-git-info/2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true - - /html-encoding-sniffer/2.0.1: - resolution: {integrity: sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==} - engines: {node: '>=10'} - dependencies: - whatwg-encoding: 1.0.5 - dev: true - - /html-escaper/2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - dev: true - - /http-proxy-agent/4.0.1: - resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} - engines: {node: '>= 6'} - dependencies: - '@tootallnate/once': 1.1.2 - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /https-browserify/1.0.0: - resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} - dev: true - - /https-proxy-agent/5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /human-signals/1.1.1: - resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} - engines: {node: '>=8.12.0'} - dev: true - - /iconv-lite/0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - - /ieee754/1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true - - /iferr/0.1.5: - resolution: {integrity: sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==} - dev: true - - /ignore/4.0.6: - resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} - engines: {node: '>= 4'} - dev: true - - /import-fresh/3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /import-local/2.0.0: - resolution: {integrity: sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==} - engines: {node: '>=6'} - hasBin: true - dependencies: - pkg-dir: 3.0.0 - resolve-cwd: 2.0.0 - dev: true - - /import-local/3.1.0: - resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} - engines: {node: '>=8'} - hasBin: true - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - dev: true - - /imurmurhash/0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /indent-string/4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true - - /infer-owner/1.0.4: - resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} - dev: true - - /inflight/1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits/2.0.1: - resolution: {integrity: sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==} - dev: true - - /inherits/2.0.3: - resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} - dev: true - - /inherits/2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - - /ini/1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true - - /interpret/1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} - dev: true - - /is-accessor-descriptor/0.1.6: - resolution: {integrity: sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: true - - /is-accessor-descriptor/1.0.0: - resolution: {integrity: sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 6.0.3 - dev: true - - /is-arrayish/0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-binary-path/1.0.1: - resolution: {integrity: sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==} - engines: {node: '>=0.10.0'} - dependencies: - binary-extensions: 1.13.1 - dev: true - optional: true - - /is-binary-path/2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 - dev: true - optional: true - - /is-buffer/1.1.6: - resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - dev: true - - /is-ci/2.0.0: - resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} - hasBin: true - dependencies: - ci-info: 2.0.0 - dev: true - - /is-core-module/2.9.0: - resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} - dependencies: - has: 1.0.3 - dev: true - - /is-data-descriptor/0.1.4: - resolution: {integrity: sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: true - - /is-data-descriptor/1.0.0: - resolution: {integrity: sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 6.0.3 - dev: true - - /is-descriptor/0.1.6: - resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} - engines: {node: '>=0.10.0'} - dependencies: - is-accessor-descriptor: 0.1.6 - is-data-descriptor: 0.1.4 - kind-of: 5.1.0 - dev: true - - /is-descriptor/1.0.2: - resolution: {integrity: sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==} - engines: {node: '>=0.10.0'} - dependencies: - is-accessor-descriptor: 1.0.0 - is-data-descriptor: 1.0.0 - kind-of: 6.0.3 - dev: true - - /is-docker/2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: true - optional: true - - /is-extendable/0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - dev: true - - /is-extendable/1.0.1: - resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} - engines: {node: '>=0.10.0'} - dependencies: - is-plain-object: 2.0.4 - dev: true - - /is-extglob/2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-fullwidth-code-point/2.0.0: - resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} - engines: {node: '>=4'} - dev: true - - /is-fullwidth-code-point/3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true - - /is-generator-fn/2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - dev: true - - /is-glob/3.1.0: - resolution: {integrity: sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - optional: true - - /is-glob/4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-number/3.0.0: - resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: true - - /is-number/7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-plain-object/2.0.4: - resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: true - - /is-potential-custom-element-name/1.0.1: - resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - dev: true - - /is-stream/1.1.0: - resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-stream/2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /is-typedarray/1.0.0: - resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - dev: true - - /is-windows/1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - dev: true - - /is-wsl/1.1.0: - resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==} - engines: {node: '>=4'} - dev: true - - /is-wsl/2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: true - optional: true - - /isarray/1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true - - /isexe/2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /isobject/2.1.0: - resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} - engines: {node: '>=0.10.0'} - dependencies: - isarray: 1.0.0 - dev: true - - /isobject/3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - dev: true - - /istanbul-lib-coverage/3.2.0: - resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} - engines: {node: '>=8'} - dev: true - - /istanbul-lib-instrument/4.0.3: - resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} - engines: {node: '>=8'} - dependencies: - '@babel/core': 7.18.2 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.0 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-lib-instrument/5.2.0: - resolution: {integrity: sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==} - engines: {node: '>=8'} - dependencies: - '@babel/core': 7.18.2 - '@babel/parser': 7.18.4 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.0 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-lib-report/3.0.0: - resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} - engines: {node: '>=8'} - dependencies: - istanbul-lib-coverage: 3.2.0 - make-dir: 3.1.0 - supports-color: 7.2.0 - dev: true - - /istanbul-lib-source-maps/4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - dependencies: - debug: 4.3.4 - istanbul-lib-coverage: 3.2.0 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-reports/3.1.4: - resolution: {integrity: sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==} - engines: {node: '>=8'} - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.0 - dev: true - - /jest-changed-files/26.6.2: - resolution: {integrity: sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/types': 26.6.2 - execa: 4.1.0 - throat: 5.0.0 - dev: true - - /jest-cli/26.6.3_canvas@2.9.1: - resolution: {integrity: sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==} - engines: {node: '>= 10.14.2'} - hasBin: true - dependencies: - '@jest/core': 26.6.3_canvas@2.9.1 - '@jest/test-result': 26.6.2 - '@jest/types': 26.6.2 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.10 - import-local: 3.1.0 - is-ci: 2.0.0 - jest-config: 26.6.3_canvas@2.9.1 - jest-util: 26.6.2 - jest-validate: 26.6.2 - prompts: 2.4.2 - yargs: 15.4.1 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - ts-node - - utf-8-validate - dev: true - - /jest-config/26.6.3_canvas@2.9.1: - resolution: {integrity: sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==} - engines: {node: '>= 10.14.2'} - peerDependencies: - ts-node: '>=9.0.0' - peerDependenciesMeta: - ts-node: - optional: true - dependencies: - '@babel/core': 7.18.2 - '@jest/test-sequencer': 26.6.3_canvas@2.9.1 - '@jest/types': 26.6.2 - babel-jest: 26.6.3_@babel+core@7.18.2 - chalk: 4.1.2 - deepmerge: 4.2.2 - glob: 7.2.3 - graceful-fs: 4.2.10 - jest-environment-jsdom: 26.6.2_canvas@2.9.1 - jest-environment-node: 26.6.2 - jest-get-type: 26.3.0 - jest-jasmine2: 26.6.3_canvas@2.9.1 - jest-regex-util: 26.0.0 - jest-resolve: 26.6.2 - jest-util: 26.6.2 - jest-validate: 26.6.2 - micromatch: 4.0.5 - pretty-format: 26.6.2 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - utf-8-validate - dev: true - - /jest-diff/26.6.2: - resolution: {integrity: sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==} - engines: {node: '>= 10.14.2'} - dependencies: - chalk: 4.1.2 - diff-sequences: 26.6.2 - jest-get-type: 26.3.0 - pretty-format: 26.6.2 - dev: true - - /jest-docblock/26.0.0: - resolution: {integrity: sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==} - engines: {node: '>= 10.14.2'} - dependencies: - detect-newline: 3.1.0 - dev: true - - /jest-each/26.6.2: - resolution: {integrity: sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/types': 26.6.2 - chalk: 4.1.2 - jest-get-type: 26.3.0 - jest-util: 26.6.2 - pretty-format: 26.6.2 - dev: true - - /jest-environment-jsdom/26.6.2_canvas@2.9.1: - resolution: {integrity: sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/environment': 26.6.2 - '@jest/fake-timers': 26.6.2 - '@jest/types': 26.6.2 - '@types/node': 17.0.41 - jest-mock: 26.6.2 - jest-util: 26.6.2 - jsdom: 16.7.0_canvas@2.9.1 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - utf-8-validate - dev: true - - /jest-environment-node/26.6.2: - resolution: {integrity: sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/environment': 26.6.2 - '@jest/fake-timers': 26.6.2 - '@jest/types': 26.6.2 - '@types/node': 17.0.41 - jest-mock: 26.6.2 - jest-util: 26.6.2 - dev: true - - /jest-get-type/26.3.0: - resolution: {integrity: sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==} - engines: {node: '>= 10.14.2'} - dev: true - - /jest-haste-map/26.6.2: - resolution: {integrity: sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/types': 26.6.2 - '@types/graceful-fs': 4.1.5 - '@types/node': 17.0.41 - anymatch: 3.1.2 - fb-watchman: 2.0.1 - graceful-fs: 4.2.10 - jest-regex-util: 26.0.0 - jest-serializer: 26.6.2 - jest-util: 26.6.2 - jest-worker: 26.6.2 - micromatch: 4.0.5 - sane: 4.1.0 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.2 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-jasmine2/26.6.3_canvas@2.9.1: - resolution: {integrity: sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==} - engines: {node: '>= 10.14.2'} - dependencies: - '@babel/traverse': 7.18.2 - '@jest/environment': 26.6.2 - '@jest/source-map': 26.6.2 - '@jest/test-result': 26.6.2 - '@jest/types': 26.6.2 - '@types/node': 17.0.41 - chalk: 4.1.2 - co: 4.6.0 - expect: 26.6.2 - is-generator-fn: 2.1.0 - jest-each: 26.6.2 - jest-matcher-utils: 26.6.2 - jest-message-util: 26.6.2 - jest-runtime: 26.6.3_canvas@2.9.1 - jest-snapshot: 26.6.2 - jest-util: 26.6.2 - pretty-format: 26.6.2 - throat: 5.0.0 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - ts-node - - utf-8-validate - dev: true - - /jest-leak-detector/26.6.2: - resolution: {integrity: sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==} - engines: {node: '>= 10.14.2'} - dependencies: - jest-get-type: 26.3.0 - pretty-format: 26.6.2 - dev: true - - /jest-matcher-utils/26.6.2: - resolution: {integrity: sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==} - engines: {node: '>= 10.14.2'} - dependencies: - chalk: 4.1.2 - jest-diff: 26.6.2 - jest-get-type: 26.3.0 - pretty-format: 26.6.2 - dev: true - - /jest-message-util/26.6.2: - resolution: {integrity: sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==} - engines: {node: '>= 10.14.2'} - dependencies: - '@babel/code-frame': 7.16.7 - '@jest/types': 26.6.2 - '@types/stack-utils': 2.0.1 - chalk: 4.1.2 - graceful-fs: 4.2.10 - micromatch: 4.0.5 - pretty-format: 26.6.2 - slash: 3.0.0 - stack-utils: 2.0.5 - dev: true - - /jest-mock/26.6.2: - resolution: {integrity: sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/types': 26.6.2 - '@types/node': 17.0.41 - dev: true - - /jest-pnp-resolver/1.2.2_jest-resolve@26.6.2: - resolution: {integrity: sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - dependencies: - jest-resolve: 26.6.2 - dev: true - - /jest-regex-util/26.0.0: - resolution: {integrity: sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==} - engines: {node: '>= 10.14.2'} - dev: true - - /jest-resolve-dependencies/26.6.3: - resolution: {integrity: sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/types': 26.6.2 - jest-regex-util: 26.0.0 - jest-snapshot: 26.6.2 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-resolve/26.6.2: - resolution: {integrity: sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/types': 26.6.2 - chalk: 4.1.2 - graceful-fs: 4.2.10 - jest-pnp-resolver: 1.2.2_jest-resolve@26.6.2 - jest-util: 26.6.2 - read-pkg-up: 7.0.1 - resolve: 1.22.0 - slash: 3.0.0 - dev: true - - /jest-runner/26.6.3_canvas@2.9.1: - resolution: {integrity: sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/console': 26.6.2 - '@jest/environment': 26.6.2 - '@jest/test-result': 26.6.2 - '@jest/types': 26.6.2 - '@types/node': 17.0.41 - chalk: 4.1.2 - emittery: 0.7.2 - exit: 0.1.2 - graceful-fs: 4.2.10 - jest-config: 26.6.3_canvas@2.9.1 - jest-docblock: 26.0.0 - jest-haste-map: 26.6.2 - jest-leak-detector: 26.6.2 - jest-message-util: 26.6.2 - jest-resolve: 26.6.2 - jest-runtime: 26.6.3_canvas@2.9.1 - jest-util: 26.6.2 - jest-worker: 26.6.2 - source-map-support: 0.5.21 - throat: 5.0.0 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - ts-node - - utf-8-validate - dev: true - - /jest-runtime/26.6.3_canvas@2.9.1: - resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==} - engines: {node: '>= 10.14.2'} - hasBin: true - dependencies: - '@jest/console': 26.6.2 - '@jest/environment': 26.6.2 - '@jest/fake-timers': 26.6.2 - '@jest/globals': 26.6.2 - '@jest/source-map': 26.6.2 - '@jest/test-result': 26.6.2 - '@jest/transform': 26.6.2 - '@jest/types': 26.6.2 - '@types/yargs': 15.0.14 - chalk: 4.1.2 - cjs-module-lexer: 0.6.0 - collect-v8-coverage: 1.0.1 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.10 - jest-config: 26.6.3_canvas@2.9.1 - jest-haste-map: 26.6.2 - jest-message-util: 26.6.2 - jest-mock: 26.6.2 - jest-regex-util: 26.0.0 - jest-resolve: 26.6.2 - jest-snapshot: 26.6.2 - jest-util: 26.6.2 - jest-validate: 26.6.2 - slash: 3.0.0 - strip-bom: 4.0.0 - yargs: 15.4.1 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - ts-node - - utf-8-validate - dev: true - - /jest-serializer/26.6.2: - resolution: {integrity: sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==} - engines: {node: '>= 10.14.2'} - dependencies: - '@types/node': 17.0.41 - graceful-fs: 4.2.10 - dev: true - - /jest-snapshot/26.6.2: - resolution: {integrity: sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==} - engines: {node: '>= 10.14.2'} - dependencies: - '@babel/types': 7.18.4 - '@jest/types': 26.6.2 - '@types/babel__traverse': 7.17.1 - '@types/prettier': 2.6.0 - chalk: 4.1.2 - expect: 26.6.2 - graceful-fs: 4.2.10 - jest-diff: 26.6.2 - jest-get-type: 26.3.0 - jest-haste-map: 26.6.2 - jest-matcher-utils: 26.6.2 - jest-message-util: 26.6.2 - jest-resolve: 26.6.2 - natural-compare: 1.4.0 - pretty-format: 26.6.2 - semver: 7.3.7 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-util/26.6.2: - resolution: {integrity: sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/types': 26.6.2 - '@types/node': 17.0.41 - chalk: 4.1.2 - graceful-fs: 4.2.10 - is-ci: 2.0.0 - micromatch: 4.0.5 - dev: true - - /jest-validate/26.6.2: - resolution: {integrity: sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/types': 26.6.2 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 26.3.0 - leven: 3.1.0 - pretty-format: 26.6.2 - dev: true - - /jest-watcher/26.6.2: - resolution: {integrity: sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==} - engines: {node: '>= 10.14.2'} - dependencies: - '@jest/test-result': 26.6.2 - '@jest/types': 26.6.2 - '@types/node': 17.0.41 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - jest-util: 26.6.2 - string-length: 4.0.2 - dev: true - - /jest-worker/26.6.2: - resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/node': 17.0.41 - merge-stream: 2.0.0 - supports-color: 7.2.0 - dev: true - - /jest/26.6.3_canvas@2.9.1: - resolution: {integrity: sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==} - engines: {node: '>= 10.14.2'} - hasBin: true - dependencies: - '@jest/core': 26.6.3_canvas@2.9.1 - import-local: 3.1.0 - jest-cli: 26.6.3_canvas@2.9.1 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - ts-node - - utf-8-validate - dev: true - - /js-tokens/4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - - /js-yaml/3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: true - - /jsdom/16.7.0_canvas@2.9.1: - resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==} - engines: {node: '>=10'} - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - dependencies: - abab: 2.0.6 - acorn: 8.7.1 - acorn-globals: 6.0.0 - canvas: 2.9.1 - cssom: 0.4.4 - cssstyle: 2.3.0 - data-urls: 2.0.0 - decimal.js: 10.3.1 - domexception: 2.0.1 - escodegen: 2.0.0 - form-data: 3.0.1 - html-encoding-sniffer: 2.0.1 - http-proxy-agent: 4.0.1 - https-proxy-agent: 5.0.1 - is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.0 - parse5: 6.0.1 - saxes: 5.0.1 - symbol-tree: 3.2.4 - tough-cookie: 4.0.0 - w3c-hr-time: 1.0.2 - w3c-xmlserializer: 2.0.0 - webidl-conversions: 6.1.0 - whatwg-encoding: 1.0.5 - whatwg-mimetype: 2.3.0 - whatwg-url: 8.7.0 - ws: 7.5.8 - xml-name-validator: 3.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /jsesc/2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /json-parse-better-errors/1.0.2: - resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} - dev: true - - /json-parse-even-better-errors/2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-schema-traverse/0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-schema-traverse/1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true - - /json-stable-stringify-without-jsonify/1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json5/1.0.1: - resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} - hasBin: true - dependencies: - minimist: 1.2.6 - dev: true - - /json5/2.2.1: - resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /kind-of/3.2.2: - resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} - engines: {node: '>=0.10.0'} - dependencies: - is-buffer: 1.1.6 - dev: true - - /kind-of/4.0.0: - resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} - engines: {node: '>=0.10.0'} - dependencies: - is-buffer: 1.1.6 - dev: true - - /kind-of/5.1.0: - resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} - engines: {node: '>=0.10.0'} - dev: true - - /kind-of/6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true - - /kleur/3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - dev: true - - /leven/3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - dev: true - - /levn/0.3.0: - resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - type-check: 0.3.2 - dev: true - - /levn/0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lines-and-columns/1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /loader-runner/2.4.0: - resolution: {integrity: sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==} - engines: {node: '>=4.3.0 <5.0.0 || >=5.10'} - dev: true - - /loader-utils/1.4.0: - resolution: {integrity: sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==} - engines: {node: '>=4.0.0'} - dependencies: - big.js: 5.2.2 - emojis-list: 3.0.0 - json5: 1.0.1 - dev: true - - /loader-utils/2.0.2: - resolution: {integrity: sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==} - engines: {node: '>=8.9.0'} - dependencies: - big.js: 5.2.2 - emojis-list: 3.0.0 - json5: 2.2.1 - dev: true - - /locate-path/3.0.0: - resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} - engines: {node: '>=6'} - dependencies: - p-locate: 3.0.0 - path-exists: 3.0.0 - dev: true - - /locate-path/5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /lodash.merge/4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash.truncate/4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - dev: true - - /lodash/4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - - /lru-cache/5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /lru-cache/6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - - /make-dir/2.1.0: - resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} - engines: {node: '>=6'} - dependencies: - pify: 4.0.1 - semver: 5.7.1 - dev: true - - /make-dir/3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - dependencies: - semver: 6.3.0 - dev: true - - /make-error/1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true - - /makeerror/1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - dependencies: - tmpl: 1.0.5 - dev: true - - /map-cache/0.2.2: - resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} - engines: {node: '>=0.10.0'} - dev: true - - /map-visit/1.0.0: - resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} - engines: {node: '>=0.10.0'} - dependencies: - object-visit: 1.0.1 - dev: true - - /md5.js/1.3.5: - resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} - dependencies: - hash-base: 3.1.0 - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - - /memory-fs/0.4.1: - resolution: {integrity: sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==} - dependencies: - errno: 0.1.8 - readable-stream: 2.3.7 - dev: true - - /memory-fs/0.5.0: - resolution: {integrity: sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==} - engines: {node: '>=4.3.0 <5.0.0 || >=5.10'} - dependencies: - errno: 0.1.8 - readable-stream: 2.3.7 - dev: true - - /merge-stream/2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /micromatch/3.1.10: - resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} - engines: {node: '>=0.10.0'} - dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - braces: 2.3.2 - define-property: 2.0.2 - extend-shallow: 3.0.2 - extglob: 2.0.4 - fragment-cache: 0.2.1 - kind-of: 6.0.3 - nanomatch: 1.2.13 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /micromatch/3.1.10_supports-color@6.1.0: - resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} - engines: {node: '>=0.10.0'} - dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - braces: 2.3.2_supports-color@6.1.0 - define-property: 2.0.2 - extend-shallow: 3.0.2 - extglob: 2.0.4_supports-color@6.1.0 - fragment-cache: 0.2.1 - kind-of: 6.0.3 - nanomatch: 1.2.13_supports-color@6.1.0 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2_supports-color@6.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /micromatch/4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /miller-rabin/4.0.1: - resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} - hasBin: true - dependencies: - bn.js: 4.12.0 - brorand: 1.1.0 - dev: true - - /mime-db/1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: true - - /mime-types/2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - - /mimic-fn/2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /mimic-response/2.1.0: - resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} - engines: {node: '>=8'} - dev: true - - /minimalistic-assert/1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: true - - /minimalistic-crypto-utils/1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - dev: true - - /minimatch/3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimist/1.2.6: - resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} - dev: true - - /minipass-collect/1.0.2: - resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.1.6 - dev: true - - /minipass-flush/1.0.5: - resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.1.6 - dev: true - - /minipass-pipeline/1.2.4: - resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} - engines: {node: '>=8'} - dependencies: - minipass: 3.1.6 - dev: true - - /minipass/3.1.6: - resolution: {integrity: sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==} - engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - dev: true - - /minizlib/2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.1.6 - yallist: 4.0.0 - dev: true - - /mississippi/3.0.0: - resolution: {integrity: sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==} - engines: {node: '>=4.0.0'} - dependencies: - concat-stream: 1.6.2 - duplexify: 3.7.1 - end-of-stream: 1.4.4 - flush-write-stream: 1.1.1 - from2: 2.3.0 - parallel-transform: 1.2.0 - pump: 3.0.0 - pumpify: 1.5.1 - stream-each: 1.2.3 - through2: 2.0.5 - dev: true - - /mixin-deep/1.3.2: - resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} - engines: {node: '>=0.10.0'} - dependencies: - for-in: 1.0.2 - is-extendable: 1.0.1 - dev: true - - /mkdirp/0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - dependencies: - minimist: 1.2.6 - dev: true - - /mkdirp/1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /move-concurrently/1.0.1: - resolution: {integrity: sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==} - dependencies: - aproba: 1.2.0 - copy-concurrently: 1.0.5 - fs-write-stream-atomic: 1.0.10 - mkdirp: 0.5.6 - rimraf: 2.7.1 - run-queue: 1.0.3 - dev: true - - /ms/2.0.0: - resolution: {integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=} - dev: true - - /ms/2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - - /nan/2.16.0: - resolution: {integrity: sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==} - dev: true - - /nanomatch/1.2.13: - resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} - engines: {node: '>=0.10.0'} - dependencies: - 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.3 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /nanomatch/1.2.13_supports-color@6.1.0: - resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} - engines: {node: '>=0.10.0'} - dependencies: - 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.3 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2_supports-color@6.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /natural-compare/1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /neo-async/2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - - /nice-try/1.0.5: - resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} - dev: true - - /node-fetch/2.6.7: - resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: true - - /node-int64/0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - dev: true - - /node-libs-browser/2.2.1: - resolution: {integrity: sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==} - dependencies: - assert: 1.5.0 - browserify-zlib: 0.2.0 - buffer: 4.9.2 - console-browserify: 1.2.0 - constants-browserify: 1.0.0 - crypto-browserify: 3.12.0 - domain-browser: 1.2.0 - events: 3.3.0 - https-browserify: 1.0.0 - os-browserify: 0.3.0 - path-browserify: 0.0.1 - process: 0.11.10 - punycode: 1.4.1 - querystring-es3: 0.2.1 - readable-stream: 2.3.7 - stream-browserify: 2.0.2 - stream-http: 2.8.3 - string_decoder: 1.3.0 - timers-browserify: 2.0.12 - tty-browserify: 0.0.0 - url: 0.11.0 - util: 0.11.1 - vm-browserify: 1.1.2 - dev: true - - /node-notifier/8.0.2: - resolution: {integrity: sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==} - requiresBuild: true - dependencies: - growly: 1.3.0 - is-wsl: 2.2.0 - semver: 7.3.7 - shellwords: 0.1.1 - uuid: 8.3.2 - which: 2.0.2 - dev: true - optional: true - - /node-releases/2.0.5: - resolution: {integrity: sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==} - dev: true - - /nopt/5.0.0: - resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} - engines: {node: '>=6'} - hasBin: true - dependencies: - abbrev: 1.1.1 - dev: true - - /normalize-package-data/2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.0 - semver: 5.7.1 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-path/2.1.1: - resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} - engines: {node: '>=0.10.0'} - dependencies: - remove-trailing-separator: 1.1.0 - dev: true - - /normalize-path/3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /npm-run-path/2.0.2: - resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} - engines: {node: '>=4'} - dependencies: - path-key: 2.0.1 - dev: true - - /npm-run-path/4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /npmlog/5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - dev: true - - /nwsapi/2.2.0: - resolution: {integrity: sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==} - dev: true - - /object-assign/4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: true - - /object-copy/0.1.0: - resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} - engines: {node: '>=0.10.0'} - dependencies: - copy-descriptor: 0.1.1 - define-property: 0.2.5 - kind-of: 3.2.2 - dev: true - - /object-visit/1.0.1: - resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: true - - /object.pick/1.3.0: - resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: true - - /once/1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - - /onetime/5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /optionator/0.8.3: - resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.3.0 - prelude-ls: 1.1.2 - type-check: 0.3.2 - word-wrap: 1.2.3 - dev: true - - /optionator/0.9.1: - resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.3 - dev: true - - /os-browserify/0.3.0: - resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} - dev: true - - /p-each-series/2.2.0: - resolution: {integrity: sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==} - engines: {node: '>=8'} - dev: true - - /p-finally/1.0.0: - resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} - engines: {node: '>=4'} - dev: true - - /p-limit/2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit/3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate/3.0.0: - resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} - engines: {node: '>=6'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate/4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-map/4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - dependencies: - aggregate-error: 3.1.0 - dev: true - - /p-try/2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /pako/1.0.11: - resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} - dev: true - - /parallel-transform/1.2.0: - resolution: {integrity: sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==} - dependencies: - cyclist: 1.0.1 - inherits: 2.0.4 - readable-stream: 2.3.7 - dev: true - - /parent-module/1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-asn1/5.1.6: - resolution: {integrity: sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==} - dependencies: - asn1.js: 5.4.1 - browserify-aes: 1.2.0 - evp_bytestokey: 1.0.3 - pbkdf2: 3.1.2 - safe-buffer: 5.2.1 - dev: true - - /parse-json/5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.16.7 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /parse-passwd/1.0.0: - resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} - engines: {node: '>=0.10.0'} - dev: true - - /parse5/6.0.1: - resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - dev: true - - /pascalcase/0.1.1: - resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} - engines: {node: '>=0.10.0'} - dev: true - - /path-browserify/0.0.1: - resolution: {integrity: sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==} - dev: true - - /path-dirname/1.0.2: - resolution: {integrity: sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==} - dev: true - optional: true - - /path-exists/3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - dev: true - - /path-exists/4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute/1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key/2.0.1: - resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} - engines: {node: '>=4'} - dev: true - - /path-key/3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-parse/1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /pbkdf2/3.1.2: - resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} - engines: {node: '>=0.12'} - dependencies: - create-hash: 1.2.0 - create-hmac: 1.1.7 - ripemd160: 2.0.2 - safe-buffer: 5.2.1 - sha.js: 2.4.11 - dev: true - - /picocolors/1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true - - /picomatch/2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /pify/4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: true - - /pirates/4.0.5: - resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==} - engines: {node: '>= 6'} - dev: true - - /pkg-dir/3.0.0: - resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==} - engines: {node: '>=6'} - dependencies: - find-up: 3.0.0 - dev: true - - /pkg-dir/4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - dev: true - - /posix-character-classes/0.1.1: - resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} - engines: {node: '>=0.10.0'} - dev: true - - /prelude-ls/1.1.2: - resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} - engines: {node: '>= 0.8.0'} - dev: true - - /prelude-ls/1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier-linter-helpers/1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} - dependencies: - fast-diff: 1.2.0 - dev: true - - /prettier/2.6.0: - resolution: {integrity: sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true - - /pretty-format/26.6.2: - resolution: {integrity: sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==} - engines: {node: '>= 10'} - dependencies: - '@jest/types': 26.6.2 - ansi-regex: 5.0.1 - ansi-styles: 4.3.0 - react-is: 17.0.2 - dev: true - - /process-nextick-args/2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true - - /process/0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - dev: true - - /progress/2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - dev: true - - /promise-inflight/1.0.1_bluebird@3.7.2: - resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} - peerDependencies: - bluebird: '*' - peerDependenciesMeta: - bluebird: - optional: true - dependencies: - bluebird: 3.7.2 - dev: true - - /prompts/2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - dev: true - - /prr/1.0.1: - resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} - dev: true - - /psl/1.8.0: - resolution: {integrity: sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==} - dev: true - - /public-encrypt/4.0.3: - resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} - dependencies: - bn.js: 4.12.0 - browserify-rsa: 4.1.0 - create-hash: 1.2.0 - parse-asn1: 5.1.6 - randombytes: 2.1.0 - safe-buffer: 5.2.1 - dev: true - - /pump/2.0.1: - resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - dev: true - - /pump/3.0.0: - resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - dev: true - - /pumpify/1.5.1: - resolution: {integrity: sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==} - dependencies: - duplexify: 3.7.1 - inherits: 2.0.4 - pump: 2.0.1 - dev: true - - /punycode/1.3.2: - resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==} - dev: true - - /punycode/1.4.1: - resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} - dev: true - - /punycode/2.1.1: - resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} - engines: {node: '>=6'} - dev: true - - /querystring-es3/0.2.1: - resolution: {integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==} - engines: {node: '>=0.4.x'} - dev: true - - /querystring/0.2.0: - resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==} - engines: {node: '>=0.4.x'} - deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. - dev: true - - /randombytes/2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /randomfill/1.0.4: - resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} - dependencies: - randombytes: 2.1.0 - safe-buffer: 5.2.1 - dev: true - - /react-is/17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - dev: true - - /read-pkg-up/7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true - - /read-pkg/5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - dependencies: - '@types/normalize-package-data': 2.4.1 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true - - /readable-stream/2.3.7: - resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: true - - /readable-stream/3.6.0: - resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - - /readdirp/2.2.1: - resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} - engines: {node: '>=0.10'} - dependencies: - graceful-fs: 4.2.10 - micromatch: 3.1.10 - readable-stream: 2.3.7 - transitivePeerDependencies: - - supports-color - dev: true - optional: true - - /readdirp/3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - optional: true - - /regex-not/1.0.2: - resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 3.0.2 - safe-regex: 1.1.0 - dev: true - - /regexpp/3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} - dev: true - - /remove-trailing-separator/1.1.0: - resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} - dev: true - - /repeat-element/1.1.4: - resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} - engines: {node: '>=0.10.0'} - dev: true - - /repeat-string/1.6.1: - resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} - engines: {node: '>=0.10'} - dev: true - - /require-directory/2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true - - /require-from-string/2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true - - /require-main-filename/2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - dev: true - - /resolve-cwd/2.0.0: - resolution: {integrity: sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg==} - engines: {node: '>=4'} - dependencies: - resolve-from: 3.0.0 - dev: true - - /resolve-cwd/3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - dependencies: - resolve-from: 5.0.0 - dev: true - - /resolve-dir/1.0.1: - resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} - engines: {node: '>=0.10.0'} - dependencies: - expand-tilde: 2.0.2 - global-modules: 1.0.0 - dev: true - - /resolve-from/3.0.0: - resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} - engines: {node: '>=4'} - dev: true - - /resolve-from/4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve-from/5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - - /resolve-url/0.2.1: - resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} - deprecated: https://github.com/lydell/resolve-url#deprecated - dev: true - - /resolve/1.22.0: - resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} - hasBin: true - dependencies: - is-core-module: 2.9.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /ret/0.1.15: - resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} - engines: {node: '>=0.12'} - dev: true - - /rimraf/2.7.1: - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rimraf/3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /ripemd160/2.0.2: - resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} - dependencies: - hash-base: 3.1.0 - inherits: 2.0.4 - dev: true - - /rsvp/4.8.5: - resolution: {integrity: sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==} - engines: {node: 6.* || >= 7.*} - dev: true - - /run-queue/1.0.3: - resolution: {integrity: sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==} - dependencies: - aproba: 1.2.0 - dev: true - - /safe-buffer/5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - - /safe-buffer/5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true - - /safe-regex/1.1.0: - resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} - dependencies: - ret: 0.1.15 - dev: true - - /safer-buffer/2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true - - /sane/4.1.0: - resolution: {integrity: sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==} - engines: {node: 6.* || 8.* || >= 10.*} - deprecated: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added - hasBin: true - dependencies: - '@cnakazawa/watch': 1.0.4 - anymatch: 2.0.0 - capture-exit: 2.0.0 - exec-sh: 0.3.6 - execa: 1.0.0 - fb-watchman: 2.0.1 - micromatch: 3.1.10 - minimist: 1.2.6 - walker: 1.0.8 - transitivePeerDependencies: - - supports-color - dev: true - - /saxes/5.0.1: - resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} - engines: {node: '>=10'} - dependencies: - xmlchars: 2.2.0 - dev: true - - /schema-utils/1.0.0: - resolution: {integrity: sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==} - engines: {node: '>= 4'} - dependencies: - ajv: 6.12.6 - ajv-errors: 1.0.1_ajv@6.12.6 - ajv-keywords: 3.5.2_ajv@6.12.6 - dev: true - - /schema-utils/3.1.1: - resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/json-schema': 7.0.11 - ajv: 6.12.6 - ajv-keywords: 3.5.2_ajv@6.12.6 - dev: true - - /semver/5.7.1: - resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} - hasBin: true - dev: true - - /semver/6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} - hasBin: true - dev: true - - /semver/7.3.7: - resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /serialize-javascript/4.0.0: - resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} - dependencies: - randombytes: 2.1.0 - dev: true - - /serialize-javascript/5.0.1: - resolution: {integrity: sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==} - dependencies: - randombytes: 2.1.0 - dev: true - - /set-blocking/2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true - - /set-value/2.0.1: - resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 2.0.1 - is-extendable: 0.1.1 - is-plain-object: 2.0.4 - split-string: 3.1.0 - dev: true - - /setimmediate/1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - dev: true - - /sha.js/2.4.11: - resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} - hasBin: true - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - - /shebang-command/1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} - dependencies: - shebang-regex: 1.0.0 - dev: true - - /shebang-command/2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex/1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} - dev: true - - /shebang-regex/3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /shellwords/0.1.1: - resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} - dev: true - optional: true - - /signal-exit/3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /simple-concat/1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - dev: true - - /simple-get/3.1.1: - resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} - dependencies: - decompress-response: 4.2.1 - once: 1.4.0 - simple-concat: 1.0.1 - dev: true - - /sisteransi/1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: true - - /slash/3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /slice-ansi/4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: true - - /snapdragon-node/2.1.1: - resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} - engines: {node: '>=0.10.0'} - dependencies: - define-property: 1.0.0 - isobject: 3.0.1 - snapdragon-util: 3.0.1 - dev: true - - /snapdragon-util/3.0.1: - resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: true - - /snapdragon/0.8.2: - resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} - engines: {node: '>=0.10.0'} - dependencies: - base: 0.11.2 - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - map-cache: 0.2.2 - source-map: 0.5.7 - source-map-resolve: 0.5.3 - use: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /snapdragon/0.8.2_supports-color@6.1.0: - resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} - engines: {node: '>=0.10.0'} - dependencies: - base: 0.11.2 - debug: 2.6.9_supports-color@6.1.0 - define-property: 0.2.5 - extend-shallow: 2.0.1 - map-cache: 0.2.2 - source-map: 0.5.7 - source-map-resolve: 0.5.3 - use: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /source-list-map/2.0.1: - resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==} - dev: true - - /source-map-resolve/0.5.3: - resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} - deprecated: See https://github.com/lydell/source-map-resolve#deprecated - dependencies: - atob: 2.1.2 - decode-uri-component: 0.2.0 - resolve-url: 0.2.1 - source-map-url: 0.4.1 - urix: 0.1.0 - dev: true - - /source-map-support/0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map-url/0.4.1: - resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} - deprecated: See https://github.com/lydell/source-map-url#deprecated - dev: true - - /source-map/0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map/0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map/0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - dev: true - - /spdx-correct/3.1.1: - resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.11 - dev: true - - /spdx-exceptions/2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - dev: true - - /spdx-expression-parse/3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.11 - dev: true - - /spdx-license-ids/3.0.11: - resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==} - dev: true - - /split-string/3.1.0: - resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 3.0.2 - dev: true - - /sprintf-js/1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true - - /ssri/6.0.2: - resolution: {integrity: sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==} - dependencies: - figgy-pudding: 3.5.2 - dev: true - - /ssri/8.0.1: - resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.1.6 - dev: true - - /stack-utils/2.0.5: - resolution: {integrity: sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==} - engines: {node: '>=10'} - dependencies: - escape-string-regexp: 2.0.0 - dev: true - - /static-extend/0.1.2: - resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} - engines: {node: '>=0.10.0'} - dependencies: - define-property: 0.2.5 - object-copy: 0.1.0 - dev: true - - /stream-browserify/2.0.2: - resolution: {integrity: sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==} - dependencies: - inherits: 2.0.4 - readable-stream: 2.3.7 - dev: true - - /stream-each/1.2.3: - resolution: {integrity: sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==} - dependencies: - end-of-stream: 1.4.4 - stream-shift: 1.0.1 - dev: true - - /stream-http/2.8.3: - resolution: {integrity: sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==} - dependencies: - builtin-status-codes: 3.0.0 - inherits: 2.0.4 - readable-stream: 2.3.7 - to-arraybuffer: 1.0.1 - xtend: 4.0.2 - dev: true - - /stream-shift/1.0.1: - resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} - dev: true - - /string-length/4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - dev: true - - /string-width/3.1.0: - resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==} - engines: {node: '>=6'} - dependencies: - emoji-regex: 7.0.3 - is-fullwidth-code-point: 2.0.0 - strip-ansi: 5.2.0 - dev: true - - /string-width/4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true - - /string_decoder/1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - dev: true - - /string_decoder/1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /strip-ansi/5.2.0: - resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} - engines: {node: '>=6'} - dependencies: - ansi-regex: 4.1.1 - dev: true - - /strip-ansi/6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-bom/4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - dev: true - - /strip-eof/1.0.0: - resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} - engines: {node: '>=0.10.0'} - dev: true - - /strip-final-newline/2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-json-comments/3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /supports-color/5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color/6.1.0: - resolution: {integrity: sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==} - engines: {node: '>=6'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color/7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-hyperlinks/2.2.0: - resolution: {integrity: sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - supports-color: 7.2.0 - dev: true - - /supports-preserve-symlinks-flag/1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /symbol-tree/3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - dev: true - - /table/6.8.0: - resolution: {integrity: sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==} - engines: {node: '>=10.0.0'} - dependencies: - ajv: 8.11.0 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /tapable/1.1.3: - resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==} - engines: {node: '>=6'} - dev: true - - /tar/6.1.11: - resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} - engines: {node: '>= 10'} - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 3.1.6 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - dev: true - - /terminal-link/2.1.1: - resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} - engines: {node: '>=8'} - dependencies: - ansi-escapes: 4.3.2 - supports-hyperlinks: 2.2.0 - dev: true - - /terser-webpack-plugin/1.4.5_webpack@4.46.0: - resolution: {integrity: sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==} - engines: {node: '>= 6.9.0'} - peerDependencies: - webpack: ^4.0.0 - dependencies: - cacache: 12.0.4 - find-cache-dir: 2.1.0 - is-wsl: 1.1.0 - schema-utils: 1.0.0 - serialize-javascript: 4.0.0 - source-map: 0.6.1 - terser: 4.8.0 - webpack: 4.46.0_webpack-cli@3.3.12 - webpack-sources: 1.4.3 - worker-farm: 1.7.0 - dev: true - - /terser-webpack-plugin/4.2.3_webpack@4.46.0: - resolution: {integrity: sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==} - engines: {node: '>= 10.13.0'} - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - dependencies: - cacache: 15.3.0 - find-cache-dir: 3.3.2 - jest-worker: 26.6.2 - p-limit: 3.1.0 - schema-utils: 3.1.1 - serialize-javascript: 5.0.1 - source-map: 0.6.1 - terser: 5.14.0 - webpack: 4.46.0_webpack-cli@3.3.12 - webpack-sources: 1.4.3 - transitivePeerDependencies: - - bluebird - dev: true - - /terser/4.8.0: - resolution: {integrity: sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - acorn: 8.7.1 - commander: 2.20.3 - source-map: 0.6.1 - source-map-support: 0.5.21 - dev: true - - /terser/5.14.0: - resolution: {integrity: sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==} - engines: {node: '>=10'} - hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.2 - acorn: 8.7.1 - commander: 2.20.3 - source-map-support: 0.5.21 - dev: true - - /test-exclude/6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - dev: true - - /text-table/0.2.0: - resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=} - dev: true - - /throat/5.0.0: - resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==} - dev: true - - /through2/2.0.5: - resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} - dependencies: - readable-stream: 2.3.7 - xtend: 4.0.2 - dev: true - - /timers-browserify/2.0.12: - resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} - engines: {node: '>=0.6.0'} - dependencies: - setimmediate: 1.0.5 - dev: true - - /tmpl/1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - dev: true - - /to-arraybuffer/1.0.1: - resolution: {integrity: sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=} - dev: true - - /to-fast-properties/2.0.0: - resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} - engines: {node: '>=4'} - dev: true - - /to-object-path/0.3.0: - resolution: {integrity: sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: true - - /to-regex-range/2.1.1: - resolution: {integrity: sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=} - engines: {node: '>=0.10.0'} - dependencies: - is-number: 3.0.0 - repeat-string: 1.6.1 - dev: true - - /to-regex-range/5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /to-regex/3.0.2: - resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} - engines: {node: '>=0.10.0'} - dependencies: - define-property: 2.0.2 - extend-shallow: 3.0.2 - regex-not: 1.0.2 - safe-regex: 1.1.0 - dev: true - - /tough-cookie/4.0.0: - resolution: {integrity: sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==} - engines: {node: '>=6'} - dependencies: - psl: 1.8.0 - punycode: 2.1.1 - universalify: 0.1.2 - dev: true - - /tr46/0.0.3: - resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=} - dev: true - - /tr46/2.1.0: - resolution: {integrity: sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==} - engines: {node: '>=8'} - dependencies: - punycode: 2.1.1 - dev: true - - /ts-jest/26.5.6_eee4nuuc45mdmx5rmbx7hzjjtq: - resolution: {integrity: sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==} - engines: {node: '>= 10'} - hasBin: true - peerDependencies: - jest: '>=26 <27' - typescript: '>=3.8 <5.0' - dependencies: - bs-logger: 0.2.6 - buffer-from: 1.1.2 - fast-json-stable-stringify: 2.1.0 - jest: 26.6.3_canvas@2.9.1 - jest-util: 26.6.2 - json5: 2.2.1 - lodash: 4.17.21 - make-error: 1.3.6 - mkdirp: 1.0.4 - semver: 7.3.7 - typescript: 3.9.10 - yargs-parser: 20.2.9 - dev: true - - /ts-loader/8.4.0_ezrl6vhczkqqw35uifasf5iyga: - resolution: {integrity: sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==} - engines: {node: '>=10.0.0'} - peerDependencies: - typescript: '*' - webpack: '*' - dependencies: - chalk: 4.1.2 - enhanced-resolve: 4.5.0 - loader-utils: 2.0.2 - micromatch: 4.0.5 - semver: 7.3.7 - typescript: 3.9.10 - webpack: 4.46.0_webpack-cli@3.3.12 - dev: true - - /tslib/1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - - /tsutils/3.21.0_typescript@3.9.10: - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 3.9.10 - dev: true - - /tty-browserify/0.0.0: - resolution: {integrity: sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=} - dev: true - - /type-check/0.3.2: - resolution: {integrity: sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - dev: true - - /type-check/0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-detect/4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - dev: true - - /type-fest/0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /type-fest/0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true - - /type-fest/0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true - - /type-fest/0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true - - /typedarray-to-buffer/3.1.5: - resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - dependencies: - is-typedarray: 1.0.0 - dev: true - - /typedarray/0.0.6: - resolution: {integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=} - dev: true - - /typescript/3.9.10: - resolution: {integrity: sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==} - engines: {node: '>=4.2.0'} - hasBin: true - dev: true - - /union-value/1.0.1: - resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} - engines: {node: '>=0.10.0'} - dependencies: - arr-union: 3.1.0 - get-value: 2.0.6 - is-extendable: 0.1.1 - set-value: 2.0.1 - dev: true - - /unique-filename/1.1.1: - resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==} - dependencies: - unique-slug: 2.0.2 - dev: true - - /unique-slug/2.0.2: - resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==} - dependencies: - imurmurhash: 0.1.4 - dev: true - - /universalify/0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - dev: true - - /unset-value/1.0.0: - resolution: {integrity: sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=} - engines: {node: '>=0.10.0'} - dependencies: - has-value: 0.3.1 - isobject: 3.0.1 - dev: true - - /upath/1.2.0: - resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} - engines: {node: '>=4'} - dev: true - optional: true - - /uri-js/4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.1.1 - dev: true - - /urix/0.1.0: - resolution: {integrity: sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=} - deprecated: Please see https://github.com/lydell/urix#deprecated - dev: true - - /url/0.11.0: - resolution: {integrity: sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=} - dependencies: - punycode: 1.3.2 - querystring: 0.2.0 - dev: true - - /use/3.1.1: - resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} - engines: {node: '>=0.10.0'} - dev: true - - /util-deprecate/1.0.2: - resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} - dev: true - - /util/0.10.3: - resolution: {integrity: sha1-evsa/lCAUkZInj23/g7TeTNqwPk=} - dependencies: - inherits: 2.0.1 - dev: true - - /util/0.11.1: - resolution: {integrity: sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==} - dependencies: - inherits: 2.0.3 - dev: true - - /uuid/8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: true - optional: true - - /v8-compile-cache/2.3.0: - resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} - dev: true - - /v8-to-istanbul/7.1.2: - resolution: {integrity: sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==} - engines: {node: '>=10.10.0'} - dependencies: - '@types/istanbul-lib-coverage': 2.0.4 - convert-source-map: 1.8.0 - source-map: 0.7.4 - dev: true - - /validate-npm-package-license/3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.1.1 - spdx-expression-parse: 3.0.1 - dev: true - - /vm-browserify/1.1.2: - resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} - dev: true - - /w3c-hr-time/1.0.2: - resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} - dependencies: - browser-process-hrtime: 1.0.0 - dev: true - - /w3c-xmlserializer/2.0.0: - resolution: {integrity: sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==} - engines: {node: '>=10'} - dependencies: - xml-name-validator: 3.0.0 - dev: true - - /walker/1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - dependencies: - makeerror: 1.0.12 - dev: true - - /watchpack-chokidar2/2.0.1: - resolution: {integrity: sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==} - requiresBuild: true - dependencies: - chokidar: 2.1.8 - transitivePeerDependencies: - - supports-color - dev: true - optional: true - - /watchpack/1.7.5: - resolution: {integrity: sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==} - dependencies: - graceful-fs: 4.2.10 - neo-async: 2.6.2 - optionalDependencies: - chokidar: 3.5.3 - watchpack-chokidar2: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /webidl-conversions/3.0.1: - resolution: {integrity: sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=} - dev: true - - /webidl-conversions/5.0.0: - resolution: {integrity: sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==} - engines: {node: '>=8'} - dev: true - - /webidl-conversions/6.1.0: - resolution: {integrity: sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==} - engines: {node: '>=10.4'} - dev: true - - /webpack-cli/3.3.12_webpack@4.46.0: - resolution: {integrity: sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==} - engines: {node: '>=6.11.5'} - hasBin: true - peerDependencies: - webpack: 4.x.x - dependencies: - chalk: 2.4.2 - cross-spawn: 6.0.5 - enhanced-resolve: 4.5.0 - findup-sync: 3.0.0_supports-color@6.1.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.3.0 - webpack: 4.46.0_webpack-cli@3.3.12 - yargs: 13.3.2 - dev: true - - /webpack-sources/1.4.3: - resolution: {integrity: sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==} - dependencies: - source-list-map: 2.0.1 - source-map: 0.6.1 - dev: true - - /webpack/4.46.0_webpack-cli@3.3.12: - resolution: {integrity: sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==} - engines: {node: '>=6.11.5'} - hasBin: true - peerDependencies: - webpack-cli: '*' - webpack-command: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - webpack-command: - optional: true - dependencies: - '@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.2 - ajv: 6.12.6 - ajv-keywords: 3.5.2_ajv@6.12.6 - chrome-trace-event: 1.0.3 - enhanced-resolve: 4.5.0 - eslint-scope: 4.0.3 - json-parse-better-errors: 1.0.2 - loader-runner: 2.4.0 - loader-utils: 1.4.0 - memory-fs: 0.4.1 - micromatch: 3.1.10 - mkdirp: 0.5.6 - neo-async: 2.6.2 - node-libs-browser: 2.2.1 - schema-utils: 1.0.0 - tapable: 1.1.3 - terser-webpack-plugin: 1.4.5_webpack@4.46.0 - watchpack: 1.7.5 - webpack-cli: 3.3.12_webpack@4.46.0 - webpack-sources: 1.4.3 - transitivePeerDependencies: - - supports-color - dev: true - - /whatwg-encoding/1.0.5: - resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} - dependencies: - iconv-lite: 0.4.24 - dev: true - - /whatwg-mimetype/2.3.0: - resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} - dev: true - - /whatwg-url/5.0.0: - resolution: {integrity: sha1-lmRU6HZUYuN2RNNib2dCzotwll0=} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - dev: true - - /whatwg-url/8.7.0: - resolution: {integrity: sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==} - engines: {node: '>=10'} - dependencies: - lodash: 4.17.21 - tr46: 2.1.0 - webidl-conversions: 6.1.0 - dev: true - - /which-module/2.0.0: - resolution: {integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=} - dev: true - - /which/1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which/2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /wide-align/1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - dependencies: - string-width: 4.2.3 - dev: true - - /word-wrap/1.2.3: - resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} - engines: {node: '>=0.10.0'} - dev: true - - /worker-farm/1.7.0: - resolution: {integrity: sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==} - dependencies: - errno: 0.1.8 - dev: true - - /wrap-ansi/5.1.0: - resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==} - engines: {node: '>=6'} - dependencies: - ansi-styles: 3.2.1 - string-width: 3.1.0 - strip-ansi: 5.2.0 - dev: true - - /wrap-ansi/6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrappy/1.0.2: - resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} - dev: true - - /write-file-atomic/3.0.3: - resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} - dependencies: - imurmurhash: 0.1.4 - is-typedarray: 1.0.0 - signal-exit: 3.0.7 - typedarray-to-buffer: 3.1.5 - dev: true - - /ws/7.5.8: - resolution: {integrity: sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /xml-name-validator/3.0.0: - resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} - dev: true - - /xmlchars/2.2.0: - resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - dev: true - - /xtend/4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} - dev: true - - /y18n/4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - dev: true - - /yallist/3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yallist/4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - - /yargs-parser/13.1.2: - resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==} - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - dev: true - - /yargs-parser/18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - dev: true - - /yargs-parser/20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - dev: true - - /yargs/13.3.2: - resolution: {integrity: sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==} - dependencies: - cliui: 5.0.0 - find-up: 3.0.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 3.1.0 - which-module: 2.0.0 - y18n: 4.0.3 - yargs-parser: 13.1.2 - dev: true - - /yargs/15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} - dependencies: - cliui: 6.0.0 - decamelize: 1.2.0 - find-up: 4.1.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 4.2.3 - which-module: 2.0.0 - y18n: 4.0.3 - yargs-parser: 18.1.3 - dev: true - - /yocto-queue/0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true From 40043806cd8e6042b1261b596d743289bae38ce5 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 9 Jun 2022 19:44:24 -0400 Subject: [PATCH 022/108] Add tests for addDropzones --- __tests__/__snapshots__/editable.test.ts.snap | 449 ++++++++++++++++++ __tests__/editable.test.ts | 43 +- 2 files changed, 491 insertions(+), 1 deletion(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index b6ae0cf6..634d04b7 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -56,6 +56,455 @@ exports[`Testing addDropzoneEvents add 2 events 1`] = ` </div> `; +exports[`Testing addDropzones verify dropzones 1`] = ` +<div> + <svg + class="qviz" + height="180" + style="max-width: fit-content;" + width="260" + > + <style> + + line, + circle, + rect { + stroke: #000000; + stroke-width: 1; + } + text { + fill: #000000; + dominant-baseline: middle; + text-anchor: middle; + font-family: Arial; + } + .control-dot { + fill: #000000; + } + .oplus line, .oplus circle { + fill: #FFFFFF; + stroke-width: 2; + } + .gate-unitary { + fill: #D9F1FA; + } + .gate-measure { + fill: #FFDE86; + } + rect.gate-swap { + fill: transparent; + stroke: transparent; + } + .arc-measure { + stroke: #000000; + fill: none; + stroke-width: 1; + } + .register-classical { + stroke-width: 0.5; + } + + .hidden { + display: none; + } + .classically-controlled-unknown { + opacity: 0.25; + } + + + .classically-controlled-one .classical-container, + .classically-controlled-one .classical-line { + stroke: #4059BD; + stroke-width: 1.3; + fill: #4059BD; + fill-opacity: 0.1; + } + .classically-controlled-zero .classical-container, + .classically-controlled-zero .classical-line { + stroke: #C40000; + stroke-width: 1.3; + fill: #C40000; + fill-opacity: 0.1; + } + + .classically-controlled-btn { + cursor: pointer; + } + .classically-controlled-unknown .classically-controlled-btn { + fill: #E5E5E5; + } + .classically-controlled-one .classically-controlled-btn { + fill: #4059BD; + } + .classically-controlled-zero .classically-controlled-btn { + fill: #C40000; + } + + .classically-controlled-btn text { + dominant-baseline: middle; + text-anchor: middle; + stroke: none; + font-family: Arial; + } + .classically-controlled-unknown .classically-controlled-btn text { + fill: #000000; + } + .classically-controlled-one .classically-controlled-btn text { + fill: #FFFFFF; + } + .classically-controlled-zero .classically-controlled-btn text { + fill: #FFFFFF; + } + + .qviz .gate-collapse, + .qviz .gate-expand { + opacity: 0; + transition: opacity 1s; + } + + .qviz:hover .gate-collapse, + .qviz:hover .gate-expand { + visibility: visible; + opacity: 0.2; + transition: visibility 1s; + transition: opacity 1s; + } + + .gate-expand, .gate-collapse { + cursor: pointer; + } + + .gate-collapse circle, + .gate-expand circle { + fill: white; + stroke-width: 2px; + stroke: black; + } + .gate-collapse path, + .gate-expand path { + stroke-width: 4px; + stroke: black; + } + + .gate:hover > .gate-collapse, + .gate:hover > .gate-expand { + visibility: visible; + opacity: 1; + transition: opacity 1s; + }.dropzone { + fill: transparent; + stroke: transparent; + } + .dropzone:hover{ + fill: red; + opacity: 25%; + } + text { + user-select: none; + } + .copying { + cursor: copy; + } + .moving { + cursor: move; + } + .detail-panel { + display: flex; + align-content: center; + gap: 12px; + } + </style> + <g> + <text + dominant-baseline="middle" + font-size="16" + text-anchor="start" + x="20" + y="40" + > + |0⟩ + </text> + <text + dominant-baseline="middle" + font-size="16" + text-anchor="start" + x="20" + y="100" + > + |0⟩ + </text> + </g> + <g> + <g> + <line + x1="40" + x2="260" + y1="40" + y2="40" + /> + <text + dominant-baseline="hanging" + font-size="75%" + text-anchor="start" + x="40" + y="24" + > + q0 + </text> + </g> + <g> + <line + x1="40" + x2="260" + y1="100" + y2="100" + /> + <text + dominant-baseline="hanging" + font-size="75%" + text-anchor="start" + x="40" + y="84" + > + q1 + </text> + </g> + <g> + <line + class="register-classical" + x1="221" + x2="221" + y1="100" + y2="139" + /> + <line + class="register-classical" + x1="219" + x2="219" + y1="100" + y2="141" + /> + <line + class="register-classical" + x1="221" + x2="260" + y1="139" + y2="139" + /> + <line + class="register-classical" + x1="219" + x2="260" + y1="141" + y2="141" + /> + </g> + </g> + <g> + <g + class="gate" + data-id="0" + data-zoom-in="false" + data-zoom-out="false" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="80" + y="20" + /> + <text + font-size="14" + x="100" + y="40" + > + H + </text> + </g> + </g> + <rect + class="dropzone" + data-dropzone-position="left" + data-id="0" + height="0" + width="10" + x="-10" + y="0" + /> + <rect + class="dropzone" + data-dropzone-position="right" + data-id="0" + height="0" + width="10" + x="0" + y="0" + /> + <rect + class="dropzone" + data-dropzone-position="left" + data-id="0" + height="0" + width="10" + x="-10" + y="0" + /> + <rect + class="dropzone" + data-dropzone-position="right" + data-id="0" + height="0" + width="10" + x="0" + y="0" + /> + </g> + <g + class="gate" + data-id="1" + data-zoom-in="false" + data-zoom-out="false" + > + <line + x1="160" + x2="160" + y1="40" + y2="100" + /> + <circle + class="control-dot" + cx="160" + cy="40" + r="5" + /> + <g + class="oplus" + > + <circle + cx="160" + cy="100" + r="15" + /> + <line + x1="160" + x2="160" + y1="85" + y2="115" + /> + <line + x1="145" + x2="175" + y1="100" + y2="100" + /> + </g> + <rect + class="dropzone" + data-dropzone-position="left" + data-id="1" + height="0" + width="10" + x="-10" + y="0" + /> + <rect + class="dropzone" + data-dropzone-position="right" + data-id="1" + height="0" + width="10" + x="0" + y="0" + /> + <rect + class="dropzone" + data-dropzone-position="left" + data-id="1" + height="0" + width="10" + x="-10" + y="0" + /> + <rect + class="dropzone" + data-dropzone-position="right" + data-id="1" + height="0" + width="10" + x="0" + y="0" + /> + </g> + <g + class="gate" + data-id="2" + data-zoom-in="false" + data-zoom-out="false" + > + <g> + <rect + class="gate-measure" + height="40" + width="40" + x="200" + y="80" + /> + <path + class="arc-measure" + d="M 235 102 A 15 12 0 0 0 205 102" + /> + <line + x1="220" + x2="232" + y1="108" + y2="88" + /> + </g> + <rect + class="dropzone" + data-dropzone-position="left" + data-id="2" + height="0" + width="10" + x="-10" + y="0" + /> + <rect + class="dropzone" + data-dropzone-position="right" + data-id="2" + height="0" + width="10" + x="0" + y="0" + /> + <rect + class="dropzone" + data-dropzone-position="left" + data-id="2" + height="0" + width="10" + x="-10" + y="0" + /> + <rect + class="dropzone" + data-dropzone-position="right" + data-id="2" + height="0" + width="10" + x="0" + y="0" + /> + </g> + </g> + </svg> +</div> +`; + exports[`Testing addMouseEvents verify mouse events 1`] = ` <div> <svg diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 156439c7..091177d3 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -7,7 +7,7 @@ import { Sqore } from '../src/sqore'; const { // addEditable addCustomStyles, - // addDropzones + addDropzones, addDocumentEvents, addDropzoneEvents, addMouseEvents, @@ -1294,3 +1294,44 @@ describe('Testing getRenderFn', () => { expect(console.log).toHaveBeenCalledWith('callbackFn is triggered'); }); }); + +describe('Testing addDropzones', () => { + test('verify dropzones', () => { + Object.defineProperty(window.SVGElement.prototype, 'getBBox', { + writable: true, + value: () => ({ + x: 0, + y: 0, + width: 0, + height: 0, + }), + }); + const container = document.createElement('div'); + const circuit: Circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + draw(circuit, container, STYLES['default'], 0, true); + const svgElem = container.querySelector('svg'); + if (svgElem != null) svgElem.removeAttribute('id'); + addDropzones(container); + expect(container).toMatchSnapshot(); + }); +}); From 5620b601696210b185b1bcfe1b5cf699a35eff21 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 13 Jun 2022 11:58:23 -0400 Subject: [PATCH 023/108] Integrate editable styles in styles.ts --- __tests__/__snapshots__/editable.test.ts.snap | 102 ++++++++++++------ __tests__/editable.test.ts | 13 --- src/editable.ts | 30 ------ src/styles.ts | 48 ++++++++- 4 files changed, 114 insertions(+), 79 deletions(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 634d04b7..1d834e89 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -1,40 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Testing addCustomStyles verify css 1`] = ` -<div> - <style /> -</div> -`; - -exports[`Testing addCustomStyles verify css 2`] = ` -<div> - <style> - .dropzone { - fill: transparent; - stroke: transparent; - } - .dropzone:hover{ - fill: red; - opacity: 25%; - } - text { - user-select: none; - } - .copying { - cursor: copy; - } - .moving { - cursor: move; - } - .detail-panel { - display: flex; - align-content: center; - gap: 12px; - } - </style> -</div> -`; - exports[`Testing addDocumentEvents verify document events 1`] = `<div />`; exports[`Testing addDocumentEvents verify document events 2`] = `<div />`; @@ -191,6 +156,29 @@ exports[`Testing addDropzones verify dropzones 1`] = ` visibility: visible; opacity: 1; transition: opacity 1s; + } + + .dropzone { + fill: transparent; + stroke: transparent; + } + .dropzone:hover{ + fill: red; + opacity: 25%; + } + text { + user-select: none; + } + .copying { + cursor: copy; + } + .moving { + cursor: move; + } + .detail-panel { + display: flex; + align-content: center; + gap: 12px; }.dropzone { fill: transparent; stroke: transparent; @@ -641,6 +629,50 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` opacity: 1; transition: opacity 1s; } + + .dropzone { + fill: transparent; + stroke: transparent; + } + .dropzone:hover{ + fill: red; + opacity: 25%; + } + text { + user-select: none; + } + .copying { + cursor: copy; + } + .moving { + cursor: move; + } + .detail-panel { + display: flex; + align-content: center; + gap: 12px; + }.dropzone { + fill: transparent; + stroke: transparent; + } + .dropzone:hover{ + fill: red; + opacity: 25%; + } + text { + user-select: none; + } + .copying { + cursor: copy; + } + .moving { + cursor: move; + } + .detail-panel { + display: flex; + align-content: center; + gap: 12px; + } </style> <g> <text diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 091177d3..3729db60 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -6,7 +6,6 @@ import { Sqore } from '../src/sqore'; const { // addEditable - addCustomStyles, addDropzones, addDocumentEvents, addDropzoneEvents, @@ -768,18 +767,6 @@ describe('Testing getGate', () => { }); }); -describe('Testing addCustomStyles', () => { - test('verify css', () => { - const container = document.createElement('div'); - const style = document.createElement('style'); - container.append(style); - expect(container).toMatchSnapshot(); - addCustomStyles(container); - expect(container).toMatchSnapshot(); - }); -}); - -// Untestable describe('Testing addDocumentEvents', () => { test('verify document events', () => { const container = document.createElement('div'); diff --git a/src/editable.ts b/src/editable.ts index c78b28c2..55fd9fe8 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -35,7 +35,6 @@ const addEditable = (container: HTMLElement, sqore: Sqore, callbackFn?: () => vo wires: getWireElemsY(container), renderFn: getRenderFn(container, sqore, callbackFn), }; - addCustomStyles(container); addDropzones(container); addDocumentEvents(container); addDropzoneEvents(context); @@ -44,34 +43,6 @@ const addEditable = (container: HTMLElement, sqore: Sqore, callbackFn?: () => vo // Commands -const addCustomStyles = (container: HTMLElement): void => { - const style = container.querySelector<HTMLStyleElement>('style'); - if (style) { - style.innerHTML += `.dropzone { - fill: transparent; - stroke: transparent; - } - .dropzone:hover{ - fill: red; - opacity: 25%; - } - text { - user-select: none; - } - .copying { - cursor: copy; - } - .moving { - cursor: move; - } - .detail-panel { - display: flex; - align-content: center; - gap: 12px; - }`; - } -}; - const addDropzones = (container: HTMLElement): void => { const gateElems = getGateElems(container); gateElems.forEach((gateElem) => { @@ -326,7 +297,6 @@ const cursorCopy = (container: HTMLElement, value: boolean): void => { const exportedForTesting = { // addEditable - addCustomStyles, addDropzones, addDocumentEvents, addDropzoneEvents, diff --git a/src/styles.ts b/src/styles.ts index 491d563e..d14434c9 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -95,7 +95,8 @@ export const style = (customStyle: StyleConfig = {}): string => { return `${_defaultGates(styleConfig)} ${_classicallyControlledGates(styleConfig)} - ${_expandCollapse}`; + ${_expandCollapse} + ${_editable}`; }; const _defaultGates = (styleConfig: StyleConfig): string => ` @@ -234,3 +235,48 @@ const _expandCollapse = ` opacity: 1; transition: opacity 1s; }`; + +const _editable = ` + .dropzone { + fill: transparent; + stroke: transparent; + } + .dropzone:hover{ + fill: red; + opacity: 25%; + } + text { + user-select: none; + } + .copying { + cursor: copy; + } + .moving { + cursor: move; + } + .detail-panel { + display: flex; + align-content: center; + gap: 12px; + }.dropzone { + fill: transparent; + stroke: transparent; + } + .dropzone:hover{ + fill: red; + opacity: 25%; + } + text { + user-select: none; + } + .copying { + cursor: copy; + } + .moving { + cursor: move; + } + .detail-panel { + display: flex; + align-content: center; + gap: 12px; + }`; From 2c6be0656069dec9f644fc8d2233ef0b7ae2c126 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 13 Jun 2022 12:17:32 -0400 Subject: [PATCH 024/108] Display grab cursor style when hover over gates --- __tests__/__snapshots__/editable.test.ts.snap | 14 ++++++++++++++ src/styles.ts | 9 ++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 1d834e89..d8e2ae43 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -201,6 +201,13 @@ exports[`Testing addDropzones verify dropzones 1`] = ` align-content: center; gap: 12px; } + g.gate:not([data-expanded=true]) rect { + cursor: grab; + } + g.gate:not([data-expanded=true]) circle { + cursor: grab; + } + </style> <g> <text @@ -673,6 +680,13 @@ exports[`Testing addMouseEvents verify mouse events 1`] = ` align-content: center; gap: 12px; } + g.gate:not([data-expanded=true]) rect { + cursor: grab; + } + g.gate:not([data-expanded=true]) circle { + cursor: grab; + } + </style> <g> <text diff --git a/src/styles.ts b/src/styles.ts index d14434c9..10327841 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -279,4 +279,11 @@ const _editable = ` display: flex; align-content: center; gap: 12px; - }`; + } + g.gate:not([data-expanded=true]) rect { + cursor: grab; + } + g.gate:not([data-expanded=true]) circle { + cursor: grab; + } + `; From 009a1d772caad6cec06abe52e11dfe11da501c90 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 13 Jun 2022 12:33:07 -0400 Subject: [PATCH 025/108] Rename callbackFn to onCircuitChange --- __tests__/editable.test.ts | 8 ++++---- example/script.js | 2 +- src/editable.ts | 16 ++++++++-------- src/index.ts | 6 +++--- src/sqore.ts | 26 +++++++++++++------------- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 3729db60..dc5651cf 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -1240,7 +1240,7 @@ describe('Testing addMouseEvents', () => { }); describe('Testing getRenderFn', () => { - test('check console.log displaying "callbackFn is triggered"', () => { + test('check console.log displaying "onCircuitChange is triggered"', () => { Object.defineProperty(window.SVGElement.prototype, 'getBBox', { writable: true, value: () => ({ @@ -1273,12 +1273,12 @@ describe('Testing getRenderFn', () => { ], }; const sqore = new Sqore(circuit, STYLES['default']); - const callbackFn = () => console.log('callbackFn is triggered'); - const renderFn = getRenderFn(container, sqore, callbackFn); + const onCircuitChange = () => console.log('onCircuitChange is triggered'); + const renderFn = getRenderFn(container, sqore, onCircuitChange); jest.spyOn(console, 'log'); renderFn(); - expect(console.log).toHaveBeenCalledWith('callbackFn is triggered'); + expect(console.log).toHaveBeenCalledWith('onCircuitChange is triggered'); }); }); diff --git a/example/script.js b/example/script.js index ef3ef492..5c1aa464 100644 --- a/example/script.js +++ b/example/script.js @@ -12,7 +12,7 @@ if (typeof qviz != 'undefined') { const sampleDiv = document.getElementById('sample'); if (sampleDiv != null) { - qviz.draw(sample, sampleDiv, qviz.STYLES['Default'], 0, true, () => console.log('callbackFn')); + qviz.draw(sample, sampleDiv, qviz.STYLES['Default'], 0, true, () => console.log('onCircuitChange')); } const teleportDiv = document.getElementById('teleport'); diff --git a/src/editable.ts b/src/editable.ts index 55fd9fe8..e0407fb6 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -22,18 +22,18 @@ let _sourceTarget: SVGElement | null; /** * Add editable elements and events. * - * @param container HTML element for rendering visualization into. - * @param sqore Sqore object - * @param callbackFn User-provided callback function triggered when circuit is changed + * @param container HTML element for rendering visualization into. + * @param sqore Sqore object + * @param onCircuitChange User-provided callback function triggered when circuit is changed * */ -const addEditable = (container: HTMLElement, sqore: Sqore, callbackFn?: () => void): void => { +const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: () => void): void => { const context: Context = { container: container, operations: sqore.circuit.operations, wires: getWireElemsY(container), - renderFn: getRenderFn(container, sqore, callbackFn), + renderFn: getRenderFn(container, sqore, onCircuitChange), }; addDropzones(container); addDocumentEvents(container); @@ -220,10 +220,10 @@ const getGate = (dataId: string, operations: Operation[]): Operation => { }; // Utilities -const getRenderFn = (container: HTMLElement, sqore: Sqore, callbackFn?: () => void): (() => void) => { +const getRenderFn = (container: HTMLElement, sqore: Sqore, onCircuitChange?: () => void): (() => void) => { return () => { - sqore.draw(container, 0, true, callbackFn); - if (callbackFn) callbackFn(); + sqore.draw(container, 0, true, onCircuitChange); + if (onCircuitChange) onCircuitChange(); }; }; diff --git a/src/index.ts b/src/index.ts index 49973b3f..5e5d770f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,7 @@ import { StyleConfig } from './styles'; * @param style Custom visualization style. * @param renderDepth Initial layer depth at which to render gates. * @param isEditable Optional value enabling/disabling editable feature - * @param callbackFn Optional function to trigger when changing elements in circuit + * @param onCircuitChange Optional function to trigger when changing elements in circuit */ export const draw = ( circuit: Circuit, @@ -21,11 +21,11 @@ export const draw = ( style: StyleConfig | string = {}, renderDepth = 0, isEditable?: boolean, - callbackFn?: () => void, + onCircuitChange?: () => void, ): void => { const sqore = new Sqore(circuit, style); - sqore.draw(container, renderDepth, isEditable, callbackFn); + sqore.draw(container, renderDepth, isEditable, onCircuitChange); }; export { STYLES } from './styles'; diff --git a/src/sqore.ts b/src/sqore.ts index 990ea3dc..878eef24 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -57,9 +57,9 @@ export class Sqore { * @param container HTML element for rendering visualization into. * @param renderDepth Initial layer depth at which to render gates. * @param isEditable Optional value enabling/disabling editable feature - * @param callbackFn Optional function to trigger when changing elements in circuit + * @param onCircuitChange Optional function to trigger when changing elements in circuit */ - draw(container: HTMLElement, renderDepth = 0, isEditable?: boolean, callbackFn?: () => void): void { + draw(container: HTMLElement, renderDepth = 0, isEditable?: boolean, onCircuitChange?: () => void): void { // Inject into container if (container == null) throw new Error(`Container not provided.`); @@ -81,7 +81,7 @@ export class Sqore { const id: string = circuit.operations[0].dataAttributes['id']; this.expandOperation(circuit.operations, id); } - this.renderCircuit(container, circuit, isEditable, callbackFn); + this.renderCircuit(container, circuit, isEditable, onCircuitChange); } /** @@ -109,23 +109,23 @@ export class Sqore { * @param container HTML element for rendering visualization into. * @param circuit Circuit object to be rendered. * @param isEditable Optional value enabling/disabling editable feature - * @param callbackFn Optional function to trigger when changing elements in circuit + * @param onCircuitChange Optional function to trigger when changing elements in circuit */ private renderCircuit( container: HTMLElement, circuit: Circuit, isEditable?: boolean, - callbackFn?: () => void, + onCircuitChange?: () => void, ): void { // Create visualization components const composedSqore: ComposedSqore = this.compose(circuit); const svg: SVGElement = this.generateSvg(composedSqore); container.innerHTML = ''; container.appendChild(svg); - this.addGateClickHandlers(container, circuit, isEditable, callbackFn); + this.addGateClickHandlers(container, circuit, isEditable, onCircuitChange); if (isEditable) { - addEditable(container, this, callbackFn); + addEditable(container, this, onCircuitChange); } } @@ -243,17 +243,17 @@ export class Sqore { * @param container HTML element containing visualized circuit. * @param circuit Circuit to be visualized. * @param isEditable Optional value enabling/disabling editable feature - * @param callbackFn Optional function to trigger when changing elements in circuit + * @param onCircuitChange Optional function to trigger when changing elements in circuit * */ private addGateClickHandlers( container: HTMLElement, circuit: Circuit, isEditable?: boolean, - callbackFn?: () => void, + onCircuitChange?: () => void, ): void { this.addClassicalControlHandlers(container); - this.addZoomHandlers(container, circuit, isEditable, callbackFn); + this.addZoomHandlers(container, circuit, isEditable, onCircuitChange); } /** @@ -310,14 +310,14 @@ export class Sqore { * @param container HTML element containing visualized circuit. * @param circuit Circuit to be visualized. * @param isEditable Optional value enabling/disabling editable feature - * @param callbackFn Optional function to trigger when changing elements in circuit + * @param onCircuitChange Optional function to trigger when changing elements in circuit * */ private addZoomHandlers( container: HTMLElement, circuit: Circuit, isEditable?: boolean, - callbackFn?: () => void, + onCircuitChange?: () => void, ): void { container.querySelectorAll('.gate .gate-control').forEach((ctrl) => { // Zoom in on clicked gate @@ -329,7 +329,7 @@ export class Sqore { } else if (ctrl.classList.contains('gate-expand')) { this.expandOperation(circuit.operations, gateId); } - this.renderCircuit(container, circuit, isEditable, callbackFn); + this.renderCircuit(container, circuit, isEditable, onCircuitChange); ev.stopPropagation(); } }); From b46060bb1695d3f455cd312dd0dd9cbd2fcb7968 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 13 Jun 2022 12:44:48 -0400 Subject: [PATCH 026/108] Document instructions on Editable feature --- example/script.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/example/script.js b/example/script.js index 5c1aa464..76149998 100644 --- a/example/script.js +++ b/example/script.js @@ -12,7 +12,12 @@ if (typeof qviz != 'undefined') { const sampleDiv = document.getElementById('sample'); if (sampleDiv != null) { - qviz.draw(sample, sampleDiv, qviz.STYLES['Default'], 0, true, () => console.log('onCircuitChange')); + const isEditable = true; + const onCircuitChange = () => console.log('onCircuitChange triggered'); + /* Pass in isEditable = true to allow circuit to be editable */ + /* Pass in onCircuitChange to trigger callback function + whenever there is a change in circuit */ + qviz.draw(sample, sampleDiv, qviz.STYLES['Default'], 0, isEditable, onCircuitChange); } const teleportDiv = document.getElementById('teleport'); From 4bfea117a9b6e653bc5472ae4f0a9e698e8e5c97 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 13 Jun 2022 12:47:46 -0400 Subject: [PATCH 027/108] Add license --- __tests__/editable.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index dc5651cf..50e7762d 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + import { Circuit, Operation } from '../src/circuit'; import { exportedForTesting } from '../src/editable'; import { RegisterType } from '../src/register'; From e41f5255738d2bf471497c258c5b779712904bb7 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 13 Jun 2022 12:51:58 -0400 Subject: [PATCH 028/108] Only allow scrollbar if neccessary --- example/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/index.html b/example/index.html index c3060fdd..e612d7b8 100644 --- a/example/index.html +++ b/example/index.html @@ -28,7 +28,7 @@ } .container { - overflow: scroll; + overflow: auto; } </style> </head> From 8e0c9e6dedaebed135f82c5b9fbb5ab71a95eacf Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <37777232+aaronthangnguyen@users.noreply.github.com> Date: Tue, 28 Jun 2022 12:43:09 -0400 Subject: [PATCH 029/108] Reimplement adding dropzones (#69) * Hardcode dropzone-layer * Create basic functionalities * Add identifiable class to x-dot * Add data-gate-id & data-gate-wire * Extract _getCenter * Add events * Change function names * Add move & copy * Fix edge cases * Add offset recursively on wires * Hold Ctrl to copy * Extra stuffs * Let onCircuitChange taking in circuit object * Add partial support for group gates * Remove unnecessary function --- example/script.js | 9 +- src/editable.ts | 540 ++++++++++++++++++-------------- src/formatters/gateFormatter.ts | 2 +- src/index.ts | 2 +- src/sqore.ts | 25 +- src/styles.ts | 52 +-- 6 files changed, 334 insertions(+), 296 deletions(-) diff --git a/example/script.js b/example/script.js index 76149998..9c15533c 100644 --- a/example/script.js +++ b/example/script.js @@ -7,13 +7,16 @@ if (typeof qviz != 'undefined') { /* These examples shows how to draw circuits into containers. */ const entangleDiv = document.getElementById('entangle'); if (entangleDiv != null) { - qviz.draw(entangle, entangleDiv, qviz.STYLES['Default']); + qviz.draw(entangle, entangleDiv, qviz.STYLES['Default'], 0, true); } const sampleDiv = document.getElementById('sample'); if (sampleDiv != null) { const isEditable = true; - const onCircuitChange = () => console.log('onCircuitChange triggered'); + const onCircuitChange = (circuit) => { + console.log('New circuit ↓'); + console.log(circuit); + }; /* Pass in isEditable = true to allow circuit to be editable */ /* Pass in onCircuitChange to trigger callback function whenever there is a change in circuit */ @@ -22,7 +25,7 @@ if (typeof qviz != 'undefined') { const teleportDiv = document.getElementById('teleport'); if (teleportDiv != null) { - qviz.draw(teleport, teleportDiv, qviz.STYLES['Default']); + qviz.draw(teleport, teleportDiv, qviz.STYLES['Default'], 0, true); } const groverDiv = document.getElementById('grover'); diff --git a/src/editable.ts b/src/editable.ts index e0407fb6..befbf36f 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -1,24 +1,21 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { Operation } from './circuit'; -import { leftPadding } from './constants'; +import { Circuit, Operation } from './circuit'; import { box } from './formatters/formatUtils'; import { Sqore } from './sqore'; interface Context { container: HTMLElement; + svg: SVGElement; operations: Operation[]; - wires: Wires; + wireData: number[]; renderFn: () => void; + paddingY: number; + selectedId: string | null; + selectedWire: string | null; } -interface Wires { - [y: string]: string; -} - -let _sourceTarget: SVGElement | null; - /** * Add editable elements and events. * @@ -28,301 +25,368 @@ let _sourceTarget: SVGElement | null; * */ -const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: () => void): void => { +const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (circuit: Circuit) => void): void => { + const svg = container.querySelector('svg') as SVGElement; + const context: Context = { container: container, + svg, operations: sqore.circuit.operations, - wires: getWireElemsY(container), - renderFn: getRenderFn(container, sqore, onCircuitChange), + wireData: _wireData(container), + renderFn: _renderFn(container, sqore, onCircuitChange), + paddingY: 20, + selectedId: null, + selectedWire: null, }; - addDropzones(container); - addDocumentEvents(container); - addDropzoneEvents(context); - addMouseEvents(context); -}; -// Commands - -const addDropzones = (container: HTMLElement): void => { - const gateElems = getGateElems(container); - gateElems.forEach((gateElem) => { - const { x, y, width, height } = gateElem.getBBox(); - const dataId = getDataId(gateElem); - gateElem.append(createLeftDropzone(x, y, height, dataId)); - gateElem.append(createRightDropzone(x, y, width, height, dataId)); - }); + // addDropzones(container); + // addDocumentEvents(container); + _addDataWires(container); + svg.appendChild(_dropzoneLayer(context)); + // addDropzoneEvents(context); + // addMouseEvents(context); + _addEvents(context); }; -const addDocumentEvents = (container: HTMLElement): void => { - container.addEventListener('click', (ev: MouseEvent) => { - _sourceTarget = null; - if (ev.ctrlKey) return; - }); - container.addEventListener('contextmenu', (ev: MouseEvent) => { - ev.preventDefault(); - }); - container.addEventListener('mouseup', () => { - cursorCopy(container, false); - cursorMove(container, false); +const _addDataWires = (container: HTMLElement) => { + const elems = _hostElems(container); + elems.forEach((elem) => { + const { cY } = _center(elem); + // i.e. cY = 40, wireData returns [40, 100, 140, 180] + // dataWire will return 0, which is the index of 40 in wireData + const dataWire = _wireData(container).findIndex((y) => y === cY); + if (dataWire !== -1) { + elem.setAttribute('data-wire', `${dataWire}`); + } else { + const { y, height } = elem.getBBox(); + const wireData = _wireData(container); + const groupDataWire = wireData.findIndex((wireY) => wireY > y && wireY < y + height); + elem.setAttribute('data-wire', `${groupDataWire}`); + } }); }; -const addDropzoneEvents = (context: Context): void => { - const { container } = context; - const dropzoneElems = container.querySelectorAll<SVGRectElement>('.dropzone'); - dropzoneElems.forEach((dropzoneElem) => { - dropzoneElem.addEventListener('mouseup', (ev: MouseEvent) => handleDropzoneMouseUp(ev, context)); - }); +/** + * Create a list of wires that element is spanning on. + * i.e. Gate 'Foo' spans on wire 0 (y=40), 1 (y=100), and 2 (y=140). + * Function returns [40, 100, 140] + */ +const _elemWires = (elem: SVGGraphicsElement, wireData: number[]) => { + const { y, height } = elem.getBBox(); + return wireData.filter((wireY) => wireY > y && wireY < y + height); }; -const addMouseEvents = (context: Context): void => { - const { container } = context; - const gateElems = getGateElems(container); - gateElems.forEach((gateElem) => { - gateElem.addEventListener('mousedown', (ev: MouseEvent) => handleGateMouseDown(ev, container)); - }); +const _hostElems = (container: HTMLElement) => { + return container.querySelectorAll<SVGGraphicsElement>( + '[class^="gate-"]:not(.gate-control, .gate-swap), .control-dot, .oplus, .cross', + ); }; -// Event handlers -const handleGateMouseDown = (ev: MouseEvent, container: HTMLElement): void => { - ev.stopPropagation(); - _sourceTarget = ev.currentTarget as SVGGElement; +const _wirePrefixes = (wireData: number[]) => wireData.map((wireY, index) => ({ index, wireY, prefixX: 40 })); - // Ctrl + Mousedown to copy. Mousedown only to move. - ev.ctrlKey ? cursorCopy(container, true) : cursorMove(container, true); +/** + * Find center point of element + */ +const _center = (elem: SVGGraphicsElement) => { + const { x, y, width, height } = elem.getBBox(); + return { cX: x + width / 2, cY: y + height / 2 }; }; -const handleDropzoneMouseUp = (ev: MouseEvent, context: Context): void | false => { - ev.stopPropagation(); - - const { container, operations, wires, renderFn } = context; - - const currentTarget = ev.currentTarget as SVGGElement; - - if (!currentTarget) return false; - - const dataId = getDataId(currentTarget); - const parent = getParent(dataId, operations); - const index = splitDataId(dataId).pop(); - const position = getDropzonePosition(currentTarget); - - if (_sourceTarget == null) return false; - - const sourceDataId = getDataId(_sourceTarget); - const sourceParent = getParent(sourceDataId, operations); - const sourceIndex = splitDataId(sourceDataId).pop(); - - if (index == null || sourceIndex == null) return false; - - const newGate = getGate(sourceDataId, operations); - const wireY = getClosestWireY(ev.offsetY, wires); - - // Not allow Measure gate to move vertically - if (wireY != null && newGate.gate !== 'measure') { - // wires[wireY] returns qubit name (i.e: 'q0') - // this remove 'q' and assign an index (i.e: 0) - const index = Number(wires[wireY].slice(1)); - const [firstTarget, ...targetsExceptFirst] = newGate.targets; - // Reserve all other properties, only change qId - Object.assign(firstTarget, { ...firstTarget, qId: index }); - // Reserve all other targets, only change first target - Object.assign(newGate, { ...newGate, targets: [firstTarget, ...targetsExceptFirst] }); - } +/** + * Create dropzone layer with all dropzones popullated + */ +const _dropzoneLayer = (context: Context) => { + const dropzoneLayer = document.createElementNS('http://www.w3.org/2000/svg', 'g'); + dropzoneLayer.classList.add('dropzone-layer'); - // Remove source element if moving using Ctrl + Mousedown - if (!ev.ctrlKey) { - deleteAt(sourceParent, sourceIndex); - } + const { container, svg, wireData, operations, paddingY } = context; + const elems = _hostElems(container); - // If dropzone is left of gate, insert before gate. - // Otherwise, insert after. - if (position === 'left') { - insertBefore(parent, index, newGate); - } else { - insertAfter(parent, index, newGate); - } + const wirePrefixes = _wirePrefixes(wireData); - // Remove cursor styles - cursorCopy(container, false); - cursorMove(container, false); + // Sort host elements by its x property + const sortedElems = Array.from(elems).sort((first, second) => { + const { x: x1 } = first.getBBox(); + const { x: x2 } = second.getBBox(); + return x1 - x2; + }); - // Redraw the circuit - renderFn(); -}; + // Add dropzones for each host elements + sortedElems.map((elem) => { + const { cX, cY } = _center(elem); + const wirePrefix = wirePrefixes.find((item) => item.wireY === cY); + + // Check to prevent group gates creating dropzones between wires + if (wirePrefix) { + const prefixX = wirePrefix.prefixX; + const elemDropzone = box(prefixX, cY - paddingY, cX - prefixX, paddingY * 2, 'dropzone'); + elemDropzone.setAttribute('data-dropzone-id', _equivDataId(elem) || ''); + elemDropzone.setAttribute('data-dropzone-wire', `${wirePrefix.index}`); + + wirePrefix.prefixX = cX; + + dropzoneLayer.appendChild(elemDropzone); + } else { + // Let group gates creating dropzones for each wire + const { x } = elem.getBBox(); + const elemWires = _elemWires(elem, wireData); + + elemWires.map((wireY) => { + const wirePrefix = wirePrefixes.find((item) => item.wireY === wireY); + if (wirePrefix) { + const prefixX = wirePrefix.prefixX; + const elemDropzone = box(prefixX, wireY - paddingY, x - prefixX, paddingY * 2, 'dropzone'); + elemDropzone.setAttribute('data-dropzone-id', _equivDataId(elem) || ''); + elemDropzone.setAttribute('data-dropzone-wire', `${wirePrefix.index}`); + + wirePrefix.prefixX = x; + + dropzoneLayer.appendChild(elemDropzone); + } + }); + console.log({ elem, x, elemWires }); + } + }); -// Element getters + // Add remaining dropzones to fit max-width of the circuit + wirePrefixes.map(({ wireY, prefixX }) => { + const maxWidth = Number(svg.getAttribute('width')); + const elemDropzone = box(prefixX, wireY - paddingY, maxWidth - prefixX, paddingY * 2, 'dropzone'); + elemDropzone.setAttribute('data-dropzone-id', `${operations.length}`); + const index = wireData.findIndex((item) => item === wireY); + elemDropzone.setAttribute('data-dropzone-wire', `${index}`); + dropzoneLayer.appendChild(elemDropzone); + }); -const getGateElems = (container: HTMLElement): SVGGElement[] => { - return Array.from(container.querySelectorAll('g.gate')); + return dropzoneLayer; }; -const getWireElems = (container: HTMLElement): SVGGElement[] => { +const _wireData = (container: HTMLElement) => { // elems include qubit wires and lines of measure gates const elems = container.querySelectorAll<SVGGElement>('svg > g:nth-child(3) > g'); // filter out <g> elements having more than 2 elements because // qubit wires contain only 2 elements: <line> and <text> // lines of measure gates contain 4 <line> elements - return Array.from(elems).filter((elem) => elem.childElementCount < 3); + const wireElems = Array.from(elems).filter((elem) => elem.childElementCount < 3); + const wireData = wireElems.map((wireElem) => { + const lineElem = wireElem.children[0] as SVGLineElement; + return lineElem.y1.baseVal.value; + }); + return wireData; }; -// Element creators - -const createDropzone = ( - x: number, - y: number, - width: number, - height: number, - dataId: string, - position: 'left' | 'right', -): SVGElement => { - const dropzone = box(x, y, width, height, `dropzone`); - dropzone.setAttribute('data-id', dataId); - dropzone.setAttribute('data-dropzone-position', position); - return dropzone; +/** + * Find equivalent gate element of host element + */ +const _equivGateElem = (elem: SVGElement) => { + return elem.closest<SVGElement>('[data-id]'); }; -const createLeftDropzone = (gateX: number, gateY: number, gateHeight: number, dataId: string): SVGElement => { - return createDropzone(gateX - leftPadding / 2, gateY, leftPadding / 2, gateHeight, dataId, 'left'); +/** + * Find data-id of host element + */ +const _equivDataId = (elem: SVGElement) => { + const gateElem = _equivGateElem(elem); + return gateElem != null ? gateElem.getAttribute('data-id') : null; }; -const createRightDropzone = ( - gateX: number, - gateY: number, - gateWidth: number, - gateHeight: number, - dataId: string, -): SVGElement => { - return createDropzone(gateX + gateWidth, gateY, leftPadding / 2, gateHeight, dataId, 'right'); + +/** + * Disable contextmenu default behaviors + */ +const _addContextMenuEvents = (container: HTMLElement) => { + container.addEventListener('contextmenu', (ev: MouseEvent) => { + ev.preventDefault(); + }); }; -// Operation getters +/** + * Add events specifically for dropzoneLayer + */ +const _addDropzoneLayerEvents = (container: HTMLElement, dropzoneLayer: SVGGElement) => { + container.addEventListener('mouseup', () => (dropzoneLayer.style.display = 'none')); +}; -const getParent = (dataId: string, operations: Operation[]): Operation[] => { - const segments = splitDataId(dataId); - // Remove last segment to navigate to parent instead of child - segments.pop(); +const _addEvents = (context: Context) => { + const { container, operations, renderFn } = context; + const dropzoneLayer = container.querySelector('.dropzone-layer') as SVGGElement; + + _addContextMenuEvents(container); + _addDropzoneLayerEvents(container, dropzoneLayer); + + // Host element events + const elems = _hostElems(container); + elems.forEach((elem) => { + elem.addEventListener('mousedown', () => { + context.selectedWire = elem.getAttribute('data-wire'); + }); + + const gateElem = _equivGateElem(elem); + gateElem?.addEventListener('mousedown', (ev: MouseEvent) => { + ev.stopPropagation(); + context.selectedId = _equivDataId(elem); + dropzoneLayer.style.display = 'block'; + }); + }); - let parent = operations; - for (const segment of segments) { - parent = parent[segment].children || parent; - } - return parent; + // Dropzone element events + const dropzoneElems = dropzoneLayer.querySelectorAll<SVGRectElement>('.dropzone'); + dropzoneElems.forEach((dropzoneElem) => { + dropzoneElem.addEventListener('mouseup', (ev: MouseEvent) => { + const targetId = dropzoneElem.getAttribute('data-dropzone-id'); + const targetWire = dropzoneElem.getAttribute('data-dropzone-wire'); + if ( + targetId == null || // + targetWire == null || + context.selectedId == null || + context.selectedWire == null + ) + return; + + const newSourceOperation = ev.ctrlKey + ? _copyX(context.selectedId, targetId, operations) + : _moveX(context.selectedId, targetId, operations); + + if (newSourceOperation != null) { + _moveY(context.selectedWire, targetWire, newSourceOperation, context.wireData); + } + + renderFn(); + }); + }); }; -const getGate = (dataId: string, operations: Operation[]): Operation => { - const parent = getParent(dataId, operations); - const index = splitDataId(dataId).pop(); +const _equivOperationParent = (dataId: string | null, operations: Operation[]): Operation[] | null => { + if (!dataId) return null; - if (index == null) { - throw new Error('Gate not found'); - } + const indexes = _indexes(dataId); + indexes.pop(); - return parent[index]; + let operationParent = operations; + for (const index of indexes) { + operationParent = operationParent[index].children || operationParent; + } + return operationParent; }; -// Utilities -const getRenderFn = (container: HTMLElement, sqore: Sqore, onCircuitChange?: () => void): (() => void) => { - return () => { - sqore.draw(container, 0, true, onCircuitChange); - if (onCircuitChange) onCircuitChange(); - }; -}; +const _equivOperation = (dataId: string | null, operations: Operation[]): Operation | null => { + if (!dataId) return null; -const getDataId = (element: Element): string => { - return element.getAttribute('data-id') || ''; -}; + const index = _lastIndex(dataId); + const operationParent = _equivOperationParent(dataId, operations); -const splitDataId = (dataId: string): number[] => { - return dataId === '' ? [] : dataId.split('-').map(Number); + if ( + operationParent == null || // + index == null + ) + return null; + + return operationParent[index]; }; -const getWireElemsY = (container: HTMLElement): Wires => { - const wireElems = getWireElems(container); - return wireElems.reduce((previous, current) => { - const y = getWireElemY(current); - const text = getWireElemText(current); - return { ...previous, [`${y}`]: text }; - }, {}); +const _moveX = (sourceId: string, targetId: string, operations: Operation[]) => { + if (sourceId === targetId) return _equivOperation(sourceId, operations); + const sourceOperation = _equivOperation(sourceId, operations); + const sourceOperationParent = _equivOperationParent(sourceId, operations); + const targetOperationParent = _equivOperationParent(targetId, operations); + const targetLastIndex = _lastIndex(targetId); + + if ( + targetOperationParent == null || // + targetLastIndex == null || + sourceOperation == null || + sourceOperationParent == null + ) + return; + + // Insert sourceOperation to target last index + const newSourceOperation: Operation = { ...sourceOperation }; + targetOperationParent.splice(targetLastIndex, 0, newSourceOperation); + + // Delete sourceOperation + sourceOperation.gate = 'removed'; + const indexToRemove = sourceOperationParent.findIndex((operation) => operation.gate === 'removed'); + sourceOperationParent.splice(indexToRemove, 1); + + return newSourceOperation; }; -const getWireElemY = (wireElem: SVGGElement): number => { - const lineElem = wireElem.querySelector<SVGLineElement>('line'); - if (lineElem == null || lineElem.getAttribute('y1') == null) throw Error('y not found'); - return Number(lineElem.getAttribute('y1')); +const _copyX = (sourceId: string, targetId: string, operations: Operation[]) => { + if (sourceId === targetId) return _equivOperation(sourceId, operations); + const sourceOperation = _equivOperation(sourceId, operations); + const sourceOperationParent = _equivOperationParent(sourceId, operations); + const targetOperationParent = _equivOperationParent(targetId, operations); + const targetLastIndex = _lastIndex(targetId); + + if ( + targetOperationParent == null || // + targetLastIndex == null || + sourceOperation == null || + sourceOperationParent == null + ) + return; + + // Insert sourceOperation to target last index + const newSourceOperation: Operation = JSON.parse(JSON.stringify(sourceOperation)); + targetOperationParent.splice(targetLastIndex, 0, newSourceOperation); + + return newSourceOperation; }; -const getWireElemText = (wireElem: SVGGElement): string => { - const textElem = wireElem.querySelector<SVGTextElement>('text'); - if (textElem == null || textElem.textContent == null || textElem.textContent === '') - throw new Error('Text not found'); - return textElem.textContent; +const _moveY = (sourceWire: string, targetWire: string, operation: Operation, wireData: number[]) => { + const offset = parseInt(targetWire) - parseInt(sourceWire); + _offsetRecursively(offset, operation, wireData); }; -const getClosestWireY = (offsetY: number, wires: { [y: number]: string }): number | null => { - for (const wire of Object.entries(wires)) { - const y = wire[0]; - const distance = Math.abs(offsetY - Number(y)); - // 15 is an arbitrary number to determine the closeness of distance - if (distance <= 15) { - return Number(y); - } +const _offsetRecursively = (offsetY: number, operation: Operation, wireData: number[]) => { + const wireDataSize = wireData.length; + + // Offset all targets by offsetY value + if (operation.targets != null) { + operation.targets.forEach((target) => { + target.qId = _circularMod(target.qId, offsetY, wireDataSize); + if (target.cId) target.cId = _circularMod(target.cId, offsetY, wireDataSize); + }); } - return null; -}; -const getDropzonePosition = (element: SVGElement): string => { - const position = element.getAttribute('data-dropzone-position'); - if (position == null) throw new Error('Position not found'); - return position; -}; + // Offset all controls by offsetY value + if (operation.controls != null) { + operation.controls.forEach((control) => { + control.qId = _circularMod(control.qId, offsetY, wireDataSize); + if (control.cId) control.cId = _circularMod(control.qId, offsetY, wireDataSize); + }); + } -const insertBefore = (parent: Operation[], index: number, newGate: Operation): void => { - parent.splice(index, 0, newGate); + // Offset recursively through all children + if (operation.children != null) { + operation.children.forEach((child) => _offsetRecursively(offsetY, child, wireData)); + } }; -const insertAfter = (parent: Operation[], index: number, newGate: Operation): void => { - parent.splice(index + 1, 0, newGate); +/** + * This modulo function always returns positive value based on total. + * i.e: value=0, offset=-1, total=4 returns 3 instead of -1 + */ +const _circularMod = (value: number, offset: number, total: number) => { + return (((value + offset) % total) + total) % total; }; -const deleteAt = (parent: Operation[], index: number): void => { - parent.splice(index, 1); -}; +const _indexes = (dataId: string) => dataId.split('-').map((segment) => parseInt(segment)); -const cursorMove = (container: HTMLElement, value: boolean): void => { - value ? container.classList.add('moving') : container.classList.remove('moving'); +const _lastIndex = (dataId: string) => { + return _indexes(dataId).pop(); }; -const cursorCopy = (container: HTMLElement, value: boolean): void => { - value ? container.classList.add('copying') : container.classList.remove('copying'); +const _renderFn = ( + container: HTMLElement, + sqore: Sqore, + onCircuitChange?: (circuit: Circuit) => void, +): (() => void) => { + return () => { + sqore.draw(container, 0, true, onCircuitChange); + if (onCircuitChange) onCircuitChange(sqore.circuit); + }; }; -const exportedForTesting = { - // addEditable - addDropzones, - addDocumentEvents, - addDropzoneEvents, - addMouseEvents, - handleGateMouseDown, - // handleDropzoneMouseUp - getGateElems, - getWireElems, - createDropzone, - createLeftDropzone, - createRightDropzone, - getParent, - getGate, - getDataId, - getRenderFn, - splitDataId, - getWireElemsY, - getWireElemY, - getWireElemText, - getClosestWireY, - getDropzonePosition, - insertBefore, - insertAfter, - deleteAt, - cursorMove, - cursorCopy, -}; +const exportedForTesting = {}; export { addEditable, exportedForTesting }; diff --git a/src/formatters/gateFormatter.ts b/src/formatters/gateFormatter.ts index 16588ff3..607bdc16 100644 --- a/src/formatters/gateFormatter.ts +++ b/src/formatters/gateFormatter.ts @@ -302,7 +302,7 @@ const _cross = (x: number, y: number): SVGElement => { const radius = 8; const line1: SVGElement = line(x - radius, y - radius, x + radius, y + radius); const line2: SVGElement = line(x - radius, y + radius, x + radius, y - radius); - return group([line1, line2]); + return group([line1, line2], { class: 'cross' }); }; /** diff --git a/src/index.ts b/src/index.ts index 5e5d770f..56b35003 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,7 +21,7 @@ export const draw = ( style: StyleConfig | string = {}, renderDepth = 0, isEditable?: boolean, - onCircuitChange?: () => void, + onCircuitChange?: (circuit: Circuit) => void, ): void => { const sqore = new Sqore(circuit, style); diff --git a/src/sqore.ts b/src/sqore.ts index 878eef24..17934f74 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -1,16 +1,16 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { formatInputs } from './formatters/inputFormatter'; +import { Circuit, ConditionalRender, Operation } from './circuit'; +import { svgNS } from './constants'; +import { addEditable } from './editable'; import { formatGates } from './formatters/gateFormatter'; +import { formatInputs } from './formatters/inputFormatter'; import { formatRegisters } from './formatters/registerFormatter'; +import { GateType, Metadata } from './metadata'; import { processOperations } from './process'; -import { ConditionalRender, Circuit, Operation } from './circuit'; -import { Metadata, GateType } from './metadata'; -import { StyleConfig, style, STYLES } from './styles'; +import { style, StyleConfig, STYLES } from './styles'; import { createUUID } from './utils'; -import { svgNS } from './constants'; -import { addEditable } from './editable'; /** * Contains metadata for visualization. @@ -59,7 +59,12 @@ export class Sqore { * @param isEditable Optional value enabling/disabling editable feature * @param onCircuitChange Optional function to trigger when changing elements in circuit */ - draw(container: HTMLElement, renderDepth = 0, isEditable?: boolean, onCircuitChange?: () => void): void { + draw( + container: HTMLElement, + renderDepth = 0, + isEditable?: boolean, + onCircuitChange?: (circuit: Circuit) => void, + ): void { // Inject into container if (container == null) throw new Error(`Container not provided.`); @@ -115,7 +120,7 @@ export class Sqore { container: HTMLElement, circuit: Circuit, isEditable?: boolean, - onCircuitChange?: () => void, + onCircuitChange?: (circuit: Circuit) => void, ): void { // Create visualization components const composedSqore: ComposedSqore = this.compose(circuit); @@ -250,7 +255,7 @@ export class Sqore { container: HTMLElement, circuit: Circuit, isEditable?: boolean, - onCircuitChange?: () => void, + onCircuitChange?: (circuit: Circuit) => void, ): void { this.addClassicalControlHandlers(container); this.addZoomHandlers(container, circuit, isEditable, onCircuitChange); @@ -317,7 +322,7 @@ export class Sqore { container: HTMLElement, circuit: Circuit, isEditable?: boolean, - onCircuitChange?: () => void, + onCircuitChange?: (circuit: Circuit) => void, ): void { container.querySelectorAll('.gate .gate-control').forEach((ctrl) => { // Zoom in on clicked gate diff --git a/src/styles.ts b/src/styles.ts index 10327841..481aea8c 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -237,53 +237,19 @@ const _expandCollapse = ` }`; const _editable = ` - .dropzone { - fill: transparent; - stroke: transparent; - } - .dropzone:hover{ - fill: red; - opacity: 25%; - } - text { - user-select: none; - } - .copying { - cursor: copy; - } - .moving { - cursor: move; - } - .detail-panel { - display: flex; - align-content: center; - gap: 12px; - }.dropzone { - fill: transparent; - stroke: transparent; - } - .dropzone:hover{ - fill: red; - opacity: 25%; - } text { user-select: none; + pointer-events: none; } - .copying { - cursor: copy; - } - .moving { - cursor: move; - } - .detail-panel { - display: flex; - align-content: center; - gap: 12px; + .dropzone-layer { + display: none; } - g.gate:not([data-expanded=true]) rect { - cursor: grab; + .dropzone { + fill-opacity: 0%; + stroke-opacity: 0%; } - g.gate:not([data-expanded=true]) circle { - cursor: grab; + .dropzone:hover { + fill: #EC7063; + fill-opacity: 50%; } `; From 605c64c7706c3097a0e39ba420e3ffed9253dc8b Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 13:11:56 -0400 Subject: [PATCH 030/108] Update snapshots --- __tests__/__snapshots__/editable.test.ts.snap | 1147 ----------------- .../__snapshots__/gateFormatter.test.ts.snap | 72 +- 2 files changed, 54 insertions(+), 1165 deletions(-) delete mode 100644 __tests__/__snapshots__/editable.test.ts.snap diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap deleted file mode 100644 index d8e2ae43..00000000 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ /dev/null @@ -1,1147 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Testing addDocumentEvents verify document events 1`] = `<div />`; - -exports[`Testing addDocumentEvents verify document events 2`] = `<div />`; - -exports[`Testing addDropzoneEvents add 1 event 1`] = ` -<div> - <svg> - <rect /> - </svg> -</div> -`; - -exports[`Testing addDropzoneEvents add 2 events 1`] = ` -<div> - <svg> - <rect /> - <rect /> - </svg> -</div> -`; - -exports[`Testing addDropzones verify dropzones 1`] = ` -<div> - <svg - class="qviz" - height="180" - style="max-width: fit-content;" - width="260" - > - <style> - - line, - circle, - rect { - stroke: #000000; - stroke-width: 1; - } - text { - fill: #000000; - dominant-baseline: middle; - text-anchor: middle; - font-family: Arial; - } - .control-dot { - fill: #000000; - } - .oplus line, .oplus circle { - fill: #FFFFFF; - stroke-width: 2; - } - .gate-unitary { - fill: #D9F1FA; - } - .gate-measure { - fill: #FFDE86; - } - rect.gate-swap { - fill: transparent; - stroke: transparent; - } - .arc-measure { - stroke: #000000; - fill: none; - stroke-width: 1; - } - .register-classical { - stroke-width: 0.5; - } - - .hidden { - display: none; - } - .classically-controlled-unknown { - opacity: 0.25; - } - - - .classically-controlled-one .classical-container, - .classically-controlled-one .classical-line { - stroke: #4059BD; - stroke-width: 1.3; - fill: #4059BD; - fill-opacity: 0.1; - } - .classically-controlled-zero .classical-container, - .classically-controlled-zero .classical-line { - stroke: #C40000; - stroke-width: 1.3; - fill: #C40000; - fill-opacity: 0.1; - } - - .classically-controlled-btn { - cursor: pointer; - } - .classically-controlled-unknown .classically-controlled-btn { - fill: #E5E5E5; - } - .classically-controlled-one .classically-controlled-btn { - fill: #4059BD; - } - .classically-controlled-zero .classically-controlled-btn { - fill: #C40000; - } - - .classically-controlled-btn text { - dominant-baseline: middle; - text-anchor: middle; - stroke: none; - font-family: Arial; - } - .classically-controlled-unknown .classically-controlled-btn text { - fill: #000000; - } - .classically-controlled-one .classically-controlled-btn text { - fill: #FFFFFF; - } - .classically-controlled-zero .classically-controlled-btn text { - fill: #FFFFFF; - } - - .qviz .gate-collapse, - .qviz .gate-expand { - opacity: 0; - transition: opacity 1s; - } - - .qviz:hover .gate-collapse, - .qviz:hover .gate-expand { - visibility: visible; - opacity: 0.2; - transition: visibility 1s; - transition: opacity 1s; - } - - .gate-expand, .gate-collapse { - cursor: pointer; - } - - .gate-collapse circle, - .gate-expand circle { - fill: white; - stroke-width: 2px; - stroke: black; - } - .gate-collapse path, - .gate-expand path { - stroke-width: 4px; - stroke: black; - } - - .gate:hover > .gate-collapse, - .gate:hover > .gate-expand { - visibility: visible; - opacity: 1; - transition: opacity 1s; - } - - .dropzone { - fill: transparent; - stroke: transparent; - } - .dropzone:hover{ - fill: red; - opacity: 25%; - } - text { - user-select: none; - } - .copying { - cursor: copy; - } - .moving { - cursor: move; - } - .detail-panel { - display: flex; - align-content: center; - gap: 12px; - }.dropzone { - fill: transparent; - stroke: transparent; - } - .dropzone:hover{ - fill: red; - opacity: 25%; - } - text { - user-select: none; - } - .copying { - cursor: copy; - } - .moving { - cursor: move; - } - .detail-panel { - display: flex; - align-content: center; - gap: 12px; - } - g.gate:not([data-expanded=true]) rect { - cursor: grab; - } - g.gate:not([data-expanded=true]) circle { - cursor: grab; - } - - </style> - <g> - <text - dominant-baseline="middle" - font-size="16" - text-anchor="start" - x="20" - y="40" - > - |0⟩ - </text> - <text - dominant-baseline="middle" - font-size="16" - text-anchor="start" - x="20" - y="100" - > - |0⟩ - </text> - </g> - <g> - <g> - <line - x1="40" - x2="260" - y1="40" - y2="40" - /> - <text - dominant-baseline="hanging" - font-size="75%" - text-anchor="start" - x="40" - y="24" - > - q0 - </text> - </g> - <g> - <line - x1="40" - x2="260" - y1="100" - y2="100" - /> - <text - dominant-baseline="hanging" - font-size="75%" - text-anchor="start" - x="40" - y="84" - > - q1 - </text> - </g> - <g> - <line - class="register-classical" - x1="221" - x2="221" - y1="100" - y2="139" - /> - <line - class="register-classical" - x1="219" - x2="219" - y1="100" - y2="141" - /> - <line - class="register-classical" - x1="221" - x2="260" - y1="139" - y2="139" - /> - <line - class="register-classical" - x1="219" - x2="260" - y1="141" - y2="141" - /> - </g> - </g> - <g> - <g - class="gate" - data-id="0" - data-zoom-in="false" - data-zoom-out="false" - > - <g> - <g> - <rect - class="gate-unitary" - height="40" - width="40" - x="80" - y="20" - /> - <text - font-size="14" - x="100" - y="40" - > - H - </text> - </g> - </g> - <rect - class="dropzone" - data-dropzone-position="left" - data-id="0" - height="0" - width="10" - x="-10" - y="0" - /> - <rect - class="dropzone" - data-dropzone-position="right" - data-id="0" - height="0" - width="10" - x="0" - y="0" - /> - <rect - class="dropzone" - data-dropzone-position="left" - data-id="0" - height="0" - width="10" - x="-10" - y="0" - /> - <rect - class="dropzone" - data-dropzone-position="right" - data-id="0" - height="0" - width="10" - x="0" - y="0" - /> - </g> - <g - class="gate" - data-id="1" - data-zoom-in="false" - data-zoom-out="false" - > - <line - x1="160" - x2="160" - y1="40" - y2="100" - /> - <circle - class="control-dot" - cx="160" - cy="40" - r="5" - /> - <g - class="oplus" - > - <circle - cx="160" - cy="100" - r="15" - /> - <line - x1="160" - x2="160" - y1="85" - y2="115" - /> - <line - x1="145" - x2="175" - y1="100" - y2="100" - /> - </g> - <rect - class="dropzone" - data-dropzone-position="left" - data-id="1" - height="0" - width="10" - x="-10" - y="0" - /> - <rect - class="dropzone" - data-dropzone-position="right" - data-id="1" - height="0" - width="10" - x="0" - y="0" - /> - <rect - class="dropzone" - data-dropzone-position="left" - data-id="1" - height="0" - width="10" - x="-10" - y="0" - /> - <rect - class="dropzone" - data-dropzone-position="right" - data-id="1" - height="0" - width="10" - x="0" - y="0" - /> - </g> - <g - class="gate" - data-id="2" - data-zoom-in="false" - data-zoom-out="false" - > - <g> - <rect - class="gate-measure" - height="40" - width="40" - x="200" - y="80" - /> - <path - class="arc-measure" - d="M 235 102 A 15 12 0 0 0 205 102" - /> - <line - x1="220" - x2="232" - y1="108" - y2="88" - /> - </g> - <rect - class="dropzone" - data-dropzone-position="left" - data-id="2" - height="0" - width="10" - x="-10" - y="0" - /> - <rect - class="dropzone" - data-dropzone-position="right" - data-id="2" - height="0" - width="10" - x="0" - y="0" - /> - <rect - class="dropzone" - data-dropzone-position="left" - data-id="2" - height="0" - width="10" - x="-10" - y="0" - /> - <rect - class="dropzone" - data-dropzone-position="right" - data-id="2" - height="0" - width="10" - x="0" - y="0" - /> - </g> - </g> - </svg> -</div> -`; - -exports[`Testing addMouseEvents verify mouse events 1`] = ` -<div> - <svg - class="qviz" - height="180" - style="max-width: fit-content;" - width="140" - > - <style> - - line, - circle, - rect { - stroke: #000000; - stroke-width: 1; - } - text { - fill: #000000; - dominant-baseline: middle; - text-anchor: middle; - font-family: Arial; - } - .control-dot { - fill: #000000; - } - .oplus line, .oplus circle { - fill: #FFFFFF; - stroke-width: 2; - } - .gate-unitary { - fill: #D9F1FA; - } - .gate-measure { - fill: #FFDE86; - } - rect.gate-swap { - fill: transparent; - stroke: transparent; - } - .arc-measure { - stroke: #000000; - fill: none; - stroke-width: 1; - } - .register-classical { - stroke-width: 0.5; - } - - .hidden { - display: none; - } - .classically-controlled-unknown { - opacity: 0.25; - } - - - .classically-controlled-one .classical-container, - .classically-controlled-one .classical-line { - stroke: #4059BD; - stroke-width: 1.3; - fill: #4059BD; - fill-opacity: 0.1; - } - .classically-controlled-zero .classical-container, - .classically-controlled-zero .classical-line { - stroke: #C40000; - stroke-width: 1.3; - fill: #C40000; - fill-opacity: 0.1; - } - - .classically-controlled-btn { - cursor: pointer; - } - .classically-controlled-unknown .classically-controlled-btn { - fill: #E5E5E5; - } - .classically-controlled-one .classically-controlled-btn { - fill: #4059BD; - } - .classically-controlled-zero .classically-controlled-btn { - fill: #C40000; - } - - .classically-controlled-btn text { - dominant-baseline: middle; - text-anchor: middle; - stroke: none; - font-family: Arial; - } - .classically-controlled-unknown .classically-controlled-btn text { - fill: #000000; - } - .classically-controlled-one .classically-controlled-btn text { - fill: #FFFFFF; - } - .classically-controlled-zero .classically-controlled-btn text { - fill: #FFFFFF; - } - - .qviz .gate-collapse, - .qviz .gate-expand { - opacity: 0; - transition: opacity 1s; - } - - .qviz:hover .gate-collapse, - .qviz:hover .gate-expand { - visibility: visible; - opacity: 0.2; - transition: visibility 1s; - transition: opacity 1s; - } - - .gate-expand, .gate-collapse { - cursor: pointer; - } - - .gate-collapse circle, - .gate-expand circle { - fill: white; - stroke-width: 2px; - stroke: black; - } - .gate-collapse path, - .gate-expand path { - stroke-width: 4px; - stroke: black; - } - - .gate:hover > .gate-collapse, - .gate:hover > .gate-expand { - visibility: visible; - opacity: 1; - transition: opacity 1s; - } - - .dropzone { - fill: transparent; - stroke: transparent; - } - .dropzone:hover{ - fill: red; - opacity: 25%; - } - text { - user-select: none; - } - .copying { - cursor: copy; - } - .moving { - cursor: move; - } - .detail-panel { - display: flex; - align-content: center; - gap: 12px; - }.dropzone { - fill: transparent; - stroke: transparent; - } - .dropzone:hover{ - fill: red; - opacity: 25%; - } - text { - user-select: none; - } - .copying { - cursor: copy; - } - .moving { - cursor: move; - } - .detail-panel { - display: flex; - align-content: center; - gap: 12px; - } - g.gate:not([data-expanded=true]) rect { - cursor: grab; - } - g.gate:not([data-expanded=true]) circle { - cursor: grab; - } - - </style> - <g> - <text - dominant-baseline="middle" - font-size="16" - text-anchor="start" - x="20" - y="40" - > - |0⟩ - </text> - <text - dominant-baseline="middle" - font-size="16" - text-anchor="start" - x="20" - y="100" - > - |0⟩ - </text> - </g> - <g> - <g> - <line - x1="40" - x2="140" - y1="40" - y2="40" - /> - <text - dominant-baseline="hanging" - font-size="75%" - text-anchor="start" - x="40" - y="24" - > - q0 - </text> - </g> - <g> - <line - x1="40" - x2="140" - y1="100" - y2="100" - /> - <text - dominant-baseline="hanging" - font-size="75%" - text-anchor="start" - x="40" - y="84" - > - q1 - </text> - </g> - <g> - <line - class="register-classical" - x1="101" - x2="101" - y1="100" - y2="139" - /> - <line - class="register-classical" - x1="99" - x2="99" - y1="100" - y2="141" - /> - <line - class="register-classical" - x1="101" - x2="140" - y1="139" - y2="139" - /> - <line - class="register-classical" - x1="99" - x2="140" - y1="141" - y2="141" - /> - </g> - </g> - <g> - <g - class="gate" - data-id="0" - data-zoom-in="false" - data-zoom-out="false" - > - <g> - <g> - <rect - class="gate-unitary" - height="40" - width="40" - x="80" - y="20" - /> - <text - font-size="14" - x="100" - y="40" - > - H - </text> - </g> - </g> - </g> - <g - class="gate" - data-id="1" - data-zoom-in="false" - data-zoom-out="false" - > - <g> - <rect - class="gate-measure" - height="40" - width="40" - x="80" - y="80" - /> - <path - class="arc-measure" - d="M 115 102 A 15 12 0 0 0 85 102" - /> - <line - x1="100" - x2="112" - y1="108" - y2="88" - /> - </g> - </g> - </g> - </svg> -</div> -`; - -exports[`Testing createDropzone create dropzone on the left 1`] = ` -<rect - class="dropzone" - data-dropzone-position="left" - data-id="0" - height="20" - width="20" - x="0" - y="0" -/> -`; - -exports[`Testing createDropzone create dropzone on the right 1`] = ` -<rect - class="dropzone" - data-dropzone-position="right" - data-id="0" - height="20" - width="20" - x="0" - y="0" -/> -`; - -exports[`Testing createLeftDropzone create left dropzone 1`] = ` -<rect - class="dropzone" - data-dropzone-position="left" - data-id="0" - height="20" - width="10" - x="-10" - y="0" -/> -`; - -exports[`Testing createRightDropzone create dropzone right 1`] = ` -<rect - class="dropzone" - data-dropzone-position="right" - data-id="0" - height="20" - width="10" - x="20" - y="0" -/> -`; - -exports[`Testing cursorCopy turn off copy cursor 1`] = ` -<div - class="copying" -/> -`; - -exports[`Testing cursorCopy turn off copy cursor 2`] = ` -<div - class="" -/> -`; - -exports[`Testing cursorCopy turn on and off copy cursor 1`] = ` -<div - class="" -/> -`; - -exports[`Testing cursorCopy turn on and off copy cursor 2`] = ` -<div - class="" -/> -`; - -exports[`Testing cursorCopy turn on copy cursor 1`] = `<div />`; - -exports[`Testing cursorCopy turn on copy cursor 2`] = ` -<div - class="copying" -/> -`; - -exports[`Testing cursorMove turn off move cursor 1`] = ` -<div - class="moving" -/> -`; - -exports[`Testing cursorMove turn off move cursor 2`] = ` -<div - class="" -/> -`; - -exports[`Testing cursorMove turn on and off move cursor 1`] = ` -<div - class="" -/> -`; - -exports[`Testing cursorMove turn on and off move cursor 2`] = ` -<div - class="" -/> -`; - -exports[`Testing cursorMove turn on move cursor 1`] = `<div />`; - -exports[`Testing cursorMove turn on move cursor 2`] = ` -<div - class="moving" -/> -`; - -exports[`Testing getGateElems get 2 gates 1`] = ` -Array [ - <g - class="gate" - data-id="0" - data-zoom-in="false" - data-zoom-out="false" - > - <g> - <g> - <rect - class="gate-unitary" - height="40" - width="40" - x="80" - y="20" - /> - <text - font-size="14" - x="100" - y="40" - > - H - </text> - </g> - </g> - </g>, - <g - class="gate" - data-id="1" - data-zoom-in="false" - data-zoom-out="false" - > - <g> - <rect - class="gate-measure" - height="40" - width="40" - x="80" - y="80" - /> - <path - class="arc-measure" - d="M 115 102 A 15 12 0 0 0 85 102" - /> - <line - x1="100" - x2="112" - y1="108" - y2="88" - /> - </g> - </g>, -] -`; - -exports[`Testing getGateElems get 3 gates 1`] = ` -Array [ - <g - class="gate" - data-id="0" - data-zoom-in="false" - data-zoom-out="false" - > - <g> - <g> - <rect - class="gate-unitary" - height="40" - width="40" - x="80" - y="20" - /> - <text - font-size="14" - x="100" - y="40" - > - H - </text> - </g> - </g> - </g>, - <g - class="gate" - data-id="1" - data-zoom-in="false" - data-zoom-out="false" - > - <line - x1="160" - x2="160" - y1="40" - y2="100" - /> - <circle - class="control-dot" - cx="160" - cy="40" - r="5" - /> - <g - class="oplus" - > - <circle - cx="160" - cy="100" - r="15" - /> - <line - x1="160" - x2="160" - y1="85" - y2="115" - /> - <line - x1="145" - x2="175" - y1="100" - y2="100" - /> - </g> - </g>, - <g - class="gate" - data-id="2" - data-zoom-in="false" - data-zoom-out="false" - > - <g> - <rect - class="gate-measure" - height="40" - width="40" - x="200" - y="80" - /> - <path - class="arc-measure" - d="M 235 102 A 15 12 0 0 0 205 102" - /> - <line - x1="220" - x2="232" - y1="108" - y2="88" - /> - </g> - </g>, -] -`; - -exports[`Testing getWireElems get 2 wires 1`] = ` -Array [ - <g> - <line - x1="40" - x2="260" - y1="40" - y2="40" - /> - <text - dominant-baseline="hanging" - font-size="75%" - text-anchor="start" - x="40" - y="24" - > - q0 - </text> - </g>, - <g> - <line - x1="40" - x2="260" - y1="100" - y2="100" - /> - <text - dominant-baseline="hanging" - font-size="75%" - text-anchor="start" - x="40" - y="84" - > - q1 - </text> - </g>, -] -`; - -exports[`Testing handleGateMouseDown copying, ctrlKey is true 1`] = ` -<div - class="copying" -/> -`; - -exports[`Testing handleGateMouseDown moving, ctrlKey is false 1`] = ` -<div - class="moving" -/> -`; diff --git a/__tests__/__snapshots__/gateFormatter.test.ts.snap b/__tests__/__snapshots__/gateFormatter.test.ts.snap index e75b6f54..5596850a 100644 --- a/__tests__/__snapshots__/gateFormatter.test.ts.snap +++ b/__tests__/__snapshots__/gateFormatter.test.ts.snap @@ -1326,7 +1326,9 @@ exports[`Testing _controlledGate SWAP gate 1`] = ` cy="40" r="5" /> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -1340,7 +1342,9 @@ exports[`Testing _controlledGate SWAP gate 1`] = ` y2="92" /> </g> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -1373,7 +1377,9 @@ exports[`Testing _controlledGate SWAP gate 2`] = ` cy="160" r="5" /> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -1387,7 +1393,9 @@ exports[`Testing _controlledGate SWAP gate 2`] = ` y2="32" /> </g> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -1420,7 +1428,9 @@ exports[`Testing _controlledGate SWAP gate 3`] = ` cy="100" r="5" /> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -1434,7 +1444,9 @@ exports[`Testing _controlledGate SWAP gate 3`] = ` y2="32" /> </g> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -1578,7 +1590,9 @@ exports[`Testing _formatGate controlled swap gate 1`] = ` cy="40" r="5" /> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -1592,7 +1606,9 @@ exports[`Testing _formatGate controlled swap gate 1`] = ` y2="92" /> </g> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -1875,7 +1891,9 @@ exports[`Testing _formatGate swap gate 1`] = ` x="60" y="20" /> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -1889,7 +1907,9 @@ exports[`Testing _formatGate swap gate 1`] = ` y2="32" /> </g> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -2419,7 +2439,9 @@ exports[`Testing _swap Adjacent swap 1`] = ` x="60" y="20" /> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -2433,7 +2455,9 @@ exports[`Testing _swap Adjacent swap 1`] = ` y2="32" /> </g> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -2465,7 +2489,9 @@ exports[`Testing _swap Adjacent swap 2`] = ` x="60" y="20" /> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -2479,7 +2505,9 @@ exports[`Testing _swap Adjacent swap 2`] = ` y2="92" /> </g> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -2511,7 +2539,9 @@ exports[`Testing _swap Non-adjacent swap 1`] = ` x="60" y="20" /> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -2525,7 +2555,9 @@ exports[`Testing _swap Non-adjacent swap 1`] = ` y2="32" /> </g> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -2557,7 +2589,9 @@ exports[`Testing _swap Non-adjacent swap 2`] = ` x="60" y="20" /> - <g> + <g + class="cross" + > <line x1="72" x2="88" @@ -2571,7 +2605,9 @@ exports[`Testing _swap Non-adjacent swap 2`] = ` y2="152" /> </g> - <g> + <g + class="cross" + > <line x1="72" x2="88" From bddc2d18c86fd176f136b21a5e262bc5ff5e9413 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 13:12:17 -0400 Subject: [PATCH 031/108] Update tests --- __tests__/editable.test.ts | 1344 +----------------------------------- src/editable.ts | 9 +- 2 files changed, 44 insertions(+), 1309 deletions(-) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 50e7762d..209f21bd 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -1,1327 +1,59 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { Circuit, Operation } from '../src/circuit'; import { exportedForTesting } from '../src/editable'; -import { RegisterType } from '../src/register'; -import { draw, STYLES } from '../src/index'; -import { Sqore } from '../src/sqore'; -const { - // addEditable - addDropzones, - addDocumentEvents, - addDropzoneEvents, - addMouseEvents, - handleGateMouseDown, - // handleDropzoneMouseUp - getGateElems, - getWireElems, - createDropzone, - createLeftDropzone, - createRightDropzone, - getParent, - getGate, - getRenderFn, - getDataId, - splitDataId, - getWireElemsY, - getWireElemY, - getWireElemText, - getClosestWireY, - getDropzonePosition, - insertBefore, - insertAfter, - deleteAt, - cursorMove, - cursorCopy, -} = exportedForTesting; +const { _indexes, _lastIndex, _center } = exportedForTesting; -// Utlities -describe('Testing getDataId', () => { - const elem = document.createElement('div'); - test('with with no data-id', () => { - expect(getDataId(elem)).toBe(''); - }); - test('with level 0 data-id', () => { - elem.setAttribute('data-id', '0'); - expect(getDataId(elem)).toBe('0'); - }); - - test('with level 1 data-id', () => { - elem.setAttribute('data-id', '0-1'); - expect(getDataId(elem)).toBe('0-1'); - }); -}); - -describe('Testing splitDataId', () => { - test('with empty dataId', () => { - expect(splitDataId('')).toStrictEqual([]); - }); - test('with level 0 data-id', () => { - expect(splitDataId('1')).toStrictEqual([1]); - }); - - test('with level 1 data-id', () => { - expect(splitDataId('1-2')).toStrictEqual([1, 2]); - }); -}); - -describe('Testing cursorMove', () => { - const container = document.createElement('div'); - test('turn on move cursor', () => { - expect(container).toMatchSnapshot(); - cursorMove(container, true); - expect(container).toMatchSnapshot(); - }); - test('turn off move cursor', () => { - expect(container).toMatchSnapshot(); - cursorMove(container, false); - expect(container).toMatchSnapshot(); - }); - test('turn on and off move cursor', () => { - expect(container).toMatchSnapshot(); - cursorMove(container, true); - cursorMove(container, false); - expect(container).toMatchSnapshot(); - }); -}); - -describe('Testing cursorCopy', () => { - const container = document.createElement('div'); - test('turn on copy cursor', () => { - expect(container).toMatchSnapshot(); - cursorCopy(container, true); - expect(container).toMatchSnapshot(); - }); - test('turn off copy cursor', () => { - expect(container).toMatchSnapshot(); - cursorCopy(container, false); - expect(container).toMatchSnapshot(); - }); - test('turn on and off copy cursor', () => { - expect(container).toMatchSnapshot(); - cursorCopy(container, true); - cursorCopy(container, false); - expect(container).toMatchSnapshot(); - }); -}); - -describe('Testing deleteAt', () => { - const operations: Operation[] = []; - beforeEach(() => { - Object.assign(operations, [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]); - }); - test('delete X at index 0', () => { - deleteAt(operations, 0); - expect(operations).toStrictEqual([ - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]); - }); - test('delete Y at index 1', () => { - deleteAt(operations, 1); - expect(operations).toStrictEqual([ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]); - }); - test('delete Z and X at index 2, 0', () => { - deleteAt(operations, 2); - deleteAt(operations, 0); - expect(operations).toStrictEqual([ - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]); - }); -}); - -describe('Testing insertBefore', () => { - test('insert before X', () => { - const operations = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - const newGate = { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - insertBefore(operations, 0, newGate); - expect(operations).toStrictEqual([ - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]); - }); -}); - -describe('Testing insertAfter', () => { - test('insert after X', () => { - const operations = [ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]; - const newGate = { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }; - insertAfter(operations, 0, newGate); - expect(operations).toStrictEqual([ - { - gate: 'X', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Y', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - { - gate: 'Z', - isMeasurement: false, - isConditional: false, - isControlled: false, - isAdjoint: false, - controls: [], - targets: [{ type: RegisterType.Qubit, qId: 0 }], - }, - ]); - }); -}); - -describe('Testing getDropzonePosition', () => { - let svgElem: SVGElement; - let dropzoneElem: SVGElement; - beforeEach(() => { - svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg') as SVGElement; - dropzoneElem = document.createElementNS('http://www.w3.org/2000/svg', 'rect') as SVGElement; - svgElem.append(dropzoneElem); - }); - test('get position of non-dropzone', () => { - expect(() => getDropzonePosition(dropzoneElem)).toThrowError('Position not found'); - }); - test('get position of dropzone on the left', () => { - dropzoneElem.setAttribute('data-dropzone-position', 'left'); - expect(getDropzonePosition(dropzoneElem)).toBe('left'); - }); - test('get position of dropzone on the right', () => { - dropzoneElem.setAttribute('data-dropzone-position', 'right'); - expect(getDropzonePosition(dropzoneElem)).toBe('right'); - }); -}); - -describe('Testing getWireElementText', () => { - let svgElem: SVGElement; - let groupElem: SVGGElement; - let textElem: SVGGElement; - beforeEach(() => { - svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg') as SVGElement; - groupElem = document.createElementNS('http://www.w3.org/2000/svg', 'g') as SVGGElement; - textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text') as SVGTextElement; - groupElem.append(textElem); - svgElem.append(groupElem); - }); - test('text element not exists', () => { - textElem.remove(); - expect(() => getWireElemText(groupElem)).toThrowError('Text not found'); - }); - test('get text element without textContent', () => { - expect(() => getWireElemText(groupElem)).toThrowError('Text not found'); - }); - test('get text element empty textContent', () => { - expect(() => getWireElemText(groupElem)).toThrowError('Text not found'); - }); - test('should return q0', () => { - textElem.textContent = 'q0'; - expect(getWireElemText(groupElem)).toEqual('q0'); - }); - test('should return q1', () => { - textElem.textContent = 'q1'; - expect(getWireElemText(groupElem)).toEqual('q1'); - }); -}); - -describe('Testing getWireElemY', () => { - let svgElem: SVGElement; - let groupElem: SVGGElement; - let lineElem: SVGGElement; - beforeEach(() => { - svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg') as SVGElement; - groupElem = document.createElementNS('http://www.w3.org/2000/svg', 'g') as SVGGElement; - lineElem = document.createElementNS('http://www.w3.org/2000/svg', 'line') as SVGLineElement; - groupElem.append(lineElem); - svgElem.append(groupElem); - }); - test('line element not exists', () => { - lineElem.remove(); - expect(() => getWireElemY(groupElem)).toThrowError('y not found'); - }); - test('get y element without y value', () => { - expect(() => getWireElemY(groupElem)).toThrowError('y not found'); - }); - test('get text element empty textContent', () => { - expect(() => getWireElemY(groupElem)).toThrowError('y not found'); - }); - test('should return 40', () => { - lineElem.setAttribute('y1', '40'); - expect(getWireElemY(groupElem)).toEqual(40); - }); - test('should return 99', () => { - lineElem.setAttribute('y1', '99'); - expect(getWireElemY(groupElem)).toEqual(99); - }); -}); - -describe('Testing getParent', () => { - test('with level 0 gate', () => { - const operations = [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ]; - expect(getParent('0', operations)).toStrictEqual([ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ]); - }); - test('with level 1 gate', () => { - const operations = [ - { - gate: 'Foo', - conditionalRender: 3, - targets: [{ qId: 0 }, { qId: 1 }], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - }, - { - gate: 'RX', - displayArgs: '(0.25)', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 0 }], - }, - ], - }, - { - gate: 'X', - targets: [{ qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 2 }, { qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }, { qId: 3 }], - targets: [{ qId: 1 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }, { qId: 3 }], - targets: [{ qId: 2 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'measure', - isMeasurement: true, - controls: [{ qId: 0 }], - targets: [{ type: 1, qId: 0, cId: 0 }], - }, - { - gate: 'ApplyIfElseR', - isConditional: true, - controls: [{ type: 1, qId: 0, cId: 0 }], - targets: [], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - conditionalRender: 2, - }, - { - gate: 'Foo', - targets: [{ qId: 3 }], - conditionalRender: 2, - }, - ], - }, - { - gate: 'SWAP', - targets: [{ qId: 0 }, { qId: 2 }], - children: [ - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - ], - }, - { - gate: 'ZZ', - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'ZZ', - targets: [{ qId: 0 }, { qId: 1 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }, { qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - ]; - expect(getParent('0-1', operations)).toStrictEqual([ - { - gate: 'H', - targets: [{ qId: 1 }], - }, - { - gate: 'RX', - displayArgs: '(0.25)', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 0 }], - }, - ]); - }); -}); - -describe('Testing getGate', () => { - test('should return H gate', () => { - const operations = [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ]; - expect(getGate('0', operations)).toStrictEqual({ - gate: 'H', - targets: [{ qId: 0 }], - }); - }); - test('should return X gate', () => { - const operations = [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ]; - expect(getGate('1', operations)).toStrictEqual({ - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }); - }); - test('should return RX', () => { - const operations = [ - { - gate: 'Foo', - conditionalRender: 3, - targets: [{ qId: 0 }, { qId: 1 }], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - }, - { - gate: 'RX', - displayArgs: '(0.25)', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 0 }], - }, - ], - }, - { - gate: 'X', - targets: [{ qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 2 }, { qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }, { qId: 3 }], - targets: [{ qId: 1 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }, { qId: 3 }], - targets: [{ qId: 2 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'measure', - isMeasurement: true, - controls: [{ qId: 0 }], - targets: [{ type: 1, qId: 0, cId: 0 }], - }, - { - gate: 'ApplyIfElseR', - isConditional: true, - controls: [{ type: 1, qId: 0, cId: 0 }], - targets: [], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - conditionalRender: 2, - }, - { - gate: 'Foo', - targets: [{ qId: 3 }], - conditionalRender: 2, - }, - ], - }, - { - gate: 'SWAP', - targets: [{ qId: 0 }, { qId: 2 }], - children: [ - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - ], - }, - { - gate: 'ZZ', - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'ZZ', - targets: [{ qId: 0 }, { qId: 1 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }, { qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - ]; - expect(getGate('0-1', operations)).toStrictEqual({ - gate: 'RX', - displayArgs: '(0.25)', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 0 }], - }); - }); -}); - -describe('Testing addDocumentEvents', () => { - test('verify document events', () => { - const container = document.createElement('div'); - expect(container).toMatchSnapshot(); - addDocumentEvents(container); - expect(container).toMatchSnapshot(); - }); -}); - -describe('Testing handleGateMouseDown', () => { - test('copying, ctrlKey is true', () => { - const container = document.createElement('div'); - const ev = new MouseEvent('mousedown', { ctrlKey: true }); - handleGateMouseDown(ev, container); - expect(container).toMatchSnapshot(); - }); - test('moving, ctrlKey is false', () => { - const container = document.createElement('div'); - const ev = new MouseEvent('mousedown', { ctrlKey: false }); - handleGateMouseDown(ev, container); - expect(container).toMatchSnapshot(); - }); -}); - -describe('Testing getGateElems', () => { - test('get 2 gates', () => { - const container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - draw(circuit, container, STYLES['default']); - const gateElems = getGateElems(container); - expect(gateElems).toHaveLength(2); - expect(gateElems).toMatchSnapshot(); - }); - test('get 3 gates', () => { - const container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - draw(circuit, container, STYLES['default']); - const gateElems = getGateElems(container); - expect(gateElems).toHaveLength(3); - expect(gateElems).toMatchSnapshot(); - }); -}); - -describe('Testing getWireElems', () => { - test('get 2 wires', () => { - const container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - draw(circuit, container, STYLES['default']); - const wireElems = getWireElems(container); - expect(wireElems).toHaveLength(2); - expect(wireElems).toMatchSnapshot(); - }); -}); - -describe('Testing createDropzone', () => { - test('create dropzone on the left', () => { - expect(createDropzone(0, 0, 20, 20, '0', 'left')).toMatchSnapshot(); - }); - test('create dropzone on the right', () => { - expect(createDropzone(0, 0, 20, 20, '0', 'right')).toMatchSnapshot(); - }); -}); - -describe('Testing createLeftDropzone', () => { - test('create left dropzone', () => { - expect(createLeftDropzone(0, 0, 20, '0')).toMatchSnapshot(); - }); -}); - -describe('Testing createRightDropzone', () => { - test('create dropzone right', () => { - expect(createRightDropzone(0, 0, 20, 20, '0')).toMatchSnapshot(); - }); -}); - -describe('Testing getClosestWireY', () => { - test('should return 40', () => { - const container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - const wires = { '40': 'q0', '100': 'q1' }; - draw(circuit, container, STYLES['default']); - expect(getClosestWireY(50, wires)).toEqual(40); - }); - test('should return 100', () => { - const container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - const wires = { '40': 'q0', '100': 'q1' }; - draw(circuit, container, STYLES['default']); - expect(getClosestWireY(85, wires)).toEqual(100); - }); - test('should return null', () => { - const container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - const wires = { '40': 'q0', '100': 'q1' }; - draw(circuit, container, STYLES['default']); - expect(getClosestWireY(120, wires)).toEqual(null); - }); -}); - -describe('test getWireElemsY', () => { - test('get 2 wires', () => { - const container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - const expected = { '40': 'q0', '100': 'q1' }; - draw(circuit, container, STYLES['default']); - expect(getWireElemsY(container)).toStrictEqual(expected); - }); - test('get 4 wires', () => { - const container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], - operations: [ - { - gate: 'Foo', - conditionalRender: 3, - targets: [{ qId: 0 }, { qId: 1 }], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - }, - { - gate: 'RX', - displayArgs: '(0.25)', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 0 }], - }, - ], - }, - { - gate: 'X', - targets: [{ qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 2 }, { qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }, { qId: 3 }], - targets: [{ qId: 1 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }, { qId: 3 }], - targets: [{ qId: 2 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'measure', - isMeasurement: true, - controls: [{ qId: 0 }], - targets: [{ type: 1, qId: 0, cId: 0 }], - }, - { - gate: 'ApplyIfElseR', - isConditional: true, - controls: [{ type: 1, qId: 0, cId: 0 }], - targets: [], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - conditionalRender: 2, - }, - { - gate: 'Foo', - targets: [{ qId: 3 }], - conditionalRender: 2, - }, - ], - }, - { - gate: 'SWAP', - targets: [{ qId: 0 }, { qId: 2 }], - children: [ - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - ], - }, - { - gate: 'ZZ', - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'ZZ', - targets: [{ qId: 0 }, { qId: 1 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }, { qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - ], - }; - const expected = { '40': 'q0', '120': 'q1', '180': 'q2', '240': 'q3' }; - draw(circuit, container, STYLES['default']); - expect(getWireElemsY(container)).toStrictEqual(expected); - }); -}); - -describe('Testing addDropzoneEvents', () => { - interface Context { - container: HTMLElement; - operations: Operation[]; - wires: Wires; - renderFn: () => void; - } - - interface Wires { - [y: string]: string; - } - - test('add 1 event', () => { - const container = document.createElement('div'); - const svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - const dropzoneElem = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); - svgElem.append(dropzoneElem); - container.append(svgElem); - - const context: Context = { - container: container, - operations: [], - wires: {}, - renderFn: () => { - return; - }, - }; - addDropzoneEvents(context); - expect(container).toMatchSnapshot(); - }); - test('add 2 events', () => { - const container = document.createElement('div'); - const svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - const dropzoneElem = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); - const dropzoneElem1 = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); - svgElem.append(dropzoneElem); - svgElem.append(dropzoneElem1); - container.append(svgElem); - interface Context { - container: HTMLElement; - operations: Operation[]; - wires: Wires; - renderFn: () => void; - } - - const context: Context = { - container: container, - operations: [], - wires: {}, - renderFn: () => { - return; - }, - }; - addDropzoneEvents(context); - expect(container).toMatchSnapshot(); - }); -}); - -describe('Testing addMouseEvents', () => { - interface Context { - container: HTMLElement; - operations: Operation[]; - wires: Wires; - renderFn: () => void; - } - interface Wires { - [y: string]: string; - } - test('verify mouse events', () => { - const container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - draw(circuit, container, STYLES['default']); - const context: Context = { - container: container, - operations: [], - wires: {}, - renderFn: () => { - return; - }, - }; - const svgElem = container.querySelector('svg'); - if (svgElem != null) svgElem.removeAttribute('id'); - addMouseEvents(context); - expect(container).toMatchSnapshot(); - }); -}); - -describe('Testing getRenderFn', () => { - test('check console.log displaying "onCircuitChange is triggered"', () => { +describe('Test _center', () => { + test('should return {25,50}', () => { Object.defineProperty(window.SVGElement.prototype, 'getBBox', { writable: true, value: () => ({ x: 0, y: 0, - width: 0, - height: 0, + width: 50, + height: 100, }), }); - const container = document.createElement('div'); - const circuit: Circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - const sqore = new Sqore(circuit, STYLES['default']); - const onCircuitChange = () => console.log('onCircuitChange is triggered'); - const renderFn = getRenderFn(container, sqore, onCircuitChange); - - jest.spyOn(console, 'log'); - renderFn(); - expect(console.log).toHaveBeenCalledWith('onCircuitChange is triggered'); + const elem = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + expect(_center(elem)).toStrictEqual({ cX: 25, cY: 50 }); }); -}); - -describe('Testing addDropzones', () => { - test('verify dropzones', () => { + test('should return {105,210}', () => { Object.defineProperty(window.SVGElement.prototype, 'getBBox', { writable: true, value: () => ({ - x: 0, - y: 0, - width: 0, - height: 0, + x: 100, + y: 200, + width: 10, + height: 20, }), }); - const container = document.createElement('div'); - const circuit: Circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - draw(circuit, container, STYLES['default'], 0, true); - const svgElem = container.querySelector('svg'); - if (svgElem != null) svgElem.removeAttribute('id'); - addDropzones(container); - expect(container).toMatchSnapshot(); + const elem = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + expect(_center(elem)).toStrictEqual({ cX: 105, cY: 210 }); + }); +}); + +describe('Test _lastIndex', () => { + test('"" should return undefined', () => { + expect(_lastIndex('')).toBeUndefined(); + }); + test('"0-0-1" should return 1', () => { + expect(_lastIndex('0-0-1')).toEqual(1); + }); + test('"1-0-5" should return [1,0,5]', () => { + expect(_lastIndex('1-0-5')).toEqual(5); + }); +}); + +describe('Test _indexes', () => { + test('"" should return []', () => { + expect(_indexes('')).toStrictEqual([]); + }); + test('"0-0-1" should return [0,0,1]', () => { + expect(_indexes('0-0-1')).toStrictEqual([0, 0, 1]); + }); + test('"1-0-1" should return [1,0,1]', () => { + expect(_indexes('1-0-1')).toStrictEqual([1, 0, 1]); }); }); diff --git a/src/editable.ts b/src/editable.ts index befbf36f..9ef55d13 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -370,9 +370,12 @@ const _circularMod = (value: number, offset: number, total: number) => { return (((value + offset) % total) + total) % total; }; -const _indexes = (dataId: string) => dataId.split('-').map((segment) => parseInt(segment)); +const _indexes = (dataId: string): number[] => + dataId !== '' // + ? dataId.split('-').map((segment) => parseInt(segment)) + : []; -const _lastIndex = (dataId: string) => { +const _lastIndex = (dataId: string): number | undefined => { return _indexes(dataId).pop(); }; @@ -387,6 +390,6 @@ const _renderFn = ( }; }; -const exportedForTesting = {}; +const exportedForTesting = { _center, _indexes, _lastIndex }; export { addEditable, exportedForTesting }; From 4b22f075373e9096f70d1346049f4c8e90a49610 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 13:43:38 -0400 Subject: [PATCH 032/108] Add tests for _center, _wireData --- __tests__/editable.test.ts | 58 +++++++++++++++++++++++++++++++++++++- src/editable.ts | 8 +++--- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 209f21bd..66874c99 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -2,8 +2,9 @@ // Licensed under the MIT license. import { exportedForTesting } from '../src/editable'; +import { draw, STYLES } from '../src/index'; -const { _indexes, _lastIndex, _center } = exportedForTesting; +const { _center, _wireData, _indexes, _lastIndex } = exportedForTesting; describe('Test _center', () => { test('should return {25,50}', () => { @@ -34,6 +35,61 @@ describe('Test _center', () => { }); }); +describe('Test _wireData', () => { + test('2 wires should return [40,100]', () => { + const container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + draw(circuit, container, STYLES['default']); + expect(_wireData(container)).toStrictEqual([40, 100]); + }); + test('3 wires should return [40,100, 180]', () => { + const container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }, { id: 2 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 2 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + draw(circuit, container, STYLES['default']); + expect(_wireData(container)).toStrictEqual([40, 100, 180]); + }); +}); + describe('Test _lastIndex', () => { test('"" should return undefined', () => { expect(_lastIndex('')).toBeUndefined(); diff --git a/src/editable.ts b/src/editable.ts index 9ef55d13..679de361 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -87,7 +87,7 @@ const _wirePrefixes = (wireData: number[]) => wireData.map((wireY, index) => ({ /** * Find center point of element */ -const _center = (elem: SVGGraphicsElement) => { +const _center = (elem: SVGGraphicsElement): { cX: number; cY: number } => { const { x, y, width, height } = elem.getBBox(); return { cX: x + width / 2, cY: y + height / 2 }; }; @@ -161,7 +161,7 @@ const _dropzoneLayer = (context: Context) => { return dropzoneLayer; }; -const _wireData = (container: HTMLElement) => { +const _wireData = (container: HTMLElement): number[] => { // elems include qubit wires and lines of measure gates const elems = container.querySelectorAll<SVGGElement>('svg > g:nth-child(3) > g'); // filter out <g> elements having more than 2 elements because @@ -170,7 +170,7 @@ const _wireData = (container: HTMLElement) => { const wireElems = Array.from(elems).filter((elem) => elem.childElementCount < 3); const wireData = wireElems.map((wireElem) => { const lineElem = wireElem.children[0] as SVGLineElement; - return lineElem.y1.baseVal.value; + return Number(lineElem.getAttribute('y1')); }); return wireData; }; @@ -390,6 +390,6 @@ const _renderFn = ( }; }; -const exportedForTesting = { _center, _indexes, _lastIndex }; +const exportedForTesting = { _center, _wireData, _indexes, _lastIndex }; export { addEditable, exportedForTesting }; From d975f8863c433c5dedd7ec4dfc9a8787277ca3fc Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 15:30:25 -0400 Subject: [PATCH 033/108] Add tests for _equivOperation, _equivOperationParent --- __tests__/__snapshots__/editable.test.ts.snap | 100 ++++++++++ __tests__/editable.test.ts | 184 +++++++++++++++++- src/editable.ts | 9 +- 3 files changed, 287 insertions(+), 6 deletions(-) create mode 100644 __tests__/__snapshots__/editable.test.ts.snap diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap new file mode 100644 index 00000000..6dd2e3a4 --- /dev/null +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -0,0 +1,100 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test _equivOperation should return H gate 1`] = ` +Object { + "gate": "H", + "targets": Array [ + Object { + "qId": 0, + }, + ], +} +`; + +exports[`Test _equivOperation should return X gate 1`] = ` +Object { + "controls": Array [ + Object { + "qId": 0, + }, + ], + "gate": "X", + "isControlled": true, + "targets": Array [ + Object { + "qId": 1, + }, + ], +} +`; + +exports[`Test _equivOperationParent should return Foo 1`] = ` +Array [ + Object { + "gate": "H", + "targets": Array [ + Object { + "qId": 1, + }, + ], + }, + Object { + "controls": Array [ + Object { + "qId": 1, + }, + ], + "displayArgs": "(0.25)", + "gate": "RX", + "isControlled": true, + "targets": Array [ + Object { + "qId": 0, + }, + ], + }, +] +`; + +exports[`Test _equivOperationParent should return all operations 1`] = ` +Array [ + Object { + "gate": "H", + "targets": Array [ + Object { + "qId": 0, + }, + ], + }, + Object { + "controls": Array [ + Object { + "qId": 0, + }, + ], + "gate": "X", + "isControlled": true, + "targets": Array [ + Object { + "qId": 1, + }, + ], + }, + Object { + "controls": Array [ + Object { + "qId": 1, + }, + ], + "gate": "Measure", + "isMeasurement": true, + "targets": Array [ + Object { + "cId": 0, + "qId": 1, + "type": 1, + }, + ], + }, +] +`; diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 66874c99..102fbc10 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -4,7 +4,7 @@ import { exportedForTesting } from '../src/editable'; import { draw, STYLES } from '../src/index'; -const { _center, _wireData, _indexes, _lastIndex } = exportedForTesting; +const { _center, _wireData, _equivOperation, _equivOperationParent, _indexes, _lastIndex } = exportedForTesting; describe('Test _center', () => { test('should return {25,50}', () => { @@ -90,6 +90,188 @@ describe('Test _wireData', () => { }); }); +describe('Test _equivOperation', () => { + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + test('should return H gate', () => { + expect(_equivOperation('0', circuit.operations)).toMatchSnapshot(); + }); + test('should return X gate', () => { + expect(_equivOperation('1', circuit.operations)).toMatchSnapshot(); + }); +}); + +describe('Test _equivOperationParent', () => { + test('should return Foo', () => { + const circuit = { + qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], + operations: [ + { + gate: 'Foo', + conditionalRender: 3, + targets: [{ qId: 0 }, { qId: 1 }], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + }, + { + gate: 'RX', + displayArgs: '(0.25)', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 0 }], + }, + ], + }, + { + gate: 'X', + targets: [{ qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 2 }, { qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }, { qId: 3 }], + targets: [{ qId: 1 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }, { qId: 3 }], + targets: [{ qId: 2 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'measure', + isMeasurement: true, + controls: [{ qId: 0 }], + targets: [{ type: 1, qId: 0, cId: 0 }], + }, + { + gate: 'ApplyIfElseR', + isConditional: true, + controls: [{ type: 1, qId: 0, cId: 0 }], + targets: [], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + conditionalRender: 2, + }, + { + gate: 'Foo', + targets: [{ qId: 3 }], + conditionalRender: 2, + }, + ], + }, + { + gate: 'SWAP', + targets: [{ qId: 0 }, { qId: 2 }], + children: [ + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + ], + }, + { + gate: 'ZZ', + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'ZZ', + targets: [{ qId: 0 }, { qId: 1 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }, { qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + ], + }; + expect(_equivOperationParent('0-1', circuit.operations)).toMatchSnapshot(); + }); + test('should return all operations', () => { + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + expect(_equivOperationParent('0', circuit.operations)).toMatchSnapshot(); + }); +}); + describe('Test _lastIndex', () => { test('"" should return undefined', () => { expect(_lastIndex('')).toBeUndefined(); diff --git a/src/editable.ts b/src/editable.ts index 679de361..90129440 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -71,7 +71,7 @@ const _addDataWires = (container: HTMLElement) => { * i.e. Gate 'Foo' spans on wire 0 (y=40), 1 (y=100), and 2 (y=140). * Function returns [40, 100, 140] */ -const _elemWires = (elem: SVGGraphicsElement, wireData: number[]) => { +const _elemWireYs = (elem: SVGGraphicsElement, wireData: number[]) => { const { y, height } = elem.getBBox(); return wireData.filter((wireY) => wireY > y && wireY < y + height); }; @@ -129,9 +129,9 @@ const _dropzoneLayer = (context: Context) => { } else { // Let group gates creating dropzones for each wire const { x } = elem.getBBox(); - const elemWires = _elemWires(elem, wireData); + const elemWireYs = _elemWireYs(elem, wireData); - elemWires.map((wireY) => { + elemWireYs.map((wireY) => { const wirePrefix = wirePrefixes.find((item) => item.wireY === wireY); if (wirePrefix) { const prefixX = wirePrefix.prefixX; @@ -144,7 +144,6 @@ const _dropzoneLayer = (context: Context) => { dropzoneLayer.appendChild(elemDropzone); } }); - console.log({ elem, x, elemWires }); } }); @@ -390,6 +389,6 @@ const _renderFn = ( }; }; -const exportedForTesting = { _center, _wireData, _indexes, _lastIndex }; +const exportedForTesting = { _center, _wireData, _equivOperation, _equivOperationParent, _indexes, _lastIndex }; export { addEditable, exportedForTesting }; From 5daff513fa1ce9804a3ff374487443014c95d74e Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 15:45:50 -0400 Subject: [PATCH 034/108] Add tests for _moveX, _copyX --- __tests__/__snapshots__/editable.test.ts.snap | 188 ++++++++++++++++++ __tests__/editable.test.ts | 75 ++++++- src/editable.ts | 19 +- 3 files changed, 275 insertions(+), 7 deletions(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 6dd2e3a4..700b6219 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -1,5 +1,107 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Test _copyX copy elem from index 0 to index 1 1`] = ` +Array [ + Object { + "gate": "H", + "targets": Array [ + Object { + "qId": 0, + }, + ], + }, + Object { + "controls": Array [ + Object { + "qId": 0, + }, + ], + "gate": "X", + "isControlled": true, + "targets": Array [ + Object { + "qId": 1, + }, + ], + }, + Object { + "gate": "H", + "targets": Array [ + Object { + "qId": 0, + }, + ], + }, + Object { + "controls": Array [ + Object { + "qId": 1, + }, + ], + "gate": "Measure", + "isMeasurement": true, + "targets": Array [ + Object { + "cId": 0, + "qId": 1, + "type": 1, + }, + ], + }, +] +`; + +exports[`Test _copyX copy elem from index 0 to last 1`] = ` +Array [ + Object { + "gate": "H", + "targets": Array [ + Object { + "qId": 0, + }, + ], + }, + Object { + "controls": Array [ + Object { + "qId": 0, + }, + ], + "gate": "X", + "isControlled": true, + "targets": Array [ + Object { + "qId": 1, + }, + ], + }, + Object { + "controls": Array [ + Object { + "qId": 1, + }, + ], + "gate": "Measure", + "isMeasurement": true, + "targets": Array [ + Object { + "cId": 0, + "qId": 1, + "type": 1, + }, + ], + }, + Object { + "gate": "H", + "targets": Array [ + Object { + "qId": 0, + }, + ], + }, +] +`; + exports[`Test _equivOperation should return H gate 1`] = ` Object { "gate": "H", @@ -98,3 +200,89 @@ Array [ }, ] `; + +exports[`Test _moveX move elem from index 0 to index 1 1`] = ` +Array [ + Object { + "controls": Array [ + Object { + "qId": 0, + }, + ], + "gate": "X", + "isControlled": true, + "targets": Array [ + Object { + "qId": 1, + }, + ], + }, + Object { + "gate": "H", + "targets": Array [ + Object { + "qId": 0, + }, + ], + }, + Object { + "controls": Array [ + Object { + "qId": 1, + }, + ], + "gate": "Measure", + "isMeasurement": true, + "targets": Array [ + Object { + "cId": 0, + "qId": 1, + "type": 1, + }, + ], + }, +] +`; + +exports[`Test _moveX move elem from index 0 to last 1`] = ` +Array [ + Object { + "controls": Array [ + Object { + "qId": 0, + }, + ], + "gate": "X", + "isControlled": true, + "targets": Array [ + Object { + "qId": 1, + }, + ], + }, + Object { + "controls": Array [ + Object { + "qId": 1, + }, + ], + "gate": "Measure", + "isMeasurement": true, + "targets": Array [ + Object { + "cId": 0, + "qId": 1, + "type": 1, + }, + ], + }, + Object { + "gate": "H", + "targets": Array [ + Object { + "qId": 0, + }, + ], + }, +] +`; diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 102fbc10..d8f38394 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -2,9 +2,10 @@ // Licensed under the MIT license. import { exportedForTesting } from '../src/editable'; -import { draw, STYLES } from '../src/index'; +import { Circuit, draw, STYLES } from '../src/index'; -const { _center, _wireData, _equivOperation, _equivOperationParent, _indexes, _lastIndex } = exportedForTesting; +const { _center, _wireData, _equivOperation, _equivOperationParent, _moveX, _copyX, _indexes, _lastIndex } = + exportedForTesting; describe('Test _center', () => { test('should return {25,50}', () => { @@ -272,6 +273,76 @@ describe('Test _equivOperationParent', () => { }); }); +describe('Test _moveX', () => { + let circuit: Circuit; + beforeEach(() => { + circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + }); + test('move elem from index 0 to index 1', () => { + _moveX('0', '2', circuit.operations); + expect(circuit.operations).toMatchSnapshot(); + }); + test('move elem from index 0 to last', () => { + _moveX('0', '3', circuit.operations); + expect(circuit.operations).toMatchSnapshot(); + }); +}); + +describe('Test _copyX', () => { + let circuit: Circuit; + beforeEach(() => { + circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + }); + test('copy elem from index 0 to index 1', () => { + _copyX('0', '2', circuit.operations); + expect(circuit.operations).toMatchSnapshot(); + }); + test('copy elem from index 0 to last', () => { + _copyX('0', '3', circuit.operations); + expect(circuit.operations).toMatchSnapshot(); + }); +}); + describe('Test _lastIndex', () => { test('"" should return undefined', () => { expect(_lastIndex('')).toBeUndefined(); diff --git a/src/editable.ts b/src/editable.ts index 90129440..d3639ab8 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -282,7 +282,7 @@ const _equivOperation = (dataId: string | null, operations: Operation[]): Operat return operationParent[index]; }; -const _moveX = (sourceId: string, targetId: string, operations: Operation[]) => { +const _moveX = (sourceId: string, targetId: string, operations: Operation[]): Operation | null => { if (sourceId === targetId) return _equivOperation(sourceId, operations); const sourceOperation = _equivOperation(sourceId, operations); const sourceOperationParent = _equivOperationParent(sourceId, operations); @@ -295,7 +295,7 @@ const _moveX = (sourceId: string, targetId: string, operations: Operation[]) => sourceOperation == null || sourceOperationParent == null ) - return; + return null; // Insert sourceOperation to target last index const newSourceOperation: Operation = { ...sourceOperation }; @@ -309,7 +309,7 @@ const _moveX = (sourceId: string, targetId: string, operations: Operation[]) => return newSourceOperation; }; -const _copyX = (sourceId: string, targetId: string, operations: Operation[]) => { +const _copyX = (sourceId: string, targetId: string, operations: Operation[]): Operation | null => { if (sourceId === targetId) return _equivOperation(sourceId, operations); const sourceOperation = _equivOperation(sourceId, operations); const sourceOperationParent = _equivOperationParent(sourceId, operations); @@ -322,7 +322,7 @@ const _copyX = (sourceId: string, targetId: string, operations: Operation[]) => sourceOperation == null || sourceOperationParent == null ) - return; + return null; // Insert sourceOperation to target last index const newSourceOperation: Operation = JSON.parse(JSON.stringify(sourceOperation)); @@ -389,6 +389,15 @@ const _renderFn = ( }; }; -const exportedForTesting = { _center, _wireData, _equivOperation, _equivOperationParent, _indexes, _lastIndex }; +const exportedForTesting = { + _center, + _wireData, + _equivOperation, + _equivOperationParent, + _moveX, + _copyX, + _indexes, + _lastIndex, +}; export { addEditable, exportedForTesting }; From 1c1d07379181951488a1d491df0abf9b3eb1706c Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 18:02:23 -0400 Subject: [PATCH 035/108] Add tests for _circularMod --- __tests__/editable.test.ts | 25 +++++++++++++++++++++++-- src/editable.ts | 15 ++++++++------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index d8f38394..bc8de679 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -4,8 +4,17 @@ import { exportedForTesting } from '../src/editable'; import { Circuit, draw, STYLES } from '../src/index'; -const { _center, _wireData, _equivOperation, _equivOperationParent, _moveX, _copyX, _indexes, _lastIndex } = - exportedForTesting; +const { + _center, + _wireData, + _equivOperation, + _equivOperationParent, + _moveX, + _copyX, + _circularMod, + _indexes, + _lastIndex, +} = exportedForTesting; describe('Test _center', () => { test('should return {25,50}', () => { @@ -343,6 +352,18 @@ describe('Test _copyX', () => { }); }); +describe('Test _circularMod', () => { + test('should return 2', () => { + expect(_circularMod(5, 1, 4)).toEqual(2); + }); + test('should return 1', () => { + expect(_circularMod(100, 1, 2)).toEqual(1); + }); + test('should return 3', () => { + expect(_circularMod(3, 0, 4)).toEqual(3); + }); +}); + describe('Test _lastIndex', () => { test('"" should return undefined', () => { expect(_lastIndex('')).toBeUndefined(); diff --git a/src/editable.ts b/src/editable.ts index d3639ab8..8a78647a 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -336,28 +336,28 @@ const _moveY = (sourceWire: string, targetWire: string, operation: Operation, wi _offsetRecursively(offset, operation, wireData); }; -const _offsetRecursively = (offsetY: number, operation: Operation, wireData: number[]) => { +const _offsetRecursively = (offset: number, operation: Operation, wireData: number[]) => { const wireDataSize = wireData.length; // Offset all targets by offsetY value if (operation.targets != null) { operation.targets.forEach((target) => { - target.qId = _circularMod(target.qId, offsetY, wireDataSize); - if (target.cId) target.cId = _circularMod(target.cId, offsetY, wireDataSize); + target.qId = _circularMod(target.qId, offset, wireDataSize); + if (target.cId) target.cId = _circularMod(target.cId, offset, wireDataSize); }); } // Offset all controls by offsetY value if (operation.controls != null) { operation.controls.forEach((control) => { - control.qId = _circularMod(control.qId, offsetY, wireDataSize); - if (control.cId) control.cId = _circularMod(control.qId, offsetY, wireDataSize); + control.qId = _circularMod(control.qId, offset, wireDataSize); + if (control.cId) control.cId = _circularMod(control.qId, offset, wireDataSize); }); } // Offset recursively through all children if (operation.children != null) { - operation.children.forEach((child) => _offsetRecursively(offsetY, child, wireData)); + operation.children.forEach((child) => _offsetRecursively(offset, child, wireData)); } }; @@ -365,7 +365,7 @@ const _offsetRecursively = (offsetY: number, operation: Operation, wireData: num * This modulo function always returns positive value based on total. * i.e: value=0, offset=-1, total=4 returns 3 instead of -1 */ -const _circularMod = (value: number, offset: number, total: number) => { +const _circularMod = (value: number, offset: number, total: number): number => { return (((value + offset) % total) + total) % total; }; @@ -396,6 +396,7 @@ const exportedForTesting = { _equivOperationParent, _moveX, _copyX, + _circularMod, _indexes, _lastIndex, }; From 2b36d737f50f7bdfa3ad3154ad98be70303207d7 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 18:18:23 -0400 Subject: [PATCH 036/108] Add tests for _offsetRecursively --- __tests__/editable.test.ts | 27 ++++++++++++++++++++++++++- src/editable.ts | 17 ++++++++--------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index bc8de679..ccdb33b5 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. import { exportedForTesting } from '../src/editable'; -import { Circuit, draw, STYLES } from '../src/index'; +import { Circuit, draw, Operation, STYLES } from '../src/index'; const { _center, @@ -11,6 +11,7 @@ const { _equivOperationParent, _moveX, _copyX, + _offsetRecursively, _circularMod, _indexes, _lastIndex, @@ -352,6 +353,30 @@ describe('Test _copyX', () => { }); }); +describe('Test _offsetRecursively', () => { + let operation: Operation; + beforeEach(() => { + operation = { + gate: 'ZZ', + targets: [{ qId: 1 }, { qId: 3 }], + }; + }); + test('offset by 1', () => { + _offsetRecursively(operation, 1, 4); + expect(operation).toStrictEqual({ + gate: 'ZZ', + targets: [{ qId: 2 }, { qId: 0 }], + }); + }); + test('offset by 2', () => { + _offsetRecursively(operation, 2, 4); + expect(operation).toStrictEqual({ + gate: 'ZZ', + targets: [{ qId: 3 }, { qId: 1 }], + }); + }); +}); + describe('Test _circularMod', () => { test('should return 2', () => { expect(_circularMod(5, 1, 4)).toEqual(2); diff --git a/src/editable.ts b/src/editable.ts index 8a78647a..18c97c06 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -333,31 +333,29 @@ const _copyX = (sourceId: string, targetId: string, operations: Operation[]): Op const _moveY = (sourceWire: string, targetWire: string, operation: Operation, wireData: number[]) => { const offset = parseInt(targetWire) - parseInt(sourceWire); - _offsetRecursively(offset, operation, wireData); + _offsetRecursively(operation, offset, wireData.length); }; -const _offsetRecursively = (offset: number, operation: Operation, wireData: number[]) => { - const wireDataSize = wireData.length; - +const _offsetRecursively = (operation: Operation, wireOffset: number, totalWires: number): void => { // Offset all targets by offsetY value if (operation.targets != null) { operation.targets.forEach((target) => { - target.qId = _circularMod(target.qId, offset, wireDataSize); - if (target.cId) target.cId = _circularMod(target.cId, offset, wireDataSize); + target.qId = _circularMod(target.qId, wireOffset, totalWires); + if (target.cId) target.cId = _circularMod(target.cId, wireOffset, totalWires); }); } // Offset all controls by offsetY value if (operation.controls != null) { operation.controls.forEach((control) => { - control.qId = _circularMod(control.qId, offset, wireDataSize); - if (control.cId) control.cId = _circularMod(control.qId, offset, wireDataSize); + control.qId = _circularMod(control.qId, wireOffset, totalWires); + if (control.cId) control.cId = _circularMod(control.qId, wireOffset, totalWires); }); } // Offset recursively through all children if (operation.children != null) { - operation.children.forEach((child) => _offsetRecursively(offset, child, wireData)); + operation.children.forEach((child) => _offsetRecursively(child, wireOffset, totalWires)); } }; @@ -396,6 +394,7 @@ const exportedForTesting = { _equivOperationParent, _moveX, _copyX, + _offsetRecursively, _circularMod, _indexes, _lastIndex, From 6e2776c41b00f36a160f292c05e0625049822248 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 18:27:06 -0400 Subject: [PATCH 037/108] Add tests for _moveY --- __tests__/editable.test.ts | 25 +++++++++++++++++++++++++ src/editable.ts | 12 ++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index ccdb33b5..40244c02 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -11,6 +11,7 @@ const { _equivOperationParent, _moveX, _copyX, + _moveY, _offsetRecursively, _circularMod, _indexes, @@ -353,6 +354,30 @@ describe('Test _copyX', () => { }); }); +describe('Test _moveY', () => { + let operation: Operation; + beforeEach(() => { + operation = { + gate: 'ZZ', + targets: [{ qId: 1 }, { qId: 3 }], + }; + }); + test('offset by 1', () => { + _moveY('1', '2', operation, 4); + expect(operation).toStrictEqual({ + gate: 'ZZ', + targets: [{ qId: 2 }, { qId: 0 }], + }); + }); + test('offset by -3', () => { + _moveY('3', '0', operation, 4); + expect(operation).toStrictEqual({ + gate: 'ZZ', + targets: [{ qId: 2 }, { qId: 0 }], + }); + }); +}); + describe('Test _offsetRecursively', () => { let operation: Operation; beforeEach(() => { diff --git a/src/editable.ts b/src/editable.ts index 18c97c06..47b6e080 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -246,7 +246,7 @@ const _addEvents = (context: Context) => { : _moveX(context.selectedId, targetId, operations); if (newSourceOperation != null) { - _moveY(context.selectedWire, targetWire, newSourceOperation, context.wireData); + _moveY(context.selectedWire, targetWire, newSourceOperation, context.wireData.length); } renderFn(); @@ -331,12 +331,13 @@ const _copyX = (sourceId: string, targetId: string, operations: Operation[]): Op return newSourceOperation; }; -const _moveY = (sourceWire: string, targetWire: string, operation: Operation, wireData: number[]) => { +const _moveY = (sourceWire: string, targetWire: string, operation: Operation, totalWires: number): Operation => { const offset = parseInt(targetWire) - parseInt(sourceWire); - _offsetRecursively(operation, offset, wireData.length); + _offsetRecursively(operation, offset, totalWires); + return operation; }; -const _offsetRecursively = (operation: Operation, wireOffset: number, totalWires: number): void => { +const _offsetRecursively = (operation: Operation, wireOffset: number, totalWires: number): Operation => { // Offset all targets by offsetY value if (operation.targets != null) { operation.targets.forEach((target) => { @@ -357,6 +358,8 @@ const _offsetRecursively = (operation: Operation, wireOffset: number, totalWires if (operation.children != null) { operation.children.forEach((child) => _offsetRecursively(child, wireOffset, totalWires)); } + + return operation; }; /** @@ -394,6 +397,7 @@ const exportedForTesting = { _equivOperationParent, _moveX, _copyX, + _moveY, _offsetRecursively, _circularMod, _indexes, From ee00dc4eb1074e863aa6672c790e5caf4eef1209 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 18:35:10 -0400 Subject: [PATCH 038/108] Add tests for _equivGateElem --- __tests__/__snapshots__/editable.test.ts.snap | 28 +++++++++++++++ __tests__/editable.test.ts | 34 +++++++++++++++++++ src/editable.ts | 1 + 3 files changed, 63 insertions(+) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 700b6219..5655cf3a 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -102,6 +102,34 @@ Array [ ] `; +exports[`Test _equivGateElem should return gate H 1`] = ` +<g + class="gate" + data-id="0" + data-zoom-in="false" + data-zoom-out="false" +> + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="80" + y="20" + /> + <text + font-size="14" + x="100" + y="40" + > + H + </text> + </g> + </g> +</g> +`; + exports[`Test _equivOperation should return H gate 1`] = ` Object { "gate": "H", diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 40244c02..d56ce7b1 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -7,6 +7,7 @@ import { Circuit, draw, Operation, STYLES } from '../src/index'; const { _center, _wireData, + _equivGateElem, _equivOperation, _equivOperationParent, _moveX, @@ -102,6 +103,39 @@ describe('Test _wireData', () => { }); }); +describe('Test _equivGateElem', () => { + let container: HTMLElement; + beforeAll(() => { + container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + draw(circuit, container, STYLES['default']); + }); + test('should return gate H', () => { + const elem = container.querySelector('[class^="gate-"]') as SVGElement; + expect(_equivGateElem(elem)).toMatchSnapshot(); + }); +}); + describe('Test _equivOperation', () => { const circuit = { qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], diff --git a/src/editable.ts b/src/editable.ts index 47b6e080..2bf074f0 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -393,6 +393,7 @@ const _renderFn = ( const exportedForTesting = { _center, _wireData, + _equivGateElem, _equivOperation, _equivOperationParent, _moveX, From f63ecc36ad687d457b7fdecb49e3bbe2f3658554 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 18:40:08 -0400 Subject: [PATCH 039/108] Add tests for _wirePrefixes --- __tests__/editable.test.ts | 17 +++++++++++++++++ src/editable.ts | 1 + 2 files changed, 18 insertions(+) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index d56ce7b1..74d36ae8 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -5,6 +5,7 @@ import { exportedForTesting } from '../src/editable'; import { Circuit, draw, Operation, STYLES } from '../src/index'; const { + _wirePrefixes, _center, _wireData, _equivGateElem, @@ -19,6 +20,22 @@ const { _lastIndex, } = exportedForTesting; +describe('Test _wirePrefixes', () => { + test('2 wires', () => { + expect(_wirePrefixes([40, 100])).toStrictEqual([ + { index: 0, prefixX: 40, wireY: 40 }, + { index: 1, prefixX: 40, wireY: 100 }, + ]); + }); + test('3 wires', () => { + expect(_wirePrefixes([40, 100, 140])).toStrictEqual([ + { index: 0, prefixX: 40, wireY: 40 }, + { index: 1, prefixX: 40, wireY: 100 }, + { index: 2, prefixX: 40, wireY: 140 }, + ]); + }); +}); + describe('Test _center', () => { test('should return {25,50}', () => { Object.defineProperty(window.SVGElement.prototype, 'getBBox', { diff --git a/src/editable.ts b/src/editable.ts index 2bf074f0..52166aad 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -391,6 +391,7 @@ const _renderFn = ( }; const exportedForTesting = { + _wirePrefixes, _center, _wireData, _equivGateElem, From 100e2aa3e21423fff4bc6b2edbca59cf94a34ee5 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 18:48:25 -0400 Subject: [PATCH 040/108] Add tests for _wireYs --- __tests__/editable.test.ts | 17 +++++++++++++++++ src/editable.ts | 12 +++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 74d36ae8..b0123c40 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -5,6 +5,7 @@ import { exportedForTesting } from '../src/editable'; import { Circuit, draw, Operation, STYLES } from '../src/index'; const { + _wireYs, _wirePrefixes, _center, _wireData, @@ -20,6 +21,22 @@ const { _lastIndex, } = exportedForTesting; +describe('Test _wireYs', () => { + test('should return [40,100]', () => { + Object.defineProperty(window.SVGElement.prototype, 'getBBox', { + writable: true, + value: () => ({ + x: 0, + y: 20, + width: 0, + height: 120, + }), + }); + const elem = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + expect(_wireYs(elem, [40, 100, 140])).toStrictEqual([40, 100]); + }); +}); + describe('Test _wirePrefixes', () => { test('2 wires', () => { expect(_wirePrefixes([40, 100])).toStrictEqual([ diff --git a/src/editable.ts b/src/editable.ts index 52166aad..0f6b224b 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -71,7 +71,7 @@ const _addDataWires = (container: HTMLElement) => { * i.e. Gate 'Foo' spans on wire 0 (y=40), 1 (y=100), and 2 (y=140). * Function returns [40, 100, 140] */ -const _elemWireYs = (elem: SVGGraphicsElement, wireData: number[]) => { +const _wireYs = (elem: SVGGraphicsElement, wireData: number[]): number[] => { const { y, height } = elem.getBBox(); return wireData.filter((wireY) => wireY > y && wireY < y + height); }; @@ -82,7 +82,8 @@ const _hostElems = (container: HTMLElement) => { ); }; -const _wirePrefixes = (wireData: number[]) => wireData.map((wireY, index) => ({ index, wireY, prefixX: 40 })); +const _wirePrefixes = (wireData: number[]): { index: number; wireY: number; prefixX: number }[] => + wireData.map((wireY, index) => ({ index, wireY, prefixX: 40 })); /** * Find center point of element @@ -129,9 +130,9 @@ const _dropzoneLayer = (context: Context) => { } else { // Let group gates creating dropzones for each wire const { x } = elem.getBBox(); - const elemWireYs = _elemWireYs(elem, wireData); + const wireYs = _wireYs(elem, wireData); - elemWireYs.map((wireY) => { + wireYs.map((wireY) => { const wirePrefix = wirePrefixes.find((item) => item.wireY === wireY); if (wirePrefix) { const prefixX = wirePrefix.prefixX; @@ -177,7 +178,7 @@ const _wireData = (container: HTMLElement): number[] => { /** * Find equivalent gate element of host element */ -const _equivGateElem = (elem: SVGElement) => { +const _equivGateElem = (elem: SVGElement): SVGElement | null => { return elem.closest<SVGElement>('[data-id]'); }; @@ -391,6 +392,7 @@ const _renderFn = ( }; const exportedForTesting = { + _wireYs, _wirePrefixes, _center, _wireData, From 47fc810cbfd93ecefc52dbb109a95fd3eab79abe Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 18:58:36 -0400 Subject: [PATCH 041/108] Add tests for _hostElems --- __tests__/__snapshots__/editable.test.ts.snap | 46 +++++++++++++++++++ __tests__/editable.test.ts | 34 ++++++++++++++ src/editable.ts | 9 ++-- 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 5655cf3a..48af65d1 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -229,6 +229,52 @@ Array [ ] `; +exports[`Test _hostElems should return 4 elements 1`] = ` +Array [ + <rect + class="gate-unitary" + height="40" + width="40" + x="80" + y="20" + />, + <circle + class="control-dot" + cx="160" + cy="40" + r="5" + />, + <g + class="oplus" + > + <circle + cx="160" + cy="100" + r="15" + /> + <line + x1="160" + x2="160" + y1="85" + y2="115" + /> + <line + x1="145" + x2="175" + y1="100" + y2="100" + /> + </g>, + <rect + class="gate-measure" + height="40" + width="40" + x="200" + y="80" + />, +] +`; + exports[`Test _moveX move elem from index 0 to index 1 1`] = ` Array [ Object { diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index b0123c40..0bde57d6 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -6,6 +6,7 @@ import { Circuit, draw, Operation, STYLES } from '../src/index'; const { _wireYs, + _hostElems, _wirePrefixes, _center, _wireData, @@ -21,6 +22,39 @@ const { _lastIndex, } = exportedForTesting; +describe('Test _hostElems', () => { + let container: HTMLElement; + beforeAll(() => { + container = document.createElement('div'); + const circuit = { + qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], + operations: [ + { + gate: 'H', + targets: [{ qId: 0 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + { + gate: 'Measure', + isMeasurement: true, + controls: [{ qId: 1 }], + targets: [{ type: 1, qId: 1, cId: 0 }], + }, + ], + }; + draw(circuit, container, STYLES['default']); + }); + test('should return 4 elements', () => { + expect(_hostElems(container)).toMatchSnapshot(); + expect(_hostElems(container)).toHaveLength(4); + }); +}); + describe('Test _wireYs', () => { test('should return [40,100]', () => { Object.defineProperty(window.SVGElement.prototype, 'getBBox', { diff --git a/src/editable.ts b/src/editable.ts index 0f6b224b..fd863fb0 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -76,9 +76,11 @@ const _wireYs = (elem: SVGGraphicsElement, wireData: number[]): number[] => { return wireData.filter((wireY) => wireY > y && wireY < y + height); }; -const _hostElems = (container: HTMLElement) => { - return container.querySelectorAll<SVGGraphicsElement>( - '[class^="gate-"]:not(.gate-control, .gate-swap), .control-dot, .oplus, .cross', +const _hostElems = (container: HTMLElement): SVGGraphicsElement[] => { + return Array.from( + container.querySelectorAll<SVGGraphicsElement>( + '[class^="gate-"]:not(.gate-control, .gate-swap), .control-dot, .oplus, .cross', + ), ); }; @@ -393,6 +395,7 @@ const _renderFn = ( const exportedForTesting = { _wireYs, + _hostElems, _wirePrefixes, _center, _wireData, From cba0761f398890bea789219ca67193a4c6a02294 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 20:12:19 -0400 Subject: [PATCH 042/108] Remove unnecessary condition when copying --- src/editable.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/editable.ts b/src/editable.ts index fd863fb0..46fd99b8 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -313,7 +313,6 @@ const _moveX = (sourceId: string, targetId: string, operations: Operation[]): Op }; const _copyX = (sourceId: string, targetId: string, operations: Operation[]): Operation | null => { - if (sourceId === targetId) return _equivOperation(sourceId, operations); const sourceOperation = _equivOperation(sourceId, operations); const sourceOperationParent = _equivOperationParent(sourceId, operations); const targetOperationParent = _equivOperationParent(targetId, operations); From 9fbe5669f961b3eb8e870b3b9353e048b72e56a3 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 20:17:54 -0400 Subject: [PATCH 043/108] Clone operation when moving --- src/editable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editable.ts b/src/editable.ts index 46fd99b8..a18df3be 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -301,7 +301,7 @@ const _moveX = (sourceId: string, targetId: string, operations: Operation[]): Op return null; // Insert sourceOperation to target last index - const newSourceOperation: Operation = { ...sourceOperation }; + const newSourceOperation: Operation = JSON.parse(JSON.stringify(sourceOperation)); targetOperationParent.splice(targetLastIndex, 0, newSourceOperation); // Delete sourceOperation From cca0b1ca8b0d637b1975dfd2f984dc81d99972a6 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 20:34:06 -0400 Subject: [PATCH 044/108] Reformat comments --- src/editable.ts | 90 ++++++++++++++++++++++++++++++++++++++++--------- src/styles.ts | 9 +++++ 2 files changed, 83 insertions(+), 16 deletions(-) diff --git a/src/editable.ts b/src/editable.ts index a18df3be..71b95595 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -39,15 +39,17 @@ const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (ci selectedWire: null, }; - // addDropzones(container); - // addDocumentEvents(container); + _addStyles(container, _wireData(container)); _addDataWires(container); svg.appendChild(_dropzoneLayer(context)); - // addDropzoneEvents(context); - // addMouseEvents(context); _addEvents(context); }; +/** + * Add data-wire to all host elements + * + * @param container HTML element for rendering visualization into + */ const _addDataWires = (container: HTMLElement) => { const elems = _hostElems(container); elems.forEach((elem) => { @@ -67,8 +69,8 @@ const _addDataWires = (container: HTMLElement) => { }; /** - * Create a list of wires that element is spanning on. - * i.e. Gate 'Foo' spans on wire 0 (y=40), 1 (y=100), and 2 (y=140). + * Create a list of wires that element is spanning on + * i.e. Gate 'Foo' spans on wire 0 (y=40), 1 (y=100), and 2 (y=140) * Function returns [40, 100, 140] */ const _wireYs = (elem: SVGGraphicsElement, wireData: number[]): number[] => { @@ -84,11 +86,20 @@ const _hostElems = (container: HTMLElement): SVGGraphicsElement[] => { ); }; +const _addStyles = (container: HTMLElement, wireData: number[]): void => { + const elems = _hostElems(container); + elems.forEach((elem) => { + if (_wireYs(elem, wireData).length < 2) elem.style.cursor = 'grab'; + }); +}; + const _wirePrefixes = (wireData: number[]): { index: number; wireY: number; prefixX: number }[] => wireData.map((wireY, index) => ({ index, wireY, prefixX: 40 })); /** - * Find center point of element + * Find center point of element + * + * @param elem Host element */ const _center = (elem: SVGGraphicsElement): { cX: number; cY: number } => { const { x, y, width, height } = elem.getBBox(); @@ -96,7 +107,9 @@ const _center = (elem: SVGGraphicsElement): { cX: number; cY: number } => { }; /** - * Create dropzone layer with all dropzones popullated + * Create dropzone layer with all dropzones popullated + * + * @param context Context object */ const _dropzoneLayer = (context: Context) => { const dropzoneLayer = document.createElementNS('http://www.w3.org/2000/svg', 'g'); @@ -178,14 +191,18 @@ const _wireData = (container: HTMLElement): number[] => { }; /** - * Find equivalent gate element of host element + * Find equivalent gate element of host element + * + * @param elem Host element */ const _equivGateElem = (elem: SVGElement): SVGElement | null => { return elem.closest<SVGElement>('[data-id]'); }; /** - * Find data-id of host element + * Find data-id of host element + * + * @param elem Host element */ const _equivDataId = (elem: SVGElement) => { const gateElem = _equivGateElem(elem); @@ -193,7 +210,9 @@ const _equivDataId = (elem: SVGElement) => { }; /** - * Disable contextmenu default behaviors + * Disable contextmenu default behaviors + * + * @param container HTML element for rendering visualization into */ const _addContextMenuEvents = (container: HTMLElement) => { container.addEventListener('contextmenu', (ev: MouseEvent) => { @@ -202,24 +221,60 @@ const _addContextMenuEvents = (container: HTMLElement) => { }; /** - * Add events specifically for dropzoneLayer + * Add events specifically for dropzoneLayer + * + * @param container HTML element for rendering visualization into + * @param dropzoneLayer SVG group element representing dropzone layer */ const _addDropzoneLayerEvents = (container: HTMLElement, dropzoneLayer: SVGGElement) => { container.addEventListener('mouseup', () => (dropzoneLayer.style.display = 'none')); }; +/** + * Add events for document + * + * @param context Context object + */ +const _addDocumentEvents = (context: Context) => { + const { container } = context; + + document.addEventListener('keydown', (ev: KeyboardEvent) => { + if (ev.ctrlKey && context.selectedId) { + container.classList.remove('moving'); + container.classList.add('copying'); + } + }); + + document.addEventListener('keyup', () => { + if (context.selectedId) { + container.classList.remove('moving'); + } + }); + + document.addEventListener('mouseup', () => { + container.classList.remove('moving', 'copying'); + }); +}; + +/** + * Add all events + * + * @param context Context object + */ const _addEvents = (context: Context) => { const { container, operations, renderFn } = context; const dropzoneLayer = container.querySelector('.dropzone-layer') as SVGGElement; _addContextMenuEvents(container); _addDropzoneLayerEvents(container, dropzoneLayer); + _addDocumentEvents(context); // Host element events const elems = _hostElems(container); elems.forEach((elem) => { elem.addEventListener('mousedown', () => { context.selectedWire = elem.getAttribute('data-wire'); + container.classList.add('moving'); }); const gateElem = _equivGateElem(elem); @@ -334,8 +389,10 @@ const _copyX = (sourceId: string, targetId: string, operations: Operation[]): Op }; const _moveY = (sourceWire: string, targetWire: string, operation: Operation, totalWires: number): Operation => { - const offset = parseInt(targetWire) - parseInt(sourceWire); - _offsetRecursively(operation, offset, totalWires); + if (operation.gate !== 'measure') { + const offset = parseInt(targetWire) - parseInt(sourceWire); + _offsetRecursively(operation, offset, totalWires); + } return operation; }; @@ -365,8 +422,9 @@ const _offsetRecursively = (operation: Operation, wireOffset: number, totalWires }; /** - * This modulo function always returns positive value based on total. - * i.e: value=0, offset=-1, total=4 returns 3 instead of -1 + * This modulo function always returns positive value based on total + * + * i.e: value=0, offset=-1, total=4 returns 3 instead of -1 */ const _circularMod = (value: number, offset: number, total: number): number => { return (((value + offset) % total) + total) % total; diff --git a/src/styles.ts b/src/styles.ts index 481aea8c..06e7d787 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -252,4 +252,13 @@ const _editable = ` fill: #EC7063; fill-opacity: 50%; } + .grab { + cursor: grab; + } + .moving { + cursor: move; + } + .copying { + cursor: copy; + } `; From 0347a80f14ffbe04f8da72d4adc6d5d3871d934c Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 28 Jun 2022 20:35:32 -0400 Subject: [PATCH 045/108] Reformat comments --- src/editable.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/editable.ts b/src/editable.ts index 71b95595..1168f878 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -49,6 +49,7 @@ const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (ci * Add data-wire to all host elements * * @param container HTML element for rendering visualization into + * */ const _addDataWires = (container: HTMLElement) => { const elems = _hostElems(container); @@ -72,6 +73,7 @@ const _addDataWires = (container: HTMLElement) => { * Create a list of wires that element is spanning on * i.e. Gate 'Foo' spans on wire 0 (y=40), 1 (y=100), and 2 (y=140) * Function returns [40, 100, 140] + * */ const _wireYs = (elem: SVGGraphicsElement, wireData: number[]): number[] => { const { y, height } = elem.getBBox(); @@ -100,6 +102,7 @@ const _wirePrefixes = (wireData: number[]): { index: number; wireY: number; pref * Find center point of element * * @param elem Host element + * */ const _center = (elem: SVGGraphicsElement): { cX: number; cY: number } => { const { x, y, width, height } = elem.getBBox(); @@ -110,6 +113,7 @@ const _center = (elem: SVGGraphicsElement): { cX: number; cY: number } => { * Create dropzone layer with all dropzones popullated * * @param context Context object + * */ const _dropzoneLayer = (context: Context) => { const dropzoneLayer = document.createElementNS('http://www.w3.org/2000/svg', 'g'); @@ -194,6 +198,7 @@ const _wireData = (container: HTMLElement): number[] => { * Find equivalent gate element of host element * * @param elem Host element + * */ const _equivGateElem = (elem: SVGElement): SVGElement | null => { return elem.closest<SVGElement>('[data-id]'); @@ -213,6 +218,7 @@ const _equivDataId = (elem: SVGElement) => { * Disable contextmenu default behaviors * * @param container HTML element for rendering visualization into + * */ const _addContextMenuEvents = (container: HTMLElement) => { container.addEventListener('contextmenu', (ev: MouseEvent) => { @@ -225,6 +231,7 @@ const _addContextMenuEvents = (container: HTMLElement) => { * * @param container HTML element for rendering visualization into * @param dropzoneLayer SVG group element representing dropzone layer + * */ const _addDropzoneLayerEvents = (container: HTMLElement, dropzoneLayer: SVGGElement) => { container.addEventListener('mouseup', () => (dropzoneLayer.style.display = 'none')); @@ -234,6 +241,7 @@ const _addDropzoneLayerEvents = (container: HTMLElement, dropzoneLayer: SVGGElem * Add events for document * * @param context Context object + * */ const _addDocumentEvents = (context: Context) => { const { container } = context; @@ -260,6 +268,7 @@ const _addDocumentEvents = (context: Context) => { * Add all events * * @param context Context object + * */ const _addEvents = (context: Context) => { const { container, operations, renderFn } = context; @@ -425,6 +434,7 @@ const _offsetRecursively = (operation: Operation, wireOffset: number, totalWires * This modulo function always returns positive value based on total * * i.e: value=0, offset=-1, total=4 returns 3 instead of -1 + * */ const _circularMod = (value: number, offset: number, total: number): number => { return (((value + offset) % total) + total) % total; From 69dedb215c614995662fafffe1e720c14ed42917 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 29 Jun 2022 12:58:39 -0400 Subject: [PATCH 046/108] Fix keyup behaviors --- src/editable.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/editable.ts b/src/editable.ts index 1168f878..49405309 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -208,6 +208,7 @@ const _equivGateElem = (elem: SVGElement): SVGElement | null => { * Find data-id of host element * * @param elem Host element + * */ const _equivDataId = (elem: SVGElement) => { const gateElem = _equivGateElem(elem); @@ -255,12 +256,15 @@ const _addDocumentEvents = (context: Context) => { document.addEventListener('keyup', () => { if (context.selectedId) { + container.classList.remove('copying'); container.classList.remove('moving'); } }); document.addEventListener('mouseup', () => { container.classList.remove('moving', 'copying'); + context.selectedId = null; + context.selectedWire = null; }); }; From bc94aff5685773f4a1ba75883d7d0acc087787f3 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 29 Jun 2022 13:10:34 -0400 Subject: [PATCH 047/108] Overhaul comments --- src/editable.ts | 82 +++++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/src/editable.ts b/src/editable.ts index 49405309..05ac4522 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -22,9 +22,7 @@ interface Context { * @param container HTML element for rendering visualization into. * @param sqore Sqore object * @param onCircuitChange User-provided callback function triggered when circuit is changed - * */ - const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (circuit: Circuit) => void): void => { const svg = container.querySelector('svg') as SVGElement; @@ -47,9 +45,6 @@ const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (ci /** * Add data-wire to all host elements - * - * @param container HTML element for rendering visualization into - * */ const _addDataWires = (container: HTMLElement) => { const elems = _hostElems(container); @@ -70,16 +65,18 @@ const _addDataWires = (container: HTMLElement) => { }; /** - * Create a list of wires that element is spanning on - * i.e. Gate 'Foo' spans on wire 0 (y=40), 1 (y=100), and 2 (y=140) - * Function returns [40, 100, 140] - * + * Create a list of wires that element is spanning on + * i.e. Gate 'Foo' spans on wire 0 (y=40), 1 (y=100), and 2 (y=140) + * Function returns [40, 100, 140] */ const _wireYs = (elem: SVGGraphicsElement, wireData: number[]): number[] => { const { y, height } = elem.getBBox(); return wireData.filter((wireY) => wireY > y && wireY < y + height); }; +/** + * Get list of host elements that dropzones can be attached to + */ const _hostElems = (container: HTMLElement): SVGGraphicsElement[] => { return Array.from( container.querySelectorAll<SVGGraphicsElement>( @@ -88,6 +85,9 @@ const _hostElems = (container: HTMLElement): SVGGraphicsElement[] => { ); }; +/** + * Add custom styles specific to this module + */ const _addStyles = (container: HTMLElement, wireData: number[]): void => { const elems = _hostElems(container); elems.forEach((elem) => { @@ -95,14 +95,14 @@ const _addStyles = (container: HTMLElement, wireData: number[]): void => { }); }; +/** + * Generate an array of wire prefixes from wire data + */ const _wirePrefixes = (wireData: number[]): { index: number; wireY: number; prefixX: number }[] => wireData.map((wireY, index) => ({ index, wireY, prefixX: 40 })); /** * Find center point of element - * - * @param elem Host element - * */ const _center = (elem: SVGGraphicsElement): { cX: number; cY: number } => { const { x, y, width, height } = elem.getBBox(); @@ -111,9 +111,6 @@ const _center = (elem: SVGGraphicsElement): { cX: number; cY: number } => { /** * Create dropzone layer with all dropzones popullated - * - * @param context Context object - * */ const _dropzoneLayer = (context: Context) => { const dropzoneLayer = document.createElementNS('http://www.w3.org/2000/svg', 'g'); @@ -180,6 +177,9 @@ const _dropzoneLayer = (context: Context) => { return dropzoneLayer; }; +/** + * Generate an array of y values based on circuit wires + */ const _wireData = (container: HTMLElement): number[] => { // elems include qubit wires and lines of measure gates const elems = container.querySelectorAll<SVGGElement>('svg > g:nth-child(3) > g'); @@ -196,9 +196,6 @@ const _wireData = (container: HTMLElement): number[] => { /** * Find equivalent gate element of host element - * - * @param elem Host element - * */ const _equivGateElem = (elem: SVGElement): SVGElement | null => { return elem.closest<SVGElement>('[data-id]'); @@ -206,9 +203,6 @@ const _equivGateElem = (elem: SVGElement): SVGElement | null => { /** * Find data-id of host element - * - * @param elem Host element - * */ const _equivDataId = (elem: SVGElement) => { const gateElem = _equivGateElem(elem); @@ -217,9 +211,6 @@ const _equivDataId = (elem: SVGElement) => { /** * Disable contextmenu default behaviors - * - * @param container HTML element for rendering visualization into - * */ const _addContextMenuEvents = (container: HTMLElement) => { container.addEventListener('contextmenu', (ev: MouseEvent) => { @@ -229,10 +220,6 @@ const _addContextMenuEvents = (container: HTMLElement) => { /** * Add events specifically for dropzoneLayer - * - * @param container HTML element for rendering visualization into - * @param dropzoneLayer SVG group element representing dropzone layer - * */ const _addDropzoneLayerEvents = (container: HTMLElement, dropzoneLayer: SVGGElement) => { container.addEventListener('mouseup', () => (dropzoneLayer.style.display = 'none')); @@ -240,9 +227,6 @@ const _addDropzoneLayerEvents = (container: HTMLElement, dropzoneLayer: SVGGElem /** * Add events for document - * - * @param context Context object - * */ const _addDocumentEvents = (context: Context) => { const { container } = context; @@ -270,9 +254,6 @@ const _addDocumentEvents = (context: Context) => { /** * Add all events - * - * @param context Context object - * */ const _addEvents = (context: Context) => { const { container, operations, renderFn } = context; @@ -325,6 +306,9 @@ const _addEvents = (context: Context) => { }); }; +/** + * Find equivalent parent array of an operation + */ const _equivOperationParent = (dataId: string | null, operations: Operation[]): Operation[] | null => { if (!dataId) return null; @@ -338,6 +322,9 @@ const _equivOperationParent = (dataId: string | null, operations: Operation[]): return operationParent; }; +/** + * Find an equivalent operation of an element based on its data-id + */ const _equivOperation = (dataId: string | null, operations: Operation[]): Operation | null => { if (!dataId) return null; @@ -353,6 +340,9 @@ const _equivOperation = (dataId: string | null, operations: Operation[]): Operat return operationParent[index]; }; +/** + * Move an operation horizontally + */ const _moveX = (sourceId: string, targetId: string, operations: Operation[]): Operation | null => { if (sourceId === targetId) return _equivOperation(sourceId, operations); const sourceOperation = _equivOperation(sourceId, operations); @@ -380,6 +370,9 @@ const _moveX = (sourceId: string, targetId: string, operations: Operation[]): Op return newSourceOperation; }; +/** + * Copy an operation horizontally + */ const _copyX = (sourceId: string, targetId: string, operations: Operation[]): Operation | null => { const sourceOperation = _equivOperation(sourceId, operations); const sourceOperationParent = _equivOperationParent(sourceId, operations); @@ -401,6 +394,9 @@ const _copyX = (sourceId: string, targetId: string, operations: Operation[]): Op return newSourceOperation; }; +/** + * Move an operation vertically by changing its controls and targets + */ const _moveY = (sourceWire: string, targetWire: string, operation: Operation, totalWires: number): Operation => { if (operation.gate !== 'measure') { const offset = parseInt(targetWire) - parseInt(sourceWire); @@ -409,6 +405,9 @@ const _moveY = (sourceWire: string, targetWire: string, operation: Operation, to return operation; }; +/** + * Recursively change object controls and targets + */ const _offsetRecursively = (operation: Operation, wireOffset: number, totalWires: number): Operation => { // Offset all targets by offsetY value if (operation.targets != null) { @@ -436,23 +435,31 @@ const _offsetRecursively = (operation: Operation, wireOffset: number, totalWires /** * This modulo function always returns positive value based on total - * * i.e: value=0, offset=-1, total=4 returns 3 instead of -1 - * */ const _circularMod = (value: number, offset: number, total: number): number => { return (((value + offset) % total) + total) % total; }; +/** + * Split data-id into an array of indexes + */ const _indexes = (dataId: string): number[] => dataId !== '' // ? dataId.split('-').map((segment) => parseInt(segment)) : []; +/** + * Get the last index of data-id + * i.e: data-id = "0-1-2", _lastIndex will return 2 + */ const _lastIndex = (dataId: string): number | undefined => { return _indexes(dataId).pop(); }; +/** + * Return a render function with the onCircuitChange callback attached to it + */ const _renderFn = ( container: HTMLElement, sqore: Sqore, @@ -464,6 +471,9 @@ const _renderFn = ( }; }; +/** + * Object exported for unit testing + */ const exportedForTesting = { _wireYs, _hostElems, From 2f5e3f8c4973d9f2e4cd4dd8bc74c4297dd12ee6 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 30 Jun 2022 12:43:55 -0400 Subject: [PATCH 048/108] Fix add instead of remove cursor style --- src/editable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editable.ts b/src/editable.ts index 05ac4522..4c363d69 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -241,7 +241,7 @@ const _addDocumentEvents = (context: Context) => { document.addEventListener('keyup', () => { if (context.selectedId) { container.classList.remove('copying'); - container.classList.remove('moving'); + container.classList.add('moving'); } }); From 0019b5ec718397eb8f8f1eb13b73186e3071ca8e Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 6 Jul 2022 02:01:03 -0400 Subject: [PATCH 049/108] Rename _equivOperationParent to _equivParentArray --- __tests__/__snapshots__/editable.test.ts.snap | 4 ++-- __tests__/editable.test.ts | 8 ++++---- src/editable.ts | 20 +++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 48af65d1..9ea60e4d 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -158,7 +158,7 @@ Object { } `; -exports[`Test _equivOperationParent should return Foo 1`] = ` +exports[`Test _equivParentArray should return Foo 1`] = ` Array [ Object { "gate": "H", @@ -186,7 +186,7 @@ Array [ ] `; -exports[`Test _equivOperationParent should return all operations 1`] = ` +exports[`Test _equivParentArray should return all operations 1`] = ` Array [ Object { "gate": "H", diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 0bde57d6..96ce98ec 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -12,7 +12,7 @@ const { _wireData, _equivGateElem, _equivOperation, - _equivOperationParent, + _equivParentArray, _moveX, _copyX, _moveY, @@ -234,7 +234,7 @@ describe('Test _equivOperation', () => { }); }); -describe('Test _equivOperationParent', () => { +describe('Test _equivParentArray', () => { test('should return Foo', () => { const circuit = { qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], @@ -358,7 +358,7 @@ describe('Test _equivOperationParent', () => { }, ], }; - expect(_equivOperationParent('0-1', circuit.operations)).toMatchSnapshot(); + expect(_equivParentArray('0-1', circuit.operations)).toMatchSnapshot(); }); test('should return all operations', () => { const circuit = { @@ -382,7 +382,7 @@ describe('Test _equivOperationParent', () => { }, ], }; - expect(_equivOperationParent('0', circuit.operations)).toMatchSnapshot(); + expect(_equivParentArray('0', circuit.operations)).toMatchSnapshot(); }); }); diff --git a/src/editable.ts b/src/editable.ts index 4c363d69..3293cab3 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -309,17 +309,17 @@ const _addEvents = (context: Context) => { /** * Find equivalent parent array of an operation */ -const _equivOperationParent = (dataId: string | null, operations: Operation[]): Operation[] | null => { +const _equivParentArray = (dataId: string | null, operations: Operation[]): Operation[] | null => { if (!dataId) return null; const indexes = _indexes(dataId); indexes.pop(); - let operationParent = operations; + let parentArray = operations; for (const index of indexes) { - operationParent = operationParent[index].children || operationParent; + parentArray = parentArray[index].children || parentArray; } - return operationParent; + return parentArray; }; /** @@ -329,7 +329,7 @@ const _equivOperation = (dataId: string | null, operations: Operation[]): Operat if (!dataId) return null; const index = _lastIndex(dataId); - const operationParent = _equivOperationParent(dataId, operations); + const operationParent = _equivParentArray(dataId, operations); if ( operationParent == null || // @@ -346,8 +346,8 @@ const _equivOperation = (dataId: string | null, operations: Operation[]): Operat const _moveX = (sourceId: string, targetId: string, operations: Operation[]): Operation | null => { if (sourceId === targetId) return _equivOperation(sourceId, operations); const sourceOperation = _equivOperation(sourceId, operations); - const sourceOperationParent = _equivOperationParent(sourceId, operations); - const targetOperationParent = _equivOperationParent(targetId, operations); + const sourceOperationParent = _equivParentArray(sourceId, operations); + const targetOperationParent = _equivParentArray(targetId, operations); const targetLastIndex = _lastIndex(targetId); if ( @@ -375,8 +375,8 @@ const _moveX = (sourceId: string, targetId: string, operations: Operation[]): Op */ const _copyX = (sourceId: string, targetId: string, operations: Operation[]): Operation | null => { const sourceOperation = _equivOperation(sourceId, operations); - const sourceOperationParent = _equivOperationParent(sourceId, operations); - const targetOperationParent = _equivOperationParent(targetId, operations); + const sourceOperationParent = _equivParentArray(sourceId, operations); + const targetOperationParent = _equivParentArray(targetId, operations); const targetLastIndex = _lastIndex(targetId); if ( @@ -482,7 +482,7 @@ const exportedForTesting = { _wireData, _equivGateElem, _equivOperation, - _equivOperationParent, + _equivParentArray, _moveX, _copyX, _moveY, From eb1ea55e21d8f6d96432cceff95c60e58710b129 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 6 Jul 2022 03:34:04 -0400 Subject: [PATCH 050/108] Fix parent operation not updating to its children targets --- __tests__/__snapshots__/editable.test.ts.snap | 40 +++ __tests__/editable.test.ts | 276 ++++++++++++++++++ src/editable.ts | 64 ++++ 3 files changed, 380 insertions(+) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap index 9ea60e4d..c29c1bad 100644 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ b/__tests__/__snapshots__/editable.test.ts.snap @@ -229,6 +229,46 @@ Array [ ] `; +exports[`Test _equivParentOperation should return Foo 1`] = ` +Object { + "children": Array [ + Object { + "gate": "H", + "targets": Array [ + Object { + "qId": 1, + }, + ], + }, + Object { + "controls": Array [ + Object { + "qId": 1, + }, + ], + "displayArgs": "(0.25)", + "gate": "RX", + "isControlled": true, + "targets": Array [ + Object { + "qId": 0, + }, + ], + }, + ], + "conditionalRender": 3, + "gate": "Foo", + "targets": Array [ + Object { + "qId": 0, + }, + Object { + "qId": 1, + }, + ], +} +`; + exports[`Test _hostElems should return 4 elements 1`] = ` Array [ <rect diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts index 96ce98ec..0fde4705 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/editable.test.ts @@ -12,11 +12,13 @@ const { _wireData, _equivGateElem, _equivOperation, + _equivParentOperation, _equivParentArray, _moveX, _copyX, _moveY, _offsetRecursively, + _targets, _circularMod, _indexes, _lastIndex, @@ -234,6 +236,134 @@ describe('Test _equivOperation', () => { }); }); +describe('Test _equivParentOperation', () => { + test('should return Foo', () => { + const circuit = { + qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], + operations: [ + { + gate: 'Foo', + conditionalRender: 3, + targets: [{ qId: 0 }, { qId: 1 }], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + }, + { + gate: 'RX', + displayArgs: '(0.25)', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 0 }], + }, + ], + }, + { + gate: 'X', + targets: [{ qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 2 }, { qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }, { qId: 3 }], + targets: [{ qId: 1 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }, { qId: 3 }], + targets: [{ qId: 2 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'measure', + isMeasurement: true, + controls: [{ qId: 0 }], + targets: [{ type: 1, qId: 0, cId: 0 }], + }, + { + gate: 'ApplyIfElseR', + isConditional: true, + controls: [{ type: 1, qId: 0, cId: 0 }], + targets: [], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + conditionalRender: 2, + }, + { + gate: 'Foo', + targets: [{ qId: 3 }], + conditionalRender: 2, + }, + ], + }, + { + gate: 'SWAP', + targets: [{ qId: 0 }, { qId: 2 }], + children: [ + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + ], + }, + { + gate: 'ZZ', + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'ZZ', + targets: [{ qId: 0 }, { qId: 1 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }, { qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + ], + }; + expect(_equivParentOperation('0-1', circuit.operations)).toMatchSnapshot(); + }); +}); + describe('Test _equivParentArray', () => { test('should return Foo', () => { const circuit = { @@ -504,6 +634,152 @@ describe('Test _offsetRecursively', () => { }); }); +describe('Test _targets', () => { + let circuit: Circuit; + beforeEach(() => { + circuit = { + qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], + operations: [ + { + gate: 'Foo', + conditionalRender: 3, + targets: [{ qId: 0 }, { qId: 1 }], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + }, + { + gate: 'RX', + displayArgs: '(0.25)', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 0 }], + }, + ], + }, + { + gate: 'X', + targets: [{ qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 2 }, { qId: 3 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }, { qId: 3 }], + targets: [{ qId: 1 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 1 }, { qId: 3 }], + targets: [{ qId: 2 }], + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'measure', + isMeasurement: true, + controls: [{ qId: 0 }], + targets: [{ type: 1, qId: 0, cId: 0 }], + }, + { + gate: 'ApplyIfElseR', + isConditional: true, + controls: [{ type: 1, qId: 0, cId: 0 }], + targets: [], + children: [ + { + gate: 'H', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + targets: [{ qId: 1 }], + conditionalRender: 1, + }, + { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + conditionalRender: 2, + }, + { + gate: 'Foo', + targets: [{ qId: 3 }], + conditionalRender: 2, + }, + ], + }, + { + gate: 'SWAP', + targets: [{ qId: 0 }, { qId: 2 }], + children: [ + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, + { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, + ], + }, + { + gate: 'ZZ', + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'ZZ', + targets: [{ qId: 0 }, { qId: 1 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + { + gate: 'XX', + isControlled: true, + controls: [{ qId: 0 }, { qId: 2 }], + targets: [{ qId: 1 }, { qId: 3 }], + }, + ], + }; + }); + test('move RX down 1, should return [{qId:1}, {qId:2}]', () => { + const parentOperation = circuit.operations[0]; + const parentArray = parentOperation.children; + if (parentArray) { + const operation = parentArray[1]; + _moveY('0', '1', operation, 4); + } + expect(_targets(parentOperation)).toStrictEqual([{ qId: 1 }, { qId: 2 }]); + }); + test('move RX down 2, should return [{qId:1}, {qId:2}, {qId:3}]', () => { + const parentOperation = circuit.operations[0]; + const parentArray = parentOperation.children; + if (parentArray) { + const operation = parentArray[1]; + _moveY('0', '2', operation, 4); + } + expect(_targets(parentOperation)).toStrictEqual([{ qId: 1 }, { qId: 2 }, { qId: 3 }]); + }); +}); + describe('Test _circularMod', () => { test('should return 2', () => { expect(_circularMod(5, 1, 4)).toEqual(2); diff --git a/src/editable.ts b/src/editable.ts index 3293cab3..d556217c 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -3,6 +3,7 @@ import { Circuit, Operation } from './circuit'; import { box } from './formatters/formatUtils'; +import { Register } from './register'; import { Sqore } from './sqore'; interface Context { @@ -299,6 +300,10 @@ const _addEvents = (context: Context) => { if (newSourceOperation != null) { _moveY(context.selectedWire, targetWire, newSourceOperation, context.wireData.length); + const parentOperation = _equivParentOperation(context.selectedId, operations); + if (parentOperation) { + parentOperation.targets = _targets(parentOperation); + } } renderFn(); @@ -306,6 +311,22 @@ const _addEvents = (context: Context) => { }); }; +const _equivParentOperation = (dataId: string | null, operations: Operation[]): Operation | null => { + if (!dataId) return null; + + const indexes = _indexes(dataId); + indexes.pop(); + const lastIndex = indexes.pop(); + + if (lastIndex == null) return null; + + let parentOperation = operations; + for (const index of indexes) { + parentOperation = parentOperation[index].children || parentOperation; + } + return parentOperation[lastIndex]; +}; + /** * Find equivalent parent array of an operation */ @@ -433,6 +454,47 @@ const _offsetRecursively = (operation: Operation, wireOffset: number, totalWires return operation; }; +/** + * Find targets of an operation by recursively walkthrough all of its children controls and targets + * i.e. Gate Foo contains gate H and gate RX. + * qIds of Gate H is 1 + * qIds of Gate RX is 1, 2 + * This should return [{qId: 1}, {qId: 2}] + */ +const _targets = (operation: Operation): Register[] | [] => { + const _recurse = (operation: Operation) => { + registers.push(...operation.targets); + if (operation.controls) { + registers.push(...operation.controls); + // If there is more children, keep adding more to registers + if (operation.children) { + for (const child of operation.children) { + _recurse(child); + } + } + } + }; + + const registers: Register[] = []; + if (operation.children == null) return []; + + // Recursively walkthrough all children to populate registers + for (const child of operation.children) { + _recurse(child); + } + + // Extract qIds from array of object + // i.e. [{qId: 0}, {qId: 1}, {qId: 1}] -> [0, 1, 1] + const qIds = registers.map((register) => register.qId); + const uniqueQIds = Array.from(new Set(qIds)); + + // Transform array of numbers into array of qId object + // i.e. -> [0, 1] -> [{qId: 0}, {qId: 1}, {qId: 1}] + return uniqueQIds.map((qId) => ({ + qId, + })); +}; + /** * This modulo function always returns positive value based on total * i.e: value=0, offset=-1, total=4 returns 3 instead of -1 @@ -482,11 +544,13 @@ const exportedForTesting = { _wireData, _equivGateElem, _equivOperation, + _equivParentOperation, _equivParentArray, _moveX, _copyX, _moveY, _offsetRecursively, + _targets, _circularMod, _indexes, _lastIndex, From 2fe5929eaf16668905efbfaa8f83c74edaedd211 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 7 Jul 2022 11:34:01 -0400 Subject: [PATCH 051/108] Fix comment --- src/editable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editable.ts b/src/editable.ts index d556217c..4c16c9cf 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -489,7 +489,7 @@ const _targets = (operation: Operation): Register[] | [] => { const uniqueQIds = Array.from(new Set(qIds)); // Transform array of numbers into array of qId object - // i.e. -> [0, 1] -> [{qId: 0}, {qId: 1}, {qId: 1}] + // i.e. [0, 1] -> [{qId: 0}, {qId: 1}] return uniqueQIds.map((qId) => ({ qId, })); From 352e74e9701ad2cf7998fff45bd7309718a837cf Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 7 Jul 2022 11:54:52 -0400 Subject: [PATCH 052/108] First commit new feature --- src/editable.ts | 6 +-- src/panel.ts | 124 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 3 deletions(-) create mode 100755 src/panel.ts diff --git a/src/editable.ts b/src/editable.ts index 4c16c9cf..8625f3b1 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -3,6 +3,7 @@ import { Circuit, Operation } from './circuit'; import { box } from './formatters/formatUtils'; +import { addPanel } from './panel'; import { Register } from './register'; import { Sqore } from './sqore'; @@ -38,6 +39,7 @@ const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (ci selectedWire: null, }; + addPanel(context); _addStyles(container, _wireData(container)); _addDataWires(container); svg.appendChild(_dropzoneLayer(context)); @@ -248,8 +250,6 @@ const _addDocumentEvents = (context: Context) => { document.addEventListener('mouseup', () => { container.classList.remove('moving', 'copying'); - context.selectedId = null; - context.selectedWire = null; }); }; @@ -556,4 +556,4 @@ const exportedForTesting = { _lastIndex, }; -export { addEditable, exportedForTesting }; +export { addEditable, Context, _equivOperation, exportedForTesting }; diff --git a/src/panel.ts b/src/panel.ts new file mode 100755 index 00000000..45405920 --- /dev/null +++ b/src/panel.ts @@ -0,0 +1,124 @@ +import { Operation } from './circuit'; +import { Context, _equivOperation } from './editable'; + +const addPanel = (context: Context): void => { + const { container } = context; + + container.prepend(_panel(operation)); +}; + +const _panel = (operation: Operation | null) => { + console.log(operation); + const options: Option[] = [ + { + value: '0', + text: 'q0', + }, + { + value: '1', + text: 'q1', + }, + { + value: '2', + text: 'q2', + }, + { + value: '3', + text: 'q3', + }, + ]; + + const panelElem = _elem('div'); + _children(panelElem, [ + _select('Target', 'target-input', options, 0), + _checkboxes('Controls', 'controls-input', options, [2, 3]), + _text('Display', 'display-input', 'display-arg'), + ]); + + return panelElem; +}; + +const _elem = (tag: string): HTMLElement => document.createElement(tag); + +/** + * Append all child elements to a parent element + */ +const _children = (parentElem: HTMLElement, childElems: HTMLElement[]) => { + childElems.map((elem) => parentElem.appendChild(elem)); + return parentElem; +}; + +interface Option { + value: string; + text: string; +} + +const _select = (label: string, className: string, options: Option[], selectedIndex: number) => { + const optionElems = options.map(({ value, text }) => _option(value, text)); + const selectElem = _elem('select') as HTMLSelectElement; + _children(selectElem, optionElems); + selectElem.selectedIndex = selectedIndex; + + const labelElem = _elem('label') as HTMLLabelElement; + labelElem.textContent = label; + + const divElem = _elem('div') as HTMLDivElement; + divElem.className = className; + _children(divElem, [labelElem, selectElem]); + + return divElem; +}; + +const _option = (value: string, text: string) => { + const elem = _elem('option') as HTMLOptionElement; + elem.value = value; + elem.textContent = text; + return elem; +}; + +const _checkboxes = (label: string, className: string, options: Option[], selectedIndexes: number[]) => { + const checkboxElems = options.map((option, index) => { + const elem = _checkbox(option.value, option.text); + if (selectedIndexes.includes(index)) { + elem.querySelector('input')?.setAttribute('checked', 'true'); + } + return elem; + }); + + const labelElem = _elem('label'); + labelElem.textContent = label; + + const divElem = _elem('div') as HTMLDivElement; + divElem.className = className; + _children(divElem, [labelElem, ...checkboxElems]); + + return divElem; +}; + +const _checkbox = (value: string, text: string) => { + const inputElem = _elem('input') as HTMLInputElement; + inputElem.type = 'checkbox'; + inputElem.value = value; + + const labelElem = _elem('label') as HTMLLabelElement; + labelElem.textContent = text; + labelElem.prepend(inputElem); + return labelElem; +}; + +const _text = (label: string, className: string, value: string) => { + const labelElem = _elem('label') as HTMLLabelElement; + labelElem.textContent = label; + + const textElem = _elem('input') as HTMLInputElement; + textElem.type = 'text'; + textElem.value = value; + + const divElem = _elem('div'); + divElem.className = className; + _children(divElem, [labelElem, textElem]); + + return divElem; +}; + +export { addPanel }; From 22ff44b2add344226d2a492872c356a8660c0ee3 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 7 Jul 2022 12:48:20 -0400 Subject: [PATCH 053/108] Remove Context dependency --- src/editable.ts | 2 +- src/panel.ts | 12 +++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/editable.ts b/src/editable.ts index 8625f3b1..c89aa530 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -39,7 +39,7 @@ const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (ci selectedWire: null, }; - addPanel(context); + addPanel(container); _addStyles(container, _wireData(container)); _addDataWires(container); svg.appendChild(_dropzoneLayer(context)); diff --git a/src/panel.ts b/src/panel.ts index 45405920..7695f023 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -1,14 +1,8 @@ -import { Operation } from './circuit'; -import { Context, _equivOperation } from './editable'; - -const addPanel = (context: Context): void => { - const { container } = context; - - container.prepend(_panel(operation)); +const addPanel = (container: HTMLElement): void => { + container.prepend(_panel()); }; -const _panel = (operation: Operation | null) => { - console.log(operation); +const _panel = () => { const options: Option[] = [ { value: '0', From 16639dcf72bbfad7792c07593b5f4059d2ef5a2d Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 7 Jul 2022 18:59:44 -0400 Subject: [PATCH 054/108] Display data when gate is clicked --- src/editable.ts | 4 ++-- src/panel.ts | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/editable.ts b/src/editable.ts index c89aa530..e001ba16 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -39,7 +39,7 @@ const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (ci selectedWire: null, }; - addPanel(container); + addPanel(container, context.operations); _addStyles(container, _wireData(container)); _addDataWires(container); svg.appendChild(_dropzoneLayer(context)); @@ -301,7 +301,7 @@ const _addEvents = (context: Context) => { if (newSourceOperation != null) { _moveY(context.selectedWire, targetWire, newSourceOperation, context.wireData.length); const parentOperation = _equivParentOperation(context.selectedId, operations); - if (parentOperation) { + if (parentOperation != null) { parentOperation.targets = _targets(parentOperation); } } diff --git a/src/panel.ts b/src/panel.ts index 7695f023..d69ad201 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -1,5 +1,14 @@ -const addPanel = (container: HTMLElement): void => { +import { Operation } from './circuit'; +import { _equivOperation } from './editable'; + +const addPanel = (container: HTMLElement, operations: Operation[]): void => { container.prepend(_panel()); + container.querySelectorAll<SVGElement>('[data-id]').forEach((elem) => + elem.addEventListener('mousedown', () => { + const dataId = elem.getAttribute('data-id'); + console.log({ dataId, operation: _equivOperation(dataId, operations) }); + }), + ); }; const _panel = () => { From d45089b1d404412c844052506411336a1136dc61 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <37777232+aaronthangnguyen@users.noreply.github.com> Date: Thu, 7 Jul 2022 19:04:28 -0400 Subject: [PATCH 055/108] Sync to `main` (#73) * v 1.0.5 * Fixing jupyter viewer display (#70) Co-authored-by: Andres Paz <anpaz@microsoft.com> --- package.json | 2 +- quantum-viz/pyproject.toml | 2 +- quantum-viz/quantum_viz/widget.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index d9dbd88a..c138e1ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/quantum-viz.js", - "version": "1.0.4", + "version": "1.0.5", "description": "quantum-viz.js is a configurable tool for visualizing quantum circuits.", "main": "dist/qviz.min.js", "scripts": { diff --git a/quantum-viz/pyproject.toml b/quantum-viz/pyproject.toml index 2914cf61..960aff8e 100644 --- a/quantum-viz/pyproject.toml +++ b/quantum-viz/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "quantum-viz" -version = "1.0.4" +version = "1.0.5" description = "quantum-viz.js Python tools" authors = ["Microsoft Corporation <que-contacts@microsoft.com>"] license = "MIT" diff --git a/quantum-viz/quantum_viz/widget.py b/quantum-viz/quantum_viz/widget.py index 829a2a4d..3a33bba8 100644 --- a/quantum-viz/quantum_viz/widget.py +++ b/quantum-viz/quantum_viz/widget.py @@ -134,7 +134,7 @@ def html_str(self, uid: Optional[str] = None) -> str: def _ipython_display_(self) -> None: """Display the widget with IPython.""" viewer = HTML(self.html_str()) - display((viewer,)) + display(viewer) def browser_display(self) -> None: """Display the widget in the browser.""" From 48c21447ce3217852fde82b6fb18084ed874ee72 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 11 Jul 2022 15:36:24 -0400 Subject: [PATCH 056/108] Allow target edit --- package.json | 2 ++ src/editable.ts | 9 ++++---- src/index.ts | 2 ++ src/panel.ts | 59 +++++++++++++++++++++++++++---------------------- tsconfig.json | 1 + 5 files changed, 42 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index d9dbd88a..d103e7d4 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "license": "MIT", "devDependencies": { "@types/jest": "^26.0.4", + "@types/lodash": "^4.14.182", "@types/prettier": "2.6.0", "@typescript-eslint/eslint-plugin": "^3.9.0", "@typescript-eslint/parser": "^3.9.0", @@ -41,6 +42,7 @@ "eslint-plugin-jest": "^23.20.0", "eslint-plugin-prettier": "^3.1.4", "jest": "^26.6.3", + "lodash": "^4.17.21", "prettier": "2.6.0", "terser-webpack-plugin": "^4.1.0", "ts-jest": "^26.1.2", diff --git a/src/editable.ts b/src/editable.ts index e001ba16..f6e54776 100644 --- a/src/editable.ts +++ b/src/editable.ts @@ -1,9 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +import cloneDeep from 'lodash/cloneDeep'; +import isEqual from 'lodash/isEqual'; import { Circuit, Operation } from './circuit'; import { box } from './formatters/formatUtils'; -import { addPanel } from './panel'; import { Register } from './register'; import { Sqore } from './sqore'; @@ -38,8 +39,6 @@ const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (ci selectedId: null, selectedWire: null, }; - - addPanel(container, context.operations); _addStyles(container, _wireData(container)); _addDataWires(container); svg.appendChild(_dropzoneLayer(context)); @@ -284,6 +283,7 @@ const _addEvents = (context: Context) => { const dropzoneElems = dropzoneLayer.querySelectorAll<SVGRectElement>('.dropzone'); dropzoneElems.forEach((dropzoneElem) => { dropzoneElem.addEventListener('mouseup', (ev: MouseEvent) => { + const originalOperations = cloneDeep(operations); const targetId = dropzoneElem.getAttribute('data-dropzone-id'); const targetWire = dropzoneElem.getAttribute('data-dropzone-wire'); if ( @@ -305,8 +305,7 @@ const _addEvents = (context: Context) => { parentOperation.targets = _targets(parentOperation); } } - - renderFn(); + if (isEqual(originalOperations, operations) === false) renderFn(); }); }); }; diff --git a/src/index.ts b/src/index.ts index 56b35003..fdc0c9a2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ import { Sqore } from './sqore'; import { Circuit } from './circuit'; import { StyleConfig } from './styles'; +import { addPanel } from './panel'; /** * Render `circuit` into `container` at the specified layer depth. @@ -26,6 +27,7 @@ export const draw = ( const sqore = new Sqore(circuit, style); sqore.draw(container, renderDepth, isEditable, onCircuitChange); + addPanel(container, sqore); }; export { STYLES } from './styles'; diff --git a/src/panel.ts b/src/panel.ts index d69ad201..754759af 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -1,40 +1,34 @@ +import range from 'lodash/range'; import { Operation } from './circuit'; import { _equivOperation } from './editable'; +import { Sqore } from './sqore'; -const addPanel = (container: HTMLElement, operations: Operation[]): void => { - container.prepend(_panel()); - container.querySelectorAll<SVGElement>('[data-id]').forEach((elem) => +const addPanel = (container: HTMLElement, sqore: Sqore): void => { + const elems = container.querySelectorAll<SVGElement>('[data-id]'); + elems.forEach((elem) => elem.addEventListener('mousedown', () => { const dataId = elem.getAttribute('data-id'); - console.log({ dataId, operation: _equivOperation(dataId, operations) }); + const operation = _equivOperation(dataId, sqore.circuit.operations); + const newPanelElem = _panel(qubitSize, operation || undefined); + container.replaceChild(newPanelElem, panelElem); + panelElem = newPanelElem; }), ); + const qubitSize = sqore.circuit.qubits.length; + let panelElem = _panel(qubitSize); + container.prepend(panelElem); }; -const _panel = () => { - const options: Option[] = [ - { - value: '0', - text: 'q0', - }, - { - value: '1', - text: 'q1', - }, - { - value: '2', - text: 'q2', - }, - { - value: '3', - text: 'q3', - }, - ]; +const _panel = (qubitSize: number, operation?: Operation) => { + const options = range(qubitSize).map((i) => ({ value: `${i}`, text: `q${i}` })); + const target = operation?.targets[0].qId; + const controls = operation?.controls?.map((control) => control.qId); const panelElem = _elem('div'); + panelElem.className = 'panel'; _children(panelElem, [ - _select('Target', 'target-input', options, 0), - _checkboxes('Controls', 'controls-input', options, [2, 3]), + _select('Target', 'target-input', options, target || 0, operation), + _checkboxes('Controls', 'controls-input', options, controls || []), _text('Display', 'display-input', 'display-arg'), ]); @@ -56,7 +50,13 @@ interface Option { text: string; } -const _select = (label: string, className: string, options: Option[], selectedIndex: number) => { +const _select = ( + label: string, + className: string, + options: Option[], + selectedIndex: number, + operation?: Operation, +): HTMLElement => { const optionElems = options.map(({ value, text }) => _option(value, text)); const selectElem = _elem('select') as HTMLSelectElement; _children(selectElem, optionElems); @@ -69,6 +69,13 @@ const _select = (label: string, className: string, options: Option[], selectedIn divElem.className = className; _children(divElem, [labelElem, selectElem]); + selectElem.onchange = () => { + if (operation != null) { + Object.assign(operation.targets, [{ qId: selectElem.value }]); + console.log(operation); + } + }; + return divElem; }; diff --git a/tsconfig.json b/tsconfig.json index afc965bf..c3f66ab0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,7 @@ "declaration": true, "strict": true, "outDir": "lib", + "esModuleInterop": true }, "include": [ "src/**/*" From 123c86944eafea9e361c12d3aa28b4b77578b90c Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 11 Jul 2022 15:49:16 -0400 Subject: [PATCH 057/108] Change render mechanism --- src/sqore.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sqore.ts b/src/sqore.ts index 17934f74..b88db601 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -125,13 +125,13 @@ export class Sqore { // Create visualization components const composedSqore: ComposedSqore = this.compose(circuit); const svg: SVGElement = this.generateSvg(composedSqore); - container.innerHTML = ''; - container.appendChild(svg); + const previousSvg = container.querySelector('svg'); + previousSvg == null // + ? container.appendChild(svg) + : container.replaceChild(svg, previousSvg); this.addGateClickHandlers(container, circuit, isEditable, onCircuitChange); - if (isEditable) { - addEditable(container, this, onCircuitChange); - } + isEditable && addEditable(container, this, onCircuitChange); } /** From 863b7d27160e9338c4ec4e424ec1fb3aa41b9bc2 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 11 Jul 2022 16:27:38 -0400 Subject: [PATCH 058/108] use Reducer design pattern --- src/panel.ts | 51 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index 754759af..7b20d16d 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -19,6 +19,26 @@ const addPanel = (container: HTMLElement, sqore: Sqore): void => { container.prepend(panelElem); }; +interface Action { + type: string; + payload: unknown; +} + +const reducer = (initial: Operation | undefined, action: Action) => { + if (initial == null) return; + + switch (action.type) { + case 'TARGET': { + Object.assign(initial, { ...initial, targets: action.payload }); + } + case 'CONTROLS': { + Object.assign(initial, { ...initial, controls: action.payload }); + } + } + console.log(initial); + console.log('Re-rendering...'); +}; + const _panel = (qubitSize: number, operation?: Operation) => { const options = range(qubitSize).map((i) => ({ value: `${i}`, text: `q${i}` })); const target = operation?.targets[0].qId; @@ -28,7 +48,7 @@ const _panel = (qubitSize: number, operation?: Operation) => { panelElem.className = 'panel'; _children(panelElem, [ _select('Target', 'target-input', options, target || 0, operation), - _checkboxes('Controls', 'controls-input', options, controls || []), + _checkboxes('Controls', 'controls-input', options, controls || [], operation), _text('Display', 'display-input', 'display-arg'), ]); @@ -60,6 +80,7 @@ const _select = ( const optionElems = options.map(({ value, text }) => _option(value, text)); const selectElem = _elem('select') as HTMLSelectElement; _children(selectElem, optionElems); + operation == null && selectElem.setAttribute('disabled', 'true'); selectElem.selectedIndex = selectedIndex; const labelElem = _elem('label') as HTMLLabelElement; @@ -70,10 +91,7 @@ const _select = ( _children(divElem, [labelElem, selectElem]); selectElem.onchange = () => { - if (operation != null) { - Object.assign(operation.targets, [{ qId: selectElem.value }]); - console.log(operation); - } + reducer(operation, { type: 'TARGET', payload: [{ qId: selectElem.value }] }); }; return divElem; @@ -86,12 +104,27 @@ const _option = (value: string, text: string) => { return elem; }; -const _checkboxes = (label: string, className: string, options: Option[], selectedIndexes: number[]) => { +const _checkboxes = ( + label: string, + className: string, + options: Option[], + selectedIndexes: number[], + operation?: Operation, +) => { const checkboxElems = options.map((option, index) => { const elem = _checkbox(option.value, option.text); - if (selectedIndexes.includes(index)) { - elem.querySelector('input')?.setAttribute('checked', 'true'); - } + const inputElem = elem.querySelector('input') as HTMLInputElement; + selectedIndexes.includes(index) && inputElem.setAttribute('checked', 'true'); + operation == null && inputElem.setAttribute('disabled', 'true'); + + inputElem.onchange = () => { + const checkedElems = Array.from(divElem.querySelectorAll<HTMLInputElement>('input:checked')); + const newControls = checkedElems.map((elem) => ({ + qId: elem.value, + })); + reducer(operation, { type: 'CONTROLS', payload: newControls }); + }; + return elem; }); From 90b29bc62cac43196cafdb94be0b04ad701d1ac3 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 11 Jul 2022 19:13:43 -0400 Subject: [PATCH 059/108] Add basic rendering --- src/panel.ts | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index 7b20d16d..7ffad9bd 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -9,13 +9,14 @@ const addPanel = (container: HTMLElement, sqore: Sqore): void => { elem.addEventListener('mousedown', () => { const dataId = elem.getAttribute('data-id'); const operation = _equivOperation(dataId, sqore.circuit.operations); - const newPanelElem = _panel(qubitSize, operation || undefined); + const newPanelElem = _panel(qubitSize, dispatch, operation || undefined); container.replaceChild(newPanelElem, panelElem); panelElem = newPanelElem; }), ); + const dispatch = reducer(container, sqore); const qubitSize = sqore.circuit.qubits.length; - let panelElem = _panel(qubitSize); + let panelElem = _panel(qubitSize, dispatch); container.prepend(panelElem); }; @@ -24,7 +25,7 @@ interface Action { payload: unknown; } -const reducer = (initial: Operation | undefined, action: Action) => { +const reducer = (container: HTMLElement, sqore: Sqore) => (initial: Operation | undefined, action: Action) => { if (initial == null) return; switch (action.type) { @@ -35,11 +36,10 @@ const reducer = (initial: Operation | undefined, action: Action) => { Object.assign(initial, { ...initial, controls: action.payload }); } } - console.log(initial); - console.log('Re-rendering...'); + sqore.draw(container); }; -const _panel = (qubitSize: number, operation?: Operation) => { +const _panel = (qubitSize: number, dispatch: Dispatch, operation?: Operation) => { const options = range(qubitSize).map((i) => ({ value: `${i}`, text: `q${i}` })); const target = operation?.targets[0].qId; const controls = operation?.controls?.map((control) => control.qId); @@ -47,8 +47,8 @@ const _panel = (qubitSize: number, operation?: Operation) => { const panelElem = _elem('div'); panelElem.className = 'panel'; _children(panelElem, [ - _select('Target', 'target-input', options, target || 0, operation), - _checkboxes('Controls', 'controls-input', options, controls || [], operation), + _select('Target', 'target-input', options, target || 0, dispatch, operation), + _checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), _text('Display', 'display-input', 'display-arg'), ]); @@ -70,11 +70,16 @@ interface Option { text: string; } +interface Dispatch { + (initial: Operation | undefined, action: Action): void; +} + const _select = ( label: string, className: string, options: Option[], selectedIndex: number, + dispatch: Dispatch, operation?: Operation, ): HTMLElement => { const optionElems = options.map(({ value, text }) => _option(value, text)); @@ -91,7 +96,7 @@ const _select = ( _children(divElem, [labelElem, selectElem]); selectElem.onchange = () => { - reducer(operation, { type: 'TARGET', payload: [{ qId: selectElem.value }] }); + dispatch(operation, { type: 'TARGET', payload: [{ qId: selectElem.value }] }); }; return divElem; @@ -109,6 +114,7 @@ const _checkboxes = ( className: string, options: Option[], selectedIndexes: number[], + dispatch: Dispatch, operation?: Operation, ) => { const checkboxElems = options.map((option, index) => { @@ -122,7 +128,7 @@ const _checkboxes = ( const newControls = checkedElems.map((elem) => ({ qId: elem.value, })); - reducer(operation, { type: 'CONTROLS', payload: newControls }); + dispatch(operation, { type: 'CONTROLS', payload: newControls }); }; return elem; From 5b51043afd2c0ca8f8e2b9fd6944151ecf3241d9 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <37777232+aaronthangnguyen@users.noreply.github.com> Date: Wed, 13 Jul 2022 15:12:26 -0400 Subject: [PATCH 060/108] Add extensions feature (#76) * First commit * Fix mutation * Fix persistence in panel * Allow editing displayArgs --- example/script.js | 26 ++++--- src/{editable.ts => draggable.ts} | 23 ++---- src/index.ts | 15 +--- src/panel.ts | 79 ++++++++++++++------- src/sqore.ts | 112 +++++++++++++++++------------- 5 files changed, 139 insertions(+), 116 deletions(-) rename src/{editable.ts => draggable.ts} (96%) diff --git a/example/script.js b/example/script.js index 9c15533c..d65eb0d7 100644 --- a/example/script.js +++ b/example/script.js @@ -7,30 +7,38 @@ if (typeof qviz != 'undefined') { /* These examples shows how to draw circuits into containers. */ const entangleDiv = document.getElementById('entangle'); if (entangleDiv != null) { - qviz.draw(entangle, entangleDiv, qviz.STYLES['Default'], 0, true); + qviz.create(entangle) // + .useDraggable() + .usePanel() + .draw(entangleDiv); } const sampleDiv = document.getElementById('sample'); if (sampleDiv != null) { - const isEditable = true; - const onCircuitChange = (circuit) => { - console.log('New circuit ↓'); - console.log(circuit); - }; /* Pass in isEditable = true to allow circuit to be editable */ /* Pass in onCircuitChange to trigger callback function whenever there is a change in circuit */ - qviz.draw(sample, sampleDiv, qviz.STYLES['Default'], 0, isEditable, onCircuitChange); + // qviz.draw(sample, sampleDiv, qviz.STYLES['Default'], 0, isEditable, onCircuitChange); + qviz.create(sample) // + .useDraggable() + .usePanel() + .useOnCircuitChange((circuit) => { + console.log('New circuit ↓'); + console.log(circuit); + }) + .draw(sampleDiv); } const teleportDiv = document.getElementById('teleport'); if (teleportDiv != null) { - qviz.draw(teleport, teleportDiv, qviz.STYLES['Default'], 0, true); + qviz.create(teleport) // + .draw(teleportDiv); } const groverDiv = document.getElementById('grover'); if (groverDiv != null) { - qviz.draw(grover, groverDiv, qviz.STYLES['Default']); + qviz.create(grover) // + .draw(groverDiv); } } else { document.getElementById('group').remove(); diff --git a/src/editable.ts b/src/draggable.ts similarity index 96% rename from src/editable.ts rename to src/draggable.ts index f6e54776..5ab8c854 100644 --- a/src/editable.ts +++ b/src/draggable.ts @@ -3,7 +3,7 @@ import cloneDeep from 'lodash/cloneDeep'; import isEqual from 'lodash/isEqual'; -import { Circuit, Operation } from './circuit'; +import { Operation } from './circuit'; import { box } from './formatters/formatUtils'; import { Register } from './register'; import { Sqore } from './sqore'; @@ -26,7 +26,8 @@ interface Context { * @param sqore Sqore object * @param onCircuitChange User-provided callback function triggered when circuit is changed */ -const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (circuit: Circuit) => void): void => { +const extensionDraggable = (container: HTMLElement, sqore: Sqore, useRender: () => void): void => { + console.log('Draggable extension is running'); const svg = container.querySelector('svg') as SVGElement; const context: Context = { @@ -34,7 +35,7 @@ const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (ci svg, operations: sqore.circuit.operations, wireData: _wireData(container), - renderFn: _renderFn(container, sqore, onCircuitChange), + renderFn: useRender, paddingY: 20, selectedId: null, selectedWire: null, @@ -518,20 +519,6 @@ const _lastIndex = (dataId: string): number | undefined => { return _indexes(dataId).pop(); }; -/** - * Return a render function with the onCircuitChange callback attached to it - */ -const _renderFn = ( - container: HTMLElement, - sqore: Sqore, - onCircuitChange?: (circuit: Circuit) => void, -): (() => void) => { - return () => { - sqore.draw(container, 0, true, onCircuitChange); - if (onCircuitChange) onCircuitChange(sqore.circuit); - }; -}; - /** * Object exported for unit testing */ @@ -555,4 +542,4 @@ const exportedForTesting = { _lastIndex, }; -export { addEditable, Context, _equivOperation, exportedForTesting }; +export { extensionDraggable, Context, _equivOperation, exportedForTesting }; diff --git a/src/index.ts b/src/index.ts index fdc0c9a2..2d384b84 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,7 +4,6 @@ import { Sqore } from './sqore'; import { Circuit } from './circuit'; import { StyleConfig } from './styles'; -import { addPanel } from './panel'; /** * Render `circuit` into `container` at the specified layer depth. @@ -16,18 +15,8 @@ import { addPanel } from './panel'; * @param isEditable Optional value enabling/disabling editable feature * @param onCircuitChange Optional function to trigger when changing elements in circuit */ -export const draw = ( - circuit: Circuit, - container: HTMLElement, - style: StyleConfig | string = {}, - renderDepth = 0, - isEditable?: boolean, - onCircuitChange?: (circuit: Circuit) => void, -): void => { - const sqore = new Sqore(circuit, style); - - sqore.draw(container, renderDepth, isEditable, onCircuitChange); - addPanel(container, sqore); +export const create = (circuit: Circuit, style: StyleConfig | string = {}): Sqore => { + return new Sqore(circuit, style); }; export { STYLES } from './styles'; diff --git a/src/panel.ts b/src/panel.ts index 7ffad9bd..4f08b715 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -1,23 +1,34 @@ import range from 'lodash/range'; import { Operation } from './circuit'; -import { _equivOperation } from './editable'; +import { _equivOperation } from './draggable'; +import { Register } from './register'; import { Sqore } from './sqore'; -const addPanel = (container: HTMLElement, sqore: Sqore): void => { +interface Context { + operation: Operation | undefined; +} + +const context: Context = { + operation: undefined, +}; + +const extensionPanel = (container: HTMLElement, sqore: Sqore, useRender: () => void): void => { const elems = container.querySelectorAll<SVGElement>('[data-id]'); elems.forEach((elem) => elem.addEventListener('mousedown', () => { const dataId = elem.getAttribute('data-id'); const operation = _equivOperation(dataId, sqore.circuit.operations); - const newPanelElem = _panel(qubitSize, dispatch, operation || undefined); + context.operation = operation || undefined; + const newPanelElem = _panel(qubitSize, dispatch, context.operation); container.replaceChild(newPanelElem, panelElem); panelElem = newPanelElem; }), ); - const dispatch = reducer(container, sqore); + const dispatch = reducer(container, sqore, useRender); const qubitSize = sqore.circuit.qubits.length; - let panelElem = _panel(qubitSize, dispatch); - container.prepend(panelElem); + let panelElem = _panel(qubitSize, dispatch, context.operation); + const prevPanelElem = container.querySelector('.panel'); + prevPanelElem ? container.replaceChild(panelElem, prevPanelElem) : container.prepend(panelElem); }; interface Action { @@ -25,19 +36,27 @@ interface Action { payload: unknown; } -const reducer = (container: HTMLElement, sqore: Sqore) => (initial: Operation | undefined, action: Action) => { - if (initial == null) return; - - switch (action.type) { - case 'TARGET': { - Object.assign(initial, { ...initial, targets: action.payload }); +const reducer = + (_container: HTMLElement, _sqore: Sqore, useRender: () => void) => + (operation: Operation | undefined, action: Action) => { + if (operation == undefined) return; + + switch (action.type) { + case 'TARGET': { + operation.targets = action.payload as Register[]; + break; + } + case 'CONTROLS': { + operation.controls = action.payload as Register[]; + break; + } + case 'DISPLAY_ARGS': { + operation.displayArgs = action.payload as string; + break; + } } - case 'CONTROLS': { - Object.assign(initial, { ...initial, controls: action.payload }); - } - } - sqore.draw(container); -}; + useRender(); + }; const _panel = (qubitSize: number, dispatch: Dispatch, operation?: Operation) => { const options = range(qubitSize).map((i) => ({ value: `${i}`, text: `q${i}` })); @@ -49,7 +68,7 @@ const _panel = (qubitSize: number, dispatch: Dispatch, operation?: Operation) => _children(panelElem, [ _select('Target', 'target-input', options, target || 0, dispatch, operation), _checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), - _text('Display', 'display-input', 'display-arg'), + _text('Display', 'display-input', dispatch, operation), ]); return panelElem; @@ -71,7 +90,7 @@ interface Option { } interface Dispatch { - (initial: Operation | undefined, action: Action): void; + (operation: Operation | undefined, action: Action): void; } const _select = ( @@ -85,7 +104,7 @@ const _select = ( const optionElems = options.map(({ value, text }) => _option(value, text)); const selectElem = _elem('select') as HTMLSelectElement; _children(selectElem, optionElems); - operation == null && selectElem.setAttribute('disabled', 'true'); + operation == undefined && selectElem.setAttribute('disabled', 'true'); selectElem.selectedIndex = selectedIndex; const labelElem = _elem('label') as HTMLLabelElement; @@ -96,7 +115,7 @@ const _select = ( _children(divElem, [labelElem, selectElem]); selectElem.onchange = () => { - dispatch(operation, { type: 'TARGET', payload: [{ qId: selectElem.value }] }); + dispatch(operation, { type: 'TARGET', payload: [{ qId: parseInt(selectElem.value) }] }); }; return divElem; @@ -121,12 +140,12 @@ const _checkboxes = ( const elem = _checkbox(option.value, option.text); const inputElem = elem.querySelector('input') as HTMLInputElement; selectedIndexes.includes(index) && inputElem.setAttribute('checked', 'true'); - operation == null && inputElem.setAttribute('disabled', 'true'); + operation == undefined && inputElem.setAttribute('disabled', 'true'); inputElem.onchange = () => { const checkedElems = Array.from(divElem.querySelectorAll<HTMLInputElement>('input:checked')); const newControls = checkedElems.map((elem) => ({ - qId: elem.value, + qId: parseInt(elem.value), })); dispatch(operation, { type: 'CONTROLS', payload: newControls }); }; @@ -155,13 +174,19 @@ const _checkbox = (value: string, text: string) => { return labelElem; }; -const _text = (label: string, className: string, value: string) => { +const _text = (label: string, className: string, dispatch: Dispatch, operation?: Operation) => { const labelElem = _elem('label') as HTMLLabelElement; labelElem.textContent = label; const textElem = _elem('input') as HTMLInputElement; + operation == undefined && textElem.setAttribute('disabled', 'true'); textElem.type = 'text'; - textElem.value = value; + textElem.value = operation?.displayArgs || ''; + textElem.setAttribute('autofocus', 'true'); + + textElem.onchange = () => { + dispatch(operation, { type: 'DISPLAY_ARGS', payload: textElem.value }); + }; const divElem = _elem('div'); divElem.className = className; @@ -170,4 +195,4 @@ const _text = (label: string, className: string, value: string) => { return divElem; }; -export { addPanel }; +export { extensionPanel }; diff --git a/src/sqore.ts b/src/sqore.ts index b88db601..1433e54e 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -3,7 +3,8 @@ import { Circuit, ConditionalRender, Operation } from './circuit'; import { svgNS } from './constants'; -import { addEditable } from './editable'; +import { extensionDraggable } from './draggable'; +import { extensionPanel } from './panel'; import { formatGates } from './formatters/gateFormatter'; import { formatInputs } from './formatters/inputFormatter'; import { formatRegisters } from './formatters/registerFormatter'; @@ -32,6 +33,10 @@ type GateRegistry = { [id: string]: Operation; }; +type Extension = { + (container: HTMLElement, sqore: Sqore, useRender: () => void): void; +}; + /** * Entrypoint class for rendering circuit visualizations. */ @@ -39,6 +44,8 @@ export class Sqore { circuit: Circuit; style: StyleConfig = {}; gateRegistry: GateRegistry = {}; + extensions: Extension[] = []; + renderDepth = 0; /** * Initializes Sqore object with custom styles. @@ -49,6 +56,7 @@ export class Sqore { constructor(circuit: Circuit, style: StyleConfig | string = {}) { this.circuit = circuit; this.style = this.getStyle(style); + this.extensions = []; } /** @@ -56,37 +64,15 @@ export class Sqore { * * @param container HTML element for rendering visualization into. * @param renderDepth Initial layer depth at which to render gates. - * @param isEditable Optional value enabling/disabling editable feature - * @param onCircuitChange Optional function to trigger when changing elements in circuit */ - draw( - container: HTMLElement, - renderDepth = 0, - isEditable?: boolean, - onCircuitChange?: (circuit: Circuit) => void, - ): void { + draw(container: HTMLElement, renderDepth = 0): Sqore { // Inject into container if (container == null) throw new Error(`Container not provided.`); - // Create copy of circuit to prevent mutation - const circuit: Circuit = JSON.parse(JSON.stringify(this.circuit)); - - // Assign unique IDs to each operation - circuit.operations.forEach((op, i) => this.fillGateRegistry(op, i.toString())); - - // Render operations at starting at given depth - circuit.operations = this.selectOpsAtDepth(circuit.operations, renderDepth); + this.renderDepth = renderDepth; + this.renderCircuit(container); - // If only one top-level operation, expand automatically: - if ( - circuit.operations.length == 1 && - circuit.operations[0].dataAttributes != null && - circuit.operations[0].dataAttributes.hasOwnProperty('id') - ) { - const id: string = circuit.operations[0].dataAttributes['id']; - this.expandOperation(circuit.operations, id); - } - this.renderCircuit(container, circuit, isEditable, onCircuitChange); + return this; } /** @@ -116,12 +102,27 @@ export class Sqore { * @param isEditable Optional value enabling/disabling editable feature * @param onCircuitChange Optional function to trigger when changing elements in circuit */ - private renderCircuit( - container: HTMLElement, - circuit: Circuit, - isEditable?: boolean, - onCircuitChange?: (circuit: Circuit) => void, - ): void { + private renderCircuit(container: HTMLElement): void { + // Create copy of circuit to prevent mutation + const circuit: Circuit = JSON.parse(JSON.stringify(this.circuit)); + const renderDepth = this.renderDepth; + + // Assign unique IDs to each operation + circuit.operations.forEach((op, i) => this.fillGateRegistry(op, i.toString())); + + // Render operations at starting at given depth + circuit.operations = this.selectOpsAtDepth(circuit.operations, renderDepth); + + // If only one top-level operation, expand automatically: + if ( + circuit.operations.length == 1 && + circuit.operations[0].dataAttributes != null && + circuit.operations[0].dataAttributes.hasOwnProperty('id') + ) { + const id: string = circuit.operations[0].dataAttributes['id']; + this.expandOperation(circuit.operations, id); + } + // Create visualization components const composedSqore: ComposedSqore = this.compose(circuit); const svg: SVGElement = this.generateSvg(composedSqore); @@ -129,9 +130,12 @@ export class Sqore { previousSvg == null // ? container.appendChild(svg) : container.replaceChild(svg, previousSvg); - this.addGateClickHandlers(container, circuit, isEditable, onCircuitChange); + this.addGateClickHandlers(container, circuit); - isEditable && addEditable(container, this, onCircuitChange); + // Run extensions after every render or re-render + const extensions = this.extensions; + extensions != null && + extensions.map((extension) => extension(container, this, () => this.renderCircuit(container))); } /** @@ -251,14 +255,9 @@ export class Sqore { * @param onCircuitChange Optional function to trigger when changing elements in circuit * */ - private addGateClickHandlers( - container: HTMLElement, - circuit: Circuit, - isEditable?: boolean, - onCircuitChange?: (circuit: Circuit) => void, - ): void { + private addGateClickHandlers(container: HTMLElement, circuit: Circuit): void { this.addClassicalControlHandlers(container); - this.addZoomHandlers(container, circuit, isEditable, onCircuitChange); + this.addZoomHandlers(container, circuit); } /** @@ -318,12 +317,7 @@ export class Sqore { * @param onCircuitChange Optional function to trigger when changing elements in circuit * */ - private addZoomHandlers( - container: HTMLElement, - circuit: Circuit, - isEditable?: boolean, - onCircuitChange?: (circuit: Circuit) => void, - ): void { + private addZoomHandlers(container: HTMLElement, circuit: Circuit): void { container.querySelectorAll('.gate .gate-control').forEach((ctrl) => { // Zoom in on clicked gate ctrl.addEventListener('click', (ev: Event) => { @@ -334,7 +328,7 @@ export class Sqore { } else if (ctrl.classList.contains('gate-expand')) { this.expandOperation(circuit.operations, gateId); } - this.renderCircuit(container, circuit, isEditable, onCircuitChange); + this.renderCircuit(container); ev.stopPropagation(); } }); @@ -379,4 +373,24 @@ export class Sqore { } }); } + + public useDraggable(): Sqore { + this.extensions.push(extensionDraggable); + return this; + } + + public usePanel(): Sqore { + this.extensions.push(extensionPanel); + return this; + } + + public useOnCircuitChange(callback: (circuit: Circuit) => void): Sqore { + const extensionOnCircuitChange = ( + _container: HTMLElement, // + _sqore: Sqore, + _useRender: () => void, + ) => callback(this.circuit); + this.extensions.push(extensionOnCircuitChange); + return this; + } } From 2a5c35efc8ce9ec88010b9322786ef118e86ad58 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <37777232+aaronthangnguyen@users.noreply.github.com> Date: Wed, 13 Jul 2022 15:20:41 -0400 Subject: [PATCH 061/108] Sync with `main` (#77) * v 1.0.5 * Fixing jupyter viewer display (#70) Co-authored-by: Andres Paz <anpaz@microsoft.com> From 473914ad69e7d331e6e18d50c33b71806adbdde6 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 13 Jul 2022 17:22:06 -0400 Subject: [PATCH 062/108] Add styles --- example/index.html | 1 + src/draggable.ts | 13 +------------ src/panel.ts | 14 +++++++++++++- src/sqore.ts | 26 ++++++++++++-------------- src/styles.ts | 27 +++++++++++++++++++++++++-- 5 files changed, 52 insertions(+), 29 deletions(-) diff --git a/example/index.html b/example/index.html index e612d7b8..196a80c5 100644 --- a/example/index.html +++ b/example/index.html @@ -11,6 +11,7 @@ <script src="./script.js" defer></script> <style> body { + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; display: flex; justify-content: center; } diff --git a/src/draggable.ts b/src/draggable.ts index 5ab8c854..93c43f3e 100644 --- a/src/draggable.ts +++ b/src/draggable.ts @@ -27,7 +27,6 @@ interface Context { * @param onCircuitChange User-provided callback function triggered when circuit is changed */ const extensionDraggable = (container: HTMLElement, sqore: Sqore, useRender: () => void): void => { - console.log('Draggable extension is running'); const svg = container.querySelector('svg') as SVGElement; const context: Context = { @@ -212,15 +211,6 @@ const _equivDataId = (elem: SVGElement) => { return gateElem != null ? gateElem.getAttribute('data-id') : null; }; -/** - * Disable contextmenu default behaviors - */ -const _addContextMenuEvents = (container: HTMLElement) => { - container.addEventListener('contextmenu', (ev: MouseEvent) => { - ev.preventDefault(); - }); -}; - /** * Add events specifically for dropzoneLayer */ @@ -260,7 +250,6 @@ const _addEvents = (context: Context) => { const { container, operations, renderFn } = context; const dropzoneLayer = container.querySelector('.dropzone-layer') as SVGGElement; - _addContextMenuEvents(container); _addDropzoneLayerEvents(container, dropzoneLayer); _addDocumentEvents(context); @@ -542,4 +531,4 @@ const exportedForTesting = { _lastIndex, }; -export { extensionDraggable, Context, _equivOperation, exportedForTesting }; +export { extensionDraggable, Context, _equivOperation, _equivGateElem, exportedForTesting }; diff --git a/src/panel.ts b/src/panel.ts index 4f08b715..2b1f1f52 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -43,7 +43,8 @@ const reducer = switch (action.type) { case 'TARGET': { - operation.targets = action.payload as Register[]; + const payload = action.payload as Register[]; + operation.targets = payload; break; } case 'CONTROLS': { @@ -66,6 +67,7 @@ const _panel = (qubitSize: number, dispatch: Dispatch, operation?: Operation) => const panelElem = _elem('div'); panelElem.className = 'panel'; _children(panelElem, [ + _title('EDIT'), _select('Target', 'target-input', options, target || 0, dispatch, operation), _checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), _text('Display', 'display-input', dispatch, operation), @@ -84,6 +86,13 @@ const _children = (parentElem: HTMLElement, childElems: HTMLElement[]) => { return parentElem; }; +const _title = (text: string) => { + const elem = _elem('h1'); + elem.className = 'title'; + elem.innerText = text; + return elem; +}; + interface Option { value: string; text: string; @@ -108,6 +117,7 @@ const _select = ( selectElem.selectedIndex = selectedIndex; const labelElem = _elem('label') as HTMLLabelElement; + labelElem.className = 'block'; labelElem.textContent = label; const divElem = _elem('div') as HTMLDivElement; @@ -154,6 +164,7 @@ const _checkboxes = ( }); const labelElem = _elem('label'); + labelElem.className = 'block'; labelElem.textContent = label; const divElem = _elem('div') as HTMLDivElement; @@ -176,6 +187,7 @@ const _checkbox = (value: string, text: string) => { const _text = (label: string, className: string, dispatch: Dispatch, operation?: Operation) => { const labelElem = _elem('label') as HTMLLabelElement; + labelElem.className = 'block'; labelElem.textContent = label; const textElem = _elem('input') as HTMLInputElement; diff --git a/src/sqore.ts b/src/sqore.ts index 1433e54e..0300c5d5 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -99,38 +99,36 @@ export class Sqore { * * @param container HTML element for rendering visualization into. * @param circuit Circuit object to be rendered. - * @param isEditable Optional value enabling/disabling editable feature - * @param onCircuitChange Optional function to trigger when changing elements in circuit */ - private renderCircuit(container: HTMLElement): void { + private renderCircuit(container: HTMLElement, circuit?: Circuit): void { // Create copy of circuit to prevent mutation - const circuit: Circuit = JSON.parse(JSON.stringify(this.circuit)); + const _circuit: Circuit = circuit ?? JSON.parse(JSON.stringify(this.circuit)); const renderDepth = this.renderDepth; // Assign unique IDs to each operation - circuit.operations.forEach((op, i) => this.fillGateRegistry(op, i.toString())); + _circuit.operations.forEach((op, i) => this.fillGateRegistry(op, i.toString())); // Render operations at starting at given depth - circuit.operations = this.selectOpsAtDepth(circuit.operations, renderDepth); + _circuit.operations = this.selectOpsAtDepth(_circuit.operations, renderDepth); // If only one top-level operation, expand automatically: if ( - circuit.operations.length == 1 && - circuit.operations[0].dataAttributes != null && - circuit.operations[0].dataAttributes.hasOwnProperty('id') + _circuit.operations.length == 1 && + _circuit.operations[0].dataAttributes != null && + _circuit.operations[0].dataAttributes.hasOwnProperty('id') ) { - const id: string = circuit.operations[0].dataAttributes['id']; - this.expandOperation(circuit.operations, id); + const id: string = _circuit.operations[0].dataAttributes['id']; + this.expandOperation(_circuit.operations, id); } // Create visualization components - const composedSqore: ComposedSqore = this.compose(circuit); + const composedSqore: ComposedSqore = this.compose(_circuit); const svg: SVGElement = this.generateSvg(composedSqore); const previousSvg = container.querySelector('svg'); previousSvg == null // ? container.appendChild(svg) : container.replaceChild(svg, previousSvg); - this.addGateClickHandlers(container, circuit); + this.addGateClickHandlers(container, _circuit); // Run extensions after every render or re-render const extensions = this.extensions; @@ -328,7 +326,7 @@ export class Sqore { } else if (ctrl.classList.contains('gate-expand')) { this.expandOperation(circuit.operations, gateId); } - this.renderCircuit(container); + this.renderCircuit(container, circuit); ev.stopPropagation(); } }); diff --git a/src/styles.ts b/src/styles.ts index 06e7d787..764ed6e2 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -96,7 +96,8 @@ export const style = (customStyle: StyleConfig = {}): string => { return `${_defaultGates(styleConfig)} ${_classicallyControlledGates(styleConfig)} ${_expandCollapse} - ${_editable}`; + ${_draggable} + ${_panel}`; }; const _defaultGates = (styleConfig: StyleConfig): string => ` @@ -236,7 +237,7 @@ const _expandCollapse = ` transition: opacity 1s; }`; -const _editable = ` +const _draggable = ` text { user-select: none; pointer-events: none; @@ -262,3 +263,25 @@ const _editable = ` cursor: copy; } `; + +const _panel = ` + .container { + display: flex; + } + .panel { + display: flex; + flex-direction: column; + border: solid 2px black; + padding: 8px; + } + .title { + margin: 0 0 4px; + font-size: 1.2rem; + } + .block { + display: block; + } + .target-input, .controls-input, .display-input { + margin-bottom: 8px; + } +`; From acae20311964151f5267f7734c6cb09fa75be063 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 20 Jul 2022 10:55:30 -0400 Subject: [PATCH 063/108] Fix context --- src/panel.ts | 91 +++++++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index 2b1f1f52..41e3e19f 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -6,29 +6,35 @@ import { Sqore } from './sqore'; interface Context { operation: Operation | undefined; + registerSize: number; } const context: Context = { operation: undefined, + registerSize: 0, }; -const extensionPanel = (container: HTMLElement, sqore: Sqore, useRender: () => void): void => { +const extensionPanel = (container: HTMLElement, sqore: Sqore, useRefresh: () => void): void => { const elems = container.querySelectorAll<SVGElement>('[data-id]'); elems.forEach((elem) => elem.addEventListener('mousedown', () => { const dataId = elem.getAttribute('data-id'); const operation = _equivOperation(dataId, sqore.circuit.operations); context.operation = operation || undefined; - const newPanelElem = _panel(qubitSize, dispatch, context.operation); + context.registerSize = sqore.circuit.qubits.length; + const newPanelElem = _panel(dispatch, context); container.replaceChild(newPanelElem, panelElem); panelElem = newPanelElem; }), ); - const dispatch = reducer(container, sqore, useRender); - const qubitSize = sqore.circuit.qubits.length; - let panelElem = _panel(qubitSize, dispatch, context.operation); + + const dispatch = update(context, useRefresh); + + let panelElem = _panel(dispatch, context); const prevPanelElem = container.querySelector('.panel'); - prevPanelElem ? container.replaceChild(panelElem, prevPanelElem) : container.prepend(panelElem); + prevPanelElem // + ? container.replaceChild(panelElem, prevPanelElem) + : container.prepend(panelElem); }; interface Action { @@ -36,44 +42,49 @@ interface Action { payload: unknown; } -const reducer = - (_container: HTMLElement, _sqore: Sqore, useRender: () => void) => - (operation: Operation | undefined, action: Action) => { - if (operation == undefined) return; - - switch (action.type) { - case 'TARGET': { - const payload = action.payload as Register[]; - operation.targets = payload; - break; - } - case 'CONTROLS': { - operation.controls = action.payload as Register[]; - break; - } - case 'DISPLAY_ARGS': { - operation.displayArgs = action.payload as string; - break; - } +const update = (context: Context, useRefresh: () => void) => (action: Action) => { + switch (action.type) { + case 'TARGET': { + const { operation } = context; + const payload = action.payload as Register[]; + operation && (operation.targets = payload); + break; } - useRender(); - }; - -const _panel = (qubitSize: number, dispatch: Dispatch, operation?: Operation) => { - const options = range(qubitSize).map((i) => ({ value: `${i}`, text: `q${i}` })); - const target = operation?.targets[0].qId; - const controls = operation?.controls?.map((control) => control.qId); + case 'CONTROLS': { + const { operation } = context; + operation && (operation.controls = action.payload as Register[]); + break; + } + case 'DISPLAY_ARGS': { + const { operation } = context; + operation && (operation.displayArgs = action.payload as string); + break; + } + } + useRefresh(); +}; +const _panel = (dispatch: Dispatch, context: Context) => { const panelElem = _elem('div'); panelElem.className = 'panel'; - _children(panelElem, [ + _children(panelElem, editPanel(dispatch, context)); + + return panelElem; +}; + +// const addPanel = () => {}; + +const editPanel = (dispatch: Dispatch, context: Context) => { + const { operation, registerSize } = context; + const options = range(registerSize).map((i) => ({ value: `${i}`, text: `q${i}` })); + const target = operation?.targets[0].qId; + const controls = operation?.controls?.map((control) => control.qId); + return [ _title('EDIT'), _select('Target', 'target-input', options, target || 0, dispatch, operation), _checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), _text('Display', 'display-input', dispatch, operation), - ]); - - return panelElem; + ]; }; const _elem = (tag: string): HTMLElement => document.createElement(tag); @@ -99,7 +110,7 @@ interface Option { } interface Dispatch { - (operation: Operation | undefined, action: Action): void; + (action: Action): void; } const _select = ( @@ -125,7 +136,7 @@ const _select = ( _children(divElem, [labelElem, selectElem]); selectElem.onchange = () => { - dispatch(operation, { type: 'TARGET', payload: [{ qId: parseInt(selectElem.value) }] }); + dispatch({ type: 'TARGET', payload: [{ qId: parseInt(selectElem.value) }] }); }; return divElem; @@ -157,7 +168,7 @@ const _checkboxes = ( const newControls = checkedElems.map((elem) => ({ qId: parseInt(elem.value), })); - dispatch(operation, { type: 'CONTROLS', payload: newControls }); + dispatch({ type: 'CONTROLS', payload: newControls }); }; return elem; @@ -197,7 +208,7 @@ const _text = (label: string, className: string, dispatch: Dispatch, operation?: textElem.setAttribute('autofocus', 'true'); textElem.onchange = () => { - dispatch(operation, { type: 'DISPLAY_ARGS', payload: textElem.value }); + dispatch({ type: 'DISPLAY_ARGS', payload: textElem.value }); }; const divElem = _elem('div'); From 72357ba8873d584638e319fdbc5389b55419e54e Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 20 Jul 2022 11:49:23 -0400 Subject: [PATCH 064/108] Allow basic operation appending --- src/panel.ts | 99 ++++++++++++++++++++++++++++++++------------------- src/styles.ts | 3 +- 2 files changed, 64 insertions(+), 38 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index 41e3e19f..4f021993 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -5,11 +5,13 @@ import { Register } from './register'; import { Sqore } from './sqore'; interface Context { + operations: Operation[]; operation: Operation | undefined; registerSize: number; } -const context: Context = { +let context: Context = { + operations: [], operation: undefined, registerSize: 0, }; @@ -21,16 +23,18 @@ const extensionPanel = (container: HTMLElement, sqore: Sqore, useRefresh: () => const dataId = elem.getAttribute('data-id'); const operation = _equivOperation(dataId, sqore.circuit.operations); context.operation = operation || undefined; - context.registerSize = sqore.circuit.qubits.length; - const newPanelElem = _panel(dispatch, context); + const newPanelElem = panel(dispatch, context); container.replaceChild(newPanelElem, panelElem); panelElem = newPanelElem; }), ); + container.addEventListener('mouseover', () => { + context.registerSize = sqore.circuit.qubits.length; + context.operations = sqore.circuit.operations; + }); const dispatch = update(context, useRefresh); - - let panelElem = _panel(dispatch, context); + let panelElem = panel(dispatch, context); const prevPanelElem = container.querySelector('.panel'); prevPanelElem // ? container.replaceChild(panelElem, prevPanelElem) @@ -44,35 +48,56 @@ interface Action { const update = (context: Context, useRefresh: () => void) => (action: Action) => { switch (action.type) { + case 'OPERATION': { + context.operation = action.payload as Operation; + } case 'TARGET': { const { operation } = context; const payload = action.payload as Register[]; operation && (operation.targets = payload); + useRefresh(); break; } case 'CONTROLS': { const { operation } = context; operation && (operation.controls = action.payload as Register[]); + useRefresh(); break; } case 'DISPLAY_ARGS': { const { operation } = context; operation && (operation.displayArgs = action.payload as string); + useRefresh(); + break; + } + case 'ADD_OPERATION': { + context.operations.push(action.payload as Operation); + useRefresh(); break; } } - useRefresh(); }; -const _panel = (dispatch: Dispatch, context: Context) => { - const panelElem = _elem('div'); +const panel = (dispatch: Dispatch, context: Context) => { + const panelElem = elem('div'); panelElem.className = 'panel'; - _children(panelElem, editPanel(dispatch, context)); - + children(panelElem, addPanel(dispatch, context)); + // _children(panelElem, editPanel(dispatch, context)); return panelElem; }; -// const addPanel = () => {}; +const addPanel = (dispatch: Dispatch, context: Context) => { + const buttonElem = elem('button') as HTMLButtonElement; + buttonElem.textContent = 'H'; + buttonElem.addEventListener('mouseup', () => { + const operation = { + gate: 'H', + targets: [{ qId: 0 }], + }; + dispatch({ type: 'ADD_OPERATION', payload: operation }); + }); + return [title('ADD'), buttonElem]; +}; const editPanel = (dispatch: Dispatch, context: Context) => { const { operation, registerSize } = context; @@ -80,28 +105,28 @@ const editPanel = (dispatch: Dispatch, context: Context) => { const target = operation?.targets[0].qId; const controls = operation?.controls?.map((control) => control.qId); return [ - _title('EDIT'), + title('EDIT'), _select('Target', 'target-input', options, target || 0, dispatch, operation), _checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), _text('Display', 'display-input', dispatch, operation), ]; }; -const _elem = (tag: string): HTMLElement => document.createElement(tag); +const elem = (tag: string): HTMLElement => document.createElement(tag); /** * Append all child elements to a parent element */ -const _children = (parentElem: HTMLElement, childElems: HTMLElement[]) => { +const children = (parentElem: HTMLElement, childElems: HTMLElement[]) => { childElems.map((elem) => parentElem.appendChild(elem)); return parentElem; }; -const _title = (text: string) => { - const elem = _elem('h1'); - elem.className = 'title'; - elem.innerText = text; - return elem; +const title = (text: string) => { + const titleElem = elem('h2'); + titleElem.className = 'title'; + titleElem.innerText = text; + return titleElem; }; interface Option { @@ -122,18 +147,18 @@ const _select = ( operation?: Operation, ): HTMLElement => { const optionElems = options.map(({ value, text }) => _option(value, text)); - const selectElem = _elem('select') as HTMLSelectElement; - _children(selectElem, optionElems); + const selectElem = elem('select') as HTMLSelectElement; + children(selectElem, optionElems); operation == undefined && selectElem.setAttribute('disabled', 'true'); selectElem.selectedIndex = selectedIndex; - const labelElem = _elem('label') as HTMLLabelElement; + const labelElem = elem('label') as HTMLLabelElement; labelElem.className = 'block'; labelElem.textContent = label; - const divElem = _elem('div') as HTMLDivElement; + const divElem = elem('div') as HTMLDivElement; divElem.className = className; - _children(divElem, [labelElem, selectElem]); + children(divElem, [labelElem, selectElem]); selectElem.onchange = () => { dispatch({ type: 'TARGET', payload: [{ qId: parseInt(selectElem.value) }] }); @@ -143,10 +168,10 @@ const _select = ( }; const _option = (value: string, text: string) => { - const elem = _elem('option') as HTMLOptionElement; - elem.value = value; - elem.textContent = text; - return elem; + const optionElem = elem('option') as HTMLOptionElement; + optionElem.value = value; + optionElem.textContent = text; + return optionElem; }; const _checkboxes = ( @@ -174,34 +199,34 @@ const _checkboxes = ( return elem; }); - const labelElem = _elem('label'); + const labelElem = elem('label'); labelElem.className = 'block'; labelElem.textContent = label; - const divElem = _elem('div') as HTMLDivElement; + const divElem = elem('div') as HTMLDivElement; divElem.className = className; - _children(divElem, [labelElem, ...checkboxElems]); + children(divElem, [labelElem, ...checkboxElems]); return divElem; }; const _checkbox = (value: string, text: string) => { - const inputElem = _elem('input') as HTMLInputElement; + const inputElem = elem('input') as HTMLInputElement; inputElem.type = 'checkbox'; inputElem.value = value; - const labelElem = _elem('label') as HTMLLabelElement; + const labelElem = elem('label') as HTMLLabelElement; labelElem.textContent = text; labelElem.prepend(inputElem); return labelElem; }; const _text = (label: string, className: string, dispatch: Dispatch, operation?: Operation) => { - const labelElem = _elem('label') as HTMLLabelElement; + const labelElem = elem('label') as HTMLLabelElement; labelElem.className = 'block'; labelElem.textContent = label; - const textElem = _elem('input') as HTMLInputElement; + const textElem = elem('input') as HTMLInputElement; operation == undefined && textElem.setAttribute('disabled', 'true'); textElem.type = 'text'; textElem.value = operation?.displayArgs || ''; @@ -211,9 +236,9 @@ const _text = (label: string, className: string, dispatch: Dispatch, operation?: dispatch({ type: 'DISPLAY_ARGS', payload: textElem.value }); }; - const divElem = _elem('div'); + const divElem = elem('div'); divElem.className = className; - _children(divElem, [labelElem, textElem]); + children(divElem, [labelElem, textElem]); return divElem; }; diff --git a/src/styles.ts b/src/styles.ts index 764ed6e2..7fdde268 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -269,9 +269,10 @@ const _panel = ` display: flex; } .panel { + min-width: 96px; display: flex; flex-direction: column; - border: solid 2px black; + border: solid 1.5px black; padding: 8px; } .title { From b66957c4ee4eb5b243b309d80d205ca8d75746f8 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 20 Jul 2022 14:14:07 -0400 Subject: [PATCH 065/108] Allow toggling between Add or Edit Panel --- src/panel.ts | 96 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index 4f021993..5e846676 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -5,40 +5,57 @@ import { Register } from './register'; import { Sqore } from './sqore'; interface Context { + addMode: boolean; operations: Operation[]; operation: Operation | undefined; registerSize: number; } -let context: Context = { +const context: Context = { + addMode: true, operations: [], operation: undefined, registerSize: 0, }; const extensionPanel = (container: HTMLElement, sqore: Sqore, useRefresh: () => void): void => { + const dispatch = (action: Action) => { + update(action, context, useRefresh); + + const panelElem = panel(dispatch, context); + const prevPanelElem = container.querySelector('.panel'); + + prevPanelElem && container.replaceChild(panelElem, prevPanelElem); + }; + + addEvents(dispatch, container, sqore); + + const panelElem = panel(dispatch, context); + const prevPanelElem = container.querySelector('.panel'); + + prevPanelElem == null && container.prepend(panelElem); +}; + +const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => { const elems = container.querySelectorAll<SVGElement>('[data-id]'); elems.forEach((elem) => - elem.addEventListener('mousedown', () => { + elem.addEventListener('mousedown', (ev: MouseEvent) => { + ev.stopImmediatePropagation(); const dataId = elem.getAttribute('data-id'); const operation = _equivOperation(dataId, sqore.circuit.operations); - context.operation = operation || undefined; - const newPanelElem = panel(dispatch, context); - container.replaceChild(newPanelElem, panelElem); - panelElem = newPanelElem; + dispatch({ type: 'OPERATION', payload: operation }); + dispatch({ type: 'ADD_MODE', payload: false }); }), ); + container.addEventListener('mouseover', () => { context.registerSize = sqore.circuit.qubits.length; context.operations = sqore.circuit.operations; }); - const dispatch = update(context, useRefresh); - let panelElem = panel(dispatch, context); - const prevPanelElem = container.querySelector('.panel'); - prevPanelElem // - ? container.replaceChild(panelElem, prevPanelElem) - : container.prepend(panelElem); + container.addEventListener('mousedown', () => { + dispatch({ type: 'ADD_MODE', payload: true }); + }); }; interface Action { @@ -46,10 +63,15 @@ interface Action { payload: unknown; } -const update = (context: Context, useRefresh: () => void) => (action: Action) => { +const update = (action: Action, context: Context, useRefresh: () => void) => { switch (action.type) { + case 'ADD_MODE': { + context.addMode = action.payload as boolean; + break; + } case 'OPERATION': { context.operation = action.payload as Operation; + break; } case 'TARGET': { const { operation } = context; @@ -81,22 +103,35 @@ const update = (context: Context, useRefresh: () => void) => (action: Action) => const panel = (dispatch: Dispatch, context: Context) => { const panelElem = elem('div'); panelElem.className = 'panel'; - children(panelElem, addPanel(dispatch, context)); - // _children(panelElem, editPanel(dispatch, context)); + children( + panelElem, + context.addMode // + ? addPanel(dispatch, context) + : editPanel(dispatch, context), + ); return panelElem; }; const addPanel = (dispatch: Dispatch, context: Context) => { - const buttonElem = elem('button') as HTMLButtonElement; - buttonElem.textContent = 'H'; - buttonElem.addEventListener('mouseup', () => { + const hElem = elem('button') as HTMLButtonElement; + hElem.textContent = 'H'; + const xElem = elem('button') as HTMLButtonElement; + xElem.textContent = 'X'; + hElem.addEventListener('mouseup', () => { const operation = { gate: 'H', targets: [{ qId: 0 }], }; dispatch({ type: 'ADD_OPERATION', payload: operation }); }); - return [title('ADD'), buttonElem]; + xElem.addEventListener('mouseup', () => { + const operation = { + gate: 'X', + targets: [{ qId: 1 }], + }; + dispatch({ type: 'ADD_OPERATION', payload: operation }); + }); + return [title('ADD'), hElem, xElem]; }; const editPanel = (dispatch: Dispatch, context: Context) => { @@ -106,9 +141,9 @@ const editPanel = (dispatch: Dispatch, context: Context) => { const controls = operation?.controls?.map((control) => control.qId); return [ title('EDIT'), - _select('Target', 'target-input', options, target || 0, dispatch, operation), - _checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), - _text('Display', 'display-input', dispatch, operation), + select('Target', 'target-input', options, target || 0, dispatch, operation), + checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), + text('Display', 'display-input', dispatch, operation), ]; }; @@ -138,7 +173,7 @@ interface Dispatch { (action: Action): void; } -const _select = ( +const select = ( label: string, className: string, options: Option[], @@ -146,7 +181,7 @@ const _select = ( dispatch: Dispatch, operation?: Operation, ): HTMLElement => { - const optionElems = options.map(({ value, text }) => _option(value, text)); + const optionElems = options.map(({ value, text }) => option(value, text)); const selectElem = elem('select') as HTMLSelectElement; children(selectElem, optionElems); operation == undefined && selectElem.setAttribute('disabled', 'true'); @@ -167,14 +202,14 @@ const _select = ( return divElem; }; -const _option = (value: string, text: string) => { +const option = (value: string, text: string) => { const optionElem = elem('option') as HTMLOptionElement; optionElem.value = value; optionElem.textContent = text; return optionElem; }; -const _checkboxes = ( +const checkboxes = ( label: string, className: string, options: Option[], @@ -183,16 +218,19 @@ const _checkboxes = ( operation?: Operation, ) => { const checkboxElems = options.map((option, index) => { - const elem = _checkbox(option.value, option.text); + const elem = checkbox(option.value, option.text); const inputElem = elem.querySelector('input') as HTMLInputElement; selectedIndexes.includes(index) && inputElem.setAttribute('checked', 'true'); operation == undefined && inputElem.setAttribute('disabled', 'true'); inputElem.onchange = () => { + // Get all checked options const checkedElems = Array.from(divElem.querySelectorAll<HTMLInputElement>('input:checked')); + // Generate new controls from checked options const newControls = checkedElems.map((elem) => ({ qId: parseInt(elem.value), })); + // Dispatch new controls dispatch({ type: 'CONTROLS', payload: newControls }); }; @@ -210,7 +248,7 @@ const _checkboxes = ( return divElem; }; -const _checkbox = (value: string, text: string) => { +const checkbox = (value: string, text: string) => { const inputElem = elem('input') as HTMLInputElement; inputElem.type = 'checkbox'; inputElem.value = value; @@ -221,7 +259,7 @@ const _checkbox = (value: string, text: string) => { return labelElem; }; -const _text = (label: string, className: string, dispatch: Dispatch, operation?: Operation) => { +const text = (label: string, className: string, dispatch: Dispatch, operation?: Operation) => { const labelElem = elem('label') as HTMLLabelElement; labelElem.className = 'block'; labelElem.textContent = label; From acb6bb89eff9a8eaf20aa813b6fee9151127258e Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 21 Jul 2022 11:10:44 -0400 Subject: [PATCH 066/108] Add basic functionalities with Add Panel --- src/panel.ts | 81 ++++++++++++++++++++++++++++++++++++--------------- src/sqore.ts | 2 +- src/styles.ts | 14 ++++++++- 3 files changed, 71 insertions(+), 26 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index 5e846676..e054aabd 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -53,9 +53,11 @@ const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => context.operations = sqore.circuit.operations; }); - container.addEventListener('mousedown', () => { - dispatch({ type: 'ADD_MODE', payload: true }); - }); + const svgElem = container.querySelector('svg[id]'); + svgElem && + svgElem.addEventListener('mousedown', () => { + dispatch({ type: 'ADD_MODE', payload: true }); + }); }; interface Action { @@ -82,7 +84,11 @@ const update = (action: Action, context: Context, useRefresh: () => void) => { } case 'CONTROLS': { const { operation } = context; - operation && (operation.controls = action.payload as Register[]); + if (operation) { + const payload = action.payload as Register[]; + operation.controls = payload; + operation.isControlled = payload.length > 0 ? true : false; + } useRefresh(); break; } @@ -113,25 +119,10 @@ const panel = (dispatch: Dispatch, context: Context) => { }; const addPanel = (dispatch: Dispatch, context: Context) => { - const hElem = elem('button') as HTMLButtonElement; - hElem.textContent = 'H'; - const xElem = elem('button') as HTMLButtonElement; - xElem.textContent = 'X'; - hElem.addEventListener('mouseup', () => { - const operation = { - gate: 'H', - targets: [{ qId: 0 }], - }; - dispatch({ type: 'ADD_OPERATION', payload: operation }); - }); - xElem.addEventListener('mouseup', () => { - const operation = { - gate: 'X', - targets: [{ qId: 1 }], - }; - dispatch({ type: 'ADD_OPERATION', payload: operation }); - }); - return [title('ADD'), hElem, xElem]; + const hGate = gate(dispatch, 'H'); + const xGate = gate(dispatch, 'X'); + const zzGate = gate(dispatch, 'ZZ'); + return [title('ADD'), hGate, xGate, zzGate]; }; const editPanel = (dispatch: Dispatch, context: Context) => { @@ -147,7 +138,11 @@ const editPanel = (dispatch: Dispatch, context: Context) => { ]; }; -const elem = (tag: string): HTMLElement => document.createElement(tag); +const elem = (tag: string, className?: string): HTMLElement => { + const _elem = document.createElement(tag); + _elem.className = className || ''; + return _elem; +}; /** * Append all child elements to a parent element @@ -281,4 +276,42 @@ const text = (label: string, className: string, dispatch: Dispatch, operation?: return divElem; }; +/** + * Generate gate element for Add Panel based on type of gate + * @param dispatch + * @param type i.e. 'H' or 'X' + */ +const gate = (dispatch: Dispatch, type: string) => { + const operation = defaultGates[type]; + if (operation == null) throw new Error(`Gate ${type} not available`); + const divElem = elem('div', `panel-gate gate-${type}`); + divElem.addEventListener('mousedown', () => { + dispatch({ type: 'ADD_OPERATION', payload: operation }); + }); + divElem.textContent = type; + return divElem; +}; + +interface DefaultGates { + [index: string]: Operation; +} + +const defaultGates: DefaultGates = { + H: { + gate: 'H', + targets: [{ qId: 0 }], + }, + X: { + gate: 'X', + isControlled: true, + controls: [{ qId: 0 }], + targets: [{ qId: 1 }], + }, + ZZ: { + gate: 'ZZ', + targets: [{ qId: 0 }, { qId: 1 }], + isControlled: true, + }, +}; + export { extensionPanel }; diff --git a/src/sqore.ts b/src/sqore.ts index 0300c5d5..15d89f96 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -124,7 +124,7 @@ export class Sqore { // Create visualization components const composedSqore: ComposedSqore = this.compose(_circuit); const svg: SVGElement = this.generateSvg(composedSqore); - const previousSvg = container.querySelector('svg'); + const previousSvg = container.querySelector('svg[id]'); previousSvg == null // ? container.appendChild(svg) : container.replaceChild(svg, previousSvg); diff --git a/src/styles.ts b/src/styles.ts index 7fdde268..37fe5f29 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -269,7 +269,7 @@ const _panel = ` display: flex; } .panel { - min-width: 96px; + width: 144px; display: flex; flex-direction: column; border: solid 1.5px black; @@ -285,4 +285,16 @@ const _panel = ` .target-input, .controls-input, .display-input { margin-bottom: 8px; } + .panel-gate { + width: 40px; + height: 40px; + border: solid 1px; + display: flex; + justify-content: center; + align-items: center; + font-size: 14px; + } + .panel-gate.gate-H { + background-color: #D9F1FA; + } `; From 59fd7e01ed347d71a9d4dd95cb4c31829fe40f07 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 25 Jul 2022 10:51:48 -0400 Subject: [PATCH 067/108] Basic drag and drop --- src/draggable.ts | 10 ++++++- src/panel.ts | 68 +++++++++++++++++++++++++++++++++++++++--------- src/styles.ts | 17 +++++------- 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/src/draggable.ts b/src/draggable.ts index 93c43f3e..d358219c 100644 --- a/src/draggable.ts +++ b/src/draggable.ts @@ -531,4 +531,12 @@ const exportedForTesting = { _lastIndex, }; -export { extensionDraggable, Context, _equivOperation, _equivGateElem, exportedForTesting }; +export { + extensionDraggable, + Context, + _equivOperation, + _equivGateElem, + _equivParentArray, + _lastIndex, + exportedForTesting, +}; diff --git a/src/panel.ts b/src/panel.ts index e054aabd..6893e6cc 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -1,6 +1,7 @@ import range from 'lodash/range'; +import cloneDeep from 'lodash/cloneDeep'; import { Operation } from './circuit'; -import { _equivOperation } from './draggable'; +import { _equivOperation, _equivParentArray, _lastIndex } from './draggable'; import { Register } from './register'; import { Sqore } from './sqore'; @@ -9,6 +10,7 @@ interface Context { operations: Operation[]; operation: Operation | undefined; registerSize: number; + container: HTMLElement | undefined; } const context: Context = { @@ -16,6 +18,7 @@ const context: Context = { operations: [], operation: undefined, registerSize: 0, + container: undefined, }; const extensionPanel = (container: HTMLElement, sqore: Sqore, useRefresh: () => void): void => { @@ -51,6 +54,7 @@ const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => container.addEventListener('mouseover', () => { context.registerSize = sqore.circuit.qubits.length; context.operations = sqore.circuit.operations; + context.container = container; }); const svgElem = container.querySelector('svg[id]'); @@ -58,6 +62,22 @@ const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => svgElem.addEventListener('mousedown', () => { dispatch({ type: 'ADD_MODE', payload: true }); }); + + const dropzoneLayer = container.querySelector('.dropzone-layer') as SVGGElement; + const dropzoneElems = dropzoneLayer.querySelectorAll<SVGRectElement>('.dropzone'); + dropzoneElems.forEach((dropzoneElem) => + dropzoneElem.addEventListener('mouseup', () => { + if ( + context.operation && // + context.addMode + ) { + const targetId = dropzoneElem.getAttribute('data-dropzone-id'); + const targetWire = dropzoneElem.getAttribute('data-dropzone-wire'); + dispatch({ type: 'ADD_OPERATION', payload: targetId }); + dispatch({ type: 'TARGET', payload: [{ qId: parseInt(targetWire || '') }] }); + } + }), + ); }; interface Action { @@ -99,30 +119,48 @@ const update = (action: Action, context: Context, useRefresh: () => void) => { break; } case 'ADD_OPERATION': { - context.operations.push(action.payload as Operation); + const targetId = action.payload as string; + const targetOperationParent = _equivParentArray(targetId, context.operations); + const targetLastIndex = _lastIndex(targetId); + if ( + targetOperationParent != null && // + targetLastIndex != null && + context.operation != null + ) { + targetOperationParent.splice(targetLastIndex, 0, context.operation); + } + // context.operations.push(action.payload as Operation); useRefresh(); break; } + case 'DROPZONE_LAYER': { + const isVisible = action.payload as boolean; + const { container } = context; + if (container) { + const dropzoneLayer = container.querySelector('.dropzone-layer') as SVGGElement; + isVisible ? (dropzoneLayer.style.display = 'block') : 'none'; + } + break; + } } }; const panel = (dispatch: Dispatch, context: Context) => { const panelElem = elem('div'); panelElem.className = 'panel'; - children( - panelElem, + children(panelElem, [ context.addMode // ? addPanel(dispatch, context) : editPanel(dispatch, context), - ); + ]); return panelElem; }; const addPanel = (dispatch: Dispatch, context: Context) => { + const addPanelElem = elem('div', 'add-panel'); const hGate = gate(dispatch, 'H'); - const xGate = gate(dispatch, 'X'); - const zzGate = gate(dispatch, 'ZZ'); - return [title('ADD'), hGate, xGate, zzGate]; + children(addPanelElem, [title('ADD'), hGate]); + return addPanelElem; }; const editPanel = (dispatch: Dispatch, context: Context) => { @@ -130,12 +168,15 @@ const editPanel = (dispatch: Dispatch, context: Context) => { const options = range(registerSize).map((i) => ({ value: `${i}`, text: `q${i}` })); const target = operation?.targets[0].qId; const controls = operation?.controls?.map((control) => control.qId); - return [ + + const editPanelElem = elem('div', 'edit-panel'); + children(editPanelElem, [ title('EDIT'), select('Target', 'target-input', options, target || 0, dispatch, operation), checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), text('Display', 'display-input', dispatch, operation), - ]; + ]); + return editPanelElem; }; const elem = (tag: string, className?: string): HTMLElement => { @@ -275,7 +316,6 @@ const text = (label: string, className: string, dispatch: Dispatch, operation?: return divElem; }; - /** * Generate gate element for Add Panel based on type of gate * @param dispatch @@ -284,9 +324,11 @@ const text = (label: string, className: string, dispatch: Dispatch, operation?: const gate = (dispatch: Dispatch, type: string) => { const operation = defaultGates[type]; if (operation == null) throw new Error(`Gate ${type} not available`); - const divElem = elem('div', `panel-gate gate-${type}`); + const divElem = elem('div', `add-panel-gate`); divElem.addEventListener('mousedown', () => { - dispatch({ type: 'ADD_OPERATION', payload: operation }); + // dispatch({ type: 'ADD_OPERATION', payload: operation }); + dispatch({ type: 'OPERATION', payload: cloneDeep(operation) }); + dispatch({ type: 'DROPZONE_LAYER', payload: true }); }); divElem.textContent = type; return divElem; diff --git a/src/styles.ts b/src/styles.ts index 37fe5f29..82e00cf5 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -270,10 +270,12 @@ const _panel = ` } .panel { width: 144px; + border: solid 1px black; + padding: 8px; + } + .edit-panel { display: flex; flex-direction: column; - border: solid 1.5px black; - padding: 8px; } .title { margin: 0 0 4px; @@ -285,16 +287,9 @@ const _panel = ` .target-input, .controls-input, .display-input { margin-bottom: 8px; } - .panel-gate { + .add-panel-gate { width: 40px; height: 40px; - border: solid 1px; - display: flex; - justify-content: center; - align-items: center; - font-size: 14px; - } - .panel-gate.gate-H { - background-color: #D9F1FA; + border: 1px solid black; } `; From ea16116a89d135594a59a7f76100f0003278c300 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 26 Jul 2022 11:07:13 -0400 Subject: [PATCH 068/108] Basic Add Panel gate rendering --- src/draggable.ts | 29 ++++++++++++------ src/panel.ts | 80 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 88 insertions(+), 21 deletions(-) diff --git a/src/draggable.ts b/src/draggable.ts index d358219c..9af6b9d9 100644 --- a/src/draggable.ts +++ b/src/draggable.ts @@ -27,7 +27,7 @@ interface Context { * @param onCircuitChange User-provided callback function triggered when circuit is changed */ const extensionDraggable = (container: HTMLElement, sqore: Sqore, useRender: () => void): void => { - const svg = container.querySelector('svg') as SVGElement; + const svg = container.querySelector('svg[id]') as SVGElement; const context: Context = { container: container, @@ -80,11 +80,14 @@ const _wireYs = (elem: SVGGraphicsElement, wireData: number[]): number[] => { * Get list of host elements that dropzones can be attached to */ const _hostElems = (container: HTMLElement): SVGGraphicsElement[] => { - return Array.from( - container.querySelectorAll<SVGGraphicsElement>( - '[class^="gate-"]:not(.gate-control, .gate-swap), .control-dot, .oplus, .cross', - ), - ); + const svgElem = container.querySelector('svg[id]'); + return svgElem != null + ? Array.from( + svgElem.querySelectorAll<SVGGraphicsElement>( + '[class^="gate-"]:not(.gate-control, .gate-swap), .control-dot, .oplus, .cross', + ), + ) + : []; }; /** @@ -137,7 +140,7 @@ const _dropzoneLayer = (context: Context) => { // Check to prevent group gates creating dropzones between wires if (wirePrefix) { - const prefixX = wirePrefix.prefixX; + const { prefixX } = wirePrefix; const elemDropzone = box(prefixX, cY - paddingY, cX - prefixX, paddingY * 2, 'dropzone'); elemDropzone.setAttribute('data-dropzone-id', _equivDataId(elem) || ''); elemDropzone.setAttribute('data-dropzone-wire', `${wirePrefix.index}`); @@ -153,7 +156,7 @@ const _dropzoneLayer = (context: Context) => { wireYs.map((wireY) => { const wirePrefix = wirePrefixes.find((item) => item.wireY === wireY); if (wirePrefix) { - const prefixX = wirePrefix.prefixX; + const { prefixX } = wirePrefix; const elemDropzone = box(prefixX, wireY - paddingY, x - prefixX, paddingY * 2, 'dropzone'); elemDropzone.setAttribute('data-dropzone-id', _equivDataId(elem) || ''); elemDropzone.setAttribute('data-dropzone-wire', `${wirePrefix.index}`); @@ -222,7 +225,7 @@ const _addDropzoneLayerEvents = (container: HTMLElement, dropzoneLayer: SVGGElem * Add events for document */ const _addDocumentEvents = (context: Context) => { - const { container } = context; + const { container, svg } = context; document.addEventListener('keydown', (ev: KeyboardEvent) => { if (ev.ctrlKey && context.selectedId) { @@ -241,6 +244,14 @@ const _addDocumentEvents = (context: Context) => { document.addEventListener('mouseup', () => { container.classList.remove('moving', 'copying'); }); + + document.addEventListener( + 'contextmenu', + (ev: Event) => { + ev.preventDefault(); + }, + false, + ); }; /** diff --git a/src/panel.ts b/src/panel.ts index 6893e6cc..3efdc8b1 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -1,9 +1,13 @@ -import range from 'lodash/range'; import cloneDeep from 'lodash/cloneDeep'; +import range from 'lodash/range'; import { Operation } from './circuit'; +import { gateHeight, minGateWidth } from './constants'; import { _equivOperation, _equivParentArray, _lastIndex } from './draggable'; +import { _formatGate } from './formatters/gateFormatter'; +import { GateType, Metadata } from './metadata'; import { Register } from './register'; import { Sqore } from './sqore'; +import { getGateWidth } from './utils'; interface Context { addMode: boolean; @@ -129,7 +133,6 @@ const update = (action: Action, context: Context, useRefresh: () => void) => { ) { targetOperationParent.splice(targetLastIndex, 0, context.operation); } - // context.operations.push(action.payload as Operation); useRefresh(); break; } @@ -138,7 +141,7 @@ const update = (action: Action, context: Context, useRefresh: () => void) => { const { container } = context; if (container) { const dropzoneLayer = container.querySelector('.dropzone-layer') as SVGGElement; - isVisible ? (dropzoneLayer.style.display = 'block') : 'none'; + dropzoneLayer.style.display = isVisible ? 'block' : 'none'; } break; } @@ -158,8 +161,17 @@ const panel = (dispatch: Dispatch, context: Context) => { const addPanel = (dispatch: Dispatch, context: Context) => { const addPanelElem = elem('div', 'add-panel'); - const hGate = gate(dispatch, 'H'); - children(addPanelElem, [title('ADD'), hGate]); + const svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svgElem.setAttribute('width', '144px'); + svgElem.setAttribute('height', '100%'); + const hGate = gate(dispatch, 'H', 0, 0); + const xGate = gate(dispatch, 'X', 50, 0); + const x2Gate = gate(dispatch, 'X', 100, 0); + svgElem.appendChild(hGate); + svgElem.appendChild(xGate); + svgElem.appendChild(x2Gate); + children(addPanelElem, [title('ADD')]); + addPanelElem.appendChild(svgElem); return addPanelElem; }; @@ -316,22 +328,67 @@ const text = (label: string, className: string, dispatch: Dispatch, operation?: return divElem; }; + +const toMetadata = (operation: Operation | undefined, x: number, y: number): Metadata => { + const metadata: Metadata = { + type: GateType.Invalid, + x: x + minGateWidth / 2, + controlsY: [], + targetsY: [y + gateHeight / 2], + label: '', + width: -1, + }; + + if (operation == null) return metadata; + + const { + gate, + displayArgs, + isMeasurement, + // isConditional, + isControlled, + // isAdjoint, + // conditionalRender, + } = operation; + + if (isMeasurement) { + metadata.type = GateType.Measure; + } else if (gate === 'SWAP') { + metadata.type = GateType.Swap; + } else if (isControlled) { + metadata.type = gate === 'X' ? GateType.Cnot : GateType.ControlledUnitary; + metadata.label = gate; + } else if (gate === 'X') { + metadata.type = GateType.X; + metadata.label = gate; + } else { + metadata.type = GateType.Unitary; + metadata.label = gate; + metadata.targetsY = [[y + gateHeight / 2]]; + } + + if (displayArgs != null) metadata.displayArgs = displayArgs; + metadata.width = getGateWidth(metadata); + + return metadata; +}; + /** * Generate gate element for Add Panel based on type of gate * @param dispatch * @param type i.e. 'H' or 'X' */ -const gate = (dispatch: Dispatch, type: string) => { +const gate = (dispatch: Dispatch, type: string, x: number, y: number) => { const operation = defaultGates[type]; if (operation == null) throw new Error(`Gate ${type} not available`); - const divElem = elem('div', `add-panel-gate`); - divElem.addEventListener('mousedown', () => { + const metadata = toMetadata(operation, x, y); + const gateElem = _formatGate(metadata).cloneNode(true); + gateElem.addEventListener('mousedown', () => { // dispatch({ type: 'ADD_OPERATION', payload: operation }); dispatch({ type: 'OPERATION', payload: cloneDeep(operation) }); dispatch({ type: 'DROPZONE_LAYER', payload: true }); }); - divElem.textContent = type; - return divElem; + return gateElem; }; interface DefaultGates { @@ -346,8 +403,7 @@ const defaultGates: DefaultGates = { X: { gate: 'X', isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], + targets: [{ qId: 0 }], }, ZZ: { gate: 'ZZ', From ab19cd03cc6600c7b7ca33daf1796925f1dc9bbd Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 26 Jul 2022 11:22:20 -0400 Subject: [PATCH 069/108] Disable contextmenu & change cursor when dragging from Add Panel --- src/draggable.ts | 19 +++++++++++-------- src/panel.ts | 16 ++++++++++------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/draggable.ts b/src/draggable.ts index 9af6b9d9..302d2549 100644 --- a/src/draggable.ts +++ b/src/draggable.ts @@ -7,6 +7,7 @@ import { Operation } from './circuit'; import { box } from './formatters/formatUtils'; import { Register } from './register'; import { Sqore } from './sqore'; +import { panelContext } from './panel'; interface Context { container: HTMLElement; @@ -225,7 +226,7 @@ const _addDropzoneLayerEvents = (container: HTMLElement, dropzoneLayer: SVGGElem * Add events for document */ const _addDocumentEvents = (context: Context) => { - const { container, svg } = context; + const { container } = context; document.addEventListener('keydown', (ev: KeyboardEvent) => { if (ev.ctrlKey && context.selectedId) { @@ -244,14 +245,15 @@ const _addDocumentEvents = (context: Context) => { document.addEventListener('mouseup', () => { container.classList.remove('moving', 'copying'); }); +}; - document.addEventListener( - 'contextmenu', - (ev: Event) => { - ev.preventDefault(); - }, - false, - ); +/** + * Disable contextmenu default behaviors + */ +const _addContextMenuEvent = (container: HTMLElement) => { + container.addEventListener('contextmenu', (ev: MouseEvent) => { + ev.preventDefault(); + }); }; /** @@ -261,6 +263,7 @@ const _addEvents = (context: Context) => { const { container, operations, renderFn } = context; const dropzoneLayer = container.querySelector('.dropzone-layer') as SVGGElement; + _addContextMenuEvent(container); _addDropzoneLayerEvents(container, dropzoneLayer); _addDocumentEvents(context); diff --git a/src/panel.ts b/src/panel.ts index 3efdc8b1..7a6ea828 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -86,7 +86,7 @@ const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => interface Action { type: string; - payload: unknown; + payload?: unknown; } const update = (action: Action, context: Context, useRefresh: () => void) => { @@ -136,15 +136,18 @@ const update = (action: Action, context: Context, useRefresh: () => void) => { useRefresh(); break; } - case 'DROPZONE_LAYER': { - const isVisible = action.payload as boolean; + case 'DISPLAY_DROPZONE_LAYER': { const { container } = context; if (container) { const dropzoneLayer = container.querySelector('.dropzone-layer') as SVGGElement; - dropzoneLayer.style.display = isVisible ? 'block' : 'none'; + dropzoneLayer.style.display = 'block'; } break; } + case 'DISPLAY_CURSOR_MOVING': { + const { container } = context; + container && container.classList.add('moving'); + } } }; @@ -386,7 +389,8 @@ const gate = (dispatch: Dispatch, type: string, x: number, y: number) => { gateElem.addEventListener('mousedown', () => { // dispatch({ type: 'ADD_OPERATION', payload: operation }); dispatch({ type: 'OPERATION', payload: cloneDeep(operation) }); - dispatch({ type: 'DROPZONE_LAYER', payload: true }); + dispatch({ type: 'DISPLAY_DROPZONE_LAYER' }); + dispatch({ type: 'DISPLAY_CURSOR_MOVING', payload: true }); }); return gateElem; }; @@ -412,4 +416,4 @@ const defaultGates: DefaultGates = { }, }; -export { extensionPanel }; +export { extensionPanel, context as panelContext }; From 74f2f5f9a3827588abf4be4fbaaf5996635a057f Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 26 Jul 2022 11:29:13 -0400 Subject: [PATCH 070/108] Remove unnecessary export --- src/draggable.ts | 1 - src/panel.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/draggable.ts b/src/draggable.ts index 302d2549..10ece347 100644 --- a/src/draggable.ts +++ b/src/draggable.ts @@ -7,7 +7,6 @@ import { Operation } from './circuit'; import { box } from './formatters/formatUtils'; import { Register } from './register'; import { Sqore } from './sqore'; -import { panelContext } from './panel'; interface Context { container: HTMLElement; diff --git a/src/panel.ts b/src/panel.ts index 7a6ea828..bbba259c 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -416,4 +416,4 @@ const defaultGates: DefaultGates = { }, }; -export { extensionPanel, context as panelContext }; +export { extensionPanel }; From b1e06d382c97cccc8d449956236f5709042cacb7 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 26 Jul 2022 11:32:13 -0400 Subject: [PATCH 071/108] Add rendering padding & comments --- src/panel.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index bbba259c..b615e77f 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -335,9 +335,9 @@ const text = (label: string, className: string, dispatch: Dispatch, operation?: const toMetadata = (operation: Operation | undefined, x: number, y: number): Metadata => { const metadata: Metadata = { type: GateType.Invalid, - x: x + minGateWidth / 2, + x: x + 1 + minGateWidth / 2, // offset by 1 for left padding controlsY: [], - targetsY: [y + gateHeight / 2], + targetsY: [y + 1 + gateHeight / 2], // offset by 1 for top padding label: '', width: -1, }; @@ -367,7 +367,8 @@ const toMetadata = (operation: Operation | undefined, x: number, y: number): Met } else { metadata.type = GateType.Unitary; metadata.label = gate; - metadata.targetsY = [[y + gateHeight / 2]]; + metadata.targetsY = [[y + 1 + gateHeight / 2]]; + // GateType.Unitary wants matrix array. Also, offset by 1 for top padding } if (displayArgs != null) metadata.displayArgs = displayArgs; From cbc1a5f48d8f0f31e3b2675b91167d2168490a91 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 27 Jul 2022 08:57:27 -0400 Subject: [PATCH 072/108] Let usePanel accepts user options --- src/panel.ts | 45 ++++++++++++++++++++++++++------------------- src/sqore.ts | 10 +++++----- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index b615e77f..fc0223f9 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -25,23 +25,30 @@ const context: Context = { container: undefined, }; -const extensionPanel = (container: HTMLElement, sqore: Sqore, useRefresh: () => void): void => { - const dispatch = (action: Action) => { - update(action, context, useRefresh); +interface PanelOptions { + gateDictionary?: GateDictionary; + displaySize?: number; +} - const panelElem = panel(dispatch, context); - const prevPanelElem = container.querySelector('.panel'); +const extensionPanel = + (options?: PanelOptions) => + (container: HTMLElement, sqore: Sqore, useRefresh: () => void): void => { + const dispatch = (action: Action) => { + update(action, context, useRefresh); - prevPanelElem && container.replaceChild(panelElem, prevPanelElem); - }; + const panelElem = panel(dispatch, context, options); + const prevPanelElem = container.querySelector('.panel'); + + prevPanelElem && container.replaceChild(panelElem, prevPanelElem); + }; - addEvents(dispatch, container, sqore); + addEvents(dispatch, container, sqore); - const panelElem = panel(dispatch, context); - const prevPanelElem = container.querySelector('.panel'); + const panelElem = panel(dispatch, context, options); + const prevPanelElem = container.querySelector('.panel'); - prevPanelElem == null && container.prepend(panelElem); -}; + prevPanelElem == null && container.prepend(panelElem); + }; const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => { const elems = container.querySelectorAll<SVGElement>('[data-id]'); @@ -151,18 +158,18 @@ const update = (action: Action, context: Context, useRefresh: () => void) => { } }; -const panel = (dispatch: Dispatch, context: Context) => { +const panel = (dispatch: Dispatch, context: Context, options?: PanelOptions) => { const panelElem = elem('div'); panelElem.className = 'panel'; children(panelElem, [ context.addMode // - ? addPanel(dispatch, context) + ? addPanel(dispatch, context, options) : editPanel(dispatch, context), ]); return panelElem; }; -const addPanel = (dispatch: Dispatch, context: Context) => { +const addPanel = (dispatch: Dispatch, context: Context, options?: PanelOptions) => { const addPanelElem = elem('div', 'add-panel'); const svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svgElem.setAttribute('width', '144px'); @@ -383,7 +390,7 @@ const toMetadata = (operation: Operation | undefined, x: number, y: number): Met * @param type i.e. 'H' or 'X' */ const gate = (dispatch: Dispatch, type: string, x: number, y: number) => { - const operation = defaultGates[type]; + const operation = gateDictionary[type]; if (operation == null) throw new Error(`Gate ${type} not available`); const metadata = toMetadata(operation, x, y); const gateElem = _formatGate(metadata).cloneNode(true); @@ -396,11 +403,11 @@ const gate = (dispatch: Dispatch, type: string, x: number, y: number) => { return gateElem; }; -interface DefaultGates { +interface GateDictionary { [index: string]: Operation; } -const defaultGates: DefaultGates = { +const gateDictionary: GateDictionary = { H: { gate: 'H', targets: [{ qId: 0 }], @@ -417,4 +424,4 @@ const defaultGates: DefaultGates = { }, }; -export { extensionPanel }; +export { extensionPanel, PanelOptions }; diff --git a/src/sqore.ts b/src/sqore.ts index 15d89f96..1a850113 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -4,7 +4,7 @@ import { Circuit, ConditionalRender, Operation } from './circuit'; import { svgNS } from './constants'; import { extensionDraggable } from './draggable'; -import { extensionPanel } from './panel'; +import { extensionPanel, PanelOptions } from './panel'; import { formatGates } from './formatters/gateFormatter'; import { formatInputs } from './formatters/inputFormatter'; import { formatRegisters } from './formatters/registerFormatter'; @@ -373,12 +373,12 @@ export class Sqore { } public useDraggable(): Sqore { - this.extensions.push(extensionDraggable); + this.extensions = [...this.extensions, extensionDraggable]; return this; } - public usePanel(): Sqore { - this.extensions.push(extensionPanel); + public usePanel(options?: PanelOptions): Sqore { + this.extensions = [...this.extensions, extensionPanel(options)]; return this; } @@ -388,7 +388,7 @@ export class Sqore { _sqore: Sqore, _useRender: () => void, ) => callback(this.circuit); - this.extensions.push(extensionOnCircuitChange); + this.extensions = [...this.extensions, extensionOnCircuitChange]; return this; } } From c82fd00e92bad74247dd3feec74339b59eaad1d8 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 27 Jul 2022 09:22:59 -0400 Subject: [PATCH 073/108] Rename useRender to useRefresh --- src/draggable.ts | 4 ++-- src/sqore.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/draggable.ts b/src/draggable.ts index 10ece347..46cae392 100644 --- a/src/draggable.ts +++ b/src/draggable.ts @@ -26,7 +26,7 @@ interface Context { * @param sqore Sqore object * @param onCircuitChange User-provided callback function triggered when circuit is changed */ -const extensionDraggable = (container: HTMLElement, sqore: Sqore, useRender: () => void): void => { +const extensionDraggable = (container: HTMLElement, sqore: Sqore, useRefresh: () => void): void => { const svg = container.querySelector('svg[id]') as SVGElement; const context: Context = { @@ -34,7 +34,7 @@ const extensionDraggable = (container: HTMLElement, sqore: Sqore, useRender: () svg, operations: sqore.circuit.operations, wireData: _wireData(container), - renderFn: useRender, + renderFn: useRefresh, paddingY: 20, selectedId: null, selectedWire: null, diff --git a/src/sqore.ts b/src/sqore.ts index 1a850113..600a9b27 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -34,7 +34,7 @@ type GateRegistry = { }; type Extension = { - (container: HTMLElement, sqore: Sqore, useRender: () => void): void; + (container: HTMLElement, sqore: Sqore, useRefresh: () => void): void; }; /** @@ -130,7 +130,7 @@ export class Sqore { : container.replaceChild(svg, previousSvg); this.addGateClickHandlers(container, _circuit); - // Run extensions after every render or re-render + // Run extensions after every render or refresh const extensions = this.extensions; extensions != null && extensions.map((extension) => extension(container, this, () => this.renderCircuit(container))); @@ -386,7 +386,7 @@ export class Sqore { const extensionOnCircuitChange = ( _container: HTMLElement, // _sqore: Sqore, - _useRender: () => void, + _useRefresh: () => void, ) => callback(this.circuit); this.extensions = [...this.extensions, extensionOnCircuitChange]; return this; From 094fe7b95e71a5abd530eabaa2f8a9813d4188ed Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Wed, 27 Jul 2022 10:41:38 -0400 Subject: [PATCH 074/108] Enable ghost element when dragging --- src/panel.ts | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/styles.ts | 10 +++++++++ 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index fc0223f9..e3688f5e 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -89,6 +89,10 @@ const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => } }), ); + + document.addEventListener('mouseup', () => { + dispatch({ type: 'REMOVE_GHOST_ELEMENT' }); + }); }; interface Action { @@ -154,6 +158,44 @@ const update = (action: Action, context: Context, useRefresh: () => void) => { case 'DISPLAY_CURSOR_MOVING': { const { container } = context; container && container.classList.add('moving'); + break; + } + case 'DISPLAY_GHOST_ELEMENT': { + const handleMouseMove = (ev: MouseEvent) => { + divElem.style.left = `${ev.clientX - minGateWidth / 2}px`; + divElem.style.top = `${ev.clientY - gateHeight / 2}px`; + }; + + const { container } = context; + const { ghostElem, initX, initY } = action.payload as { + ghostElem: SVGGraphicsElement; + initX: number; + initY: number; + }; + + // Generate svg element to wrap around ghost element + const svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svgElem.append(ghostElem); + + // Generate div element to wrap around svg element + const divElem = elem('div', 'ghost'); + divElem.style.left = `${initX - minGateWidth / 2}px`; + divElem.style.top = `${initY - gateHeight / 2}px`; + divElem.appendChild(svgElem); + + if (container) { + container.appendChild(divElem); + container.addEventListener('mousemove', handleMouseMove); + } + + break; + } + case 'REMOVE_GHOST_ELEMENT': { + const { container } = context; + if (container) { + const ghostElem = container.querySelector('.ghost'); + ghostElem && container.removeChild(ghostElem); + } } } }; @@ -393,13 +435,21 @@ const gate = (dispatch: Dispatch, type: string, x: number, y: number) => { const operation = gateDictionary[type]; if (operation == null) throw new Error(`Gate ${type} not available`); const metadata = toMetadata(operation, x, y); - const gateElem = _formatGate(metadata).cloneNode(true); - gateElem.addEventListener('mousedown', () => { - // dispatch({ type: 'ADD_OPERATION', payload: operation }); + const gateElem = _formatGate(metadata).cloneNode(true) as SVGElement; + gateElem.addEventListener('mousedown', (ev: MouseEvent) => { + // Generate equivalent ghost element with x and y at 0 + const ghostMetadata = toMetadata(operation, 0, 0); + const ghostElem = _formatGate(ghostMetadata).cloneNode(true); + // Get initial x and y position from 'mousedown' event + const { clientX: initX, clientY: initY } = ev; + + // Dispatch relevant events dispatch({ type: 'OPERATION', payload: cloneDeep(operation) }); dispatch({ type: 'DISPLAY_DROPZONE_LAYER' }); dispatch({ type: 'DISPLAY_CURSOR_MOVING', payload: true }); + dispatch({ type: 'DISPLAY_GHOST_ELEMENT', payload: { ghostElem, initX, initY } }); }); + return gateElem; }; diff --git a/src/styles.ts b/src/styles.ts index 82e00cf5..86a341d3 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +import { gateHeight, minGateWidth } from './constants'; + /** * Provides configuration for CSS styles of visualization. */ @@ -280,6 +282,7 @@ const _panel = ` .title { margin: 0 0 4px; font-size: 1.2rem; + user-select: none; } .block { display: block; @@ -292,4 +295,11 @@ const _panel = ` height: 40px; border: 1px solid black; } + .ghost { + width: ${minGateWidth}px; + height: ${gateHeight}px; + position: absolute; + z-index: 1; + pointer-events: none; + } `; From e1f0d2134380a7b4d587f44dfe947a0886af1bca Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 28 Jul 2022 10:45:33 -0400 Subject: [PATCH 075/108] Add `options` functionalities in Add Panel --- example/script.js | 6 +---- src/constants.ts | 6 +++++ src/panel.ts | 65 +++++++++++++++++++++++++++++++++-------------- src/styles.ts | 8 ++++-- 4 files changed, 59 insertions(+), 26 deletions(-) diff --git a/example/script.js b/example/script.js index d65eb0d7..69b5639a 100644 --- a/example/script.js +++ b/example/script.js @@ -9,16 +9,12 @@ if (typeof qviz != 'undefined') { if (entangleDiv != null) { qviz.create(entangle) // .useDraggable() - .usePanel() + .usePanel({ displaySize: 3 }) .draw(entangleDiv); } const sampleDiv = document.getElementById('sample'); if (sampleDiv != null) { - /* Pass in isEditable = true to allow circuit to be editable */ - /* Pass in onCircuitChange to trigger callback function - whenever there is a change in circuit */ - // qviz.draw(sample, sampleDiv, qviz.STYLES['Default'], 0, isEditable, onCircuitChange); qviz.create(sample) // .useDraggable() .usePanel() diff --git a/src/constants.ts b/src/constants.ts index 2ccb9e33..3cfb3579 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -37,3 +37,9 @@ export const labelFontSize = 14; export const argsFontSize = 12; /** Starting x coord for each register wire. */ export const regLineStart = 40; + +// Panel +/** Panel width */ +export const panelWidth = 144; +/** Gap between gates in Add Panel */ +export const gateGap = 50; diff --git a/src/panel.ts b/src/panel.ts index e3688f5e..70a25038 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -1,7 +1,7 @@ import cloneDeep from 'lodash/cloneDeep'; import range from 'lodash/range'; import { Operation } from './circuit'; -import { gateHeight, minGateWidth } from './constants'; +import { gateGap, gateHeight, minGateWidth, panelWidth } from './constants'; import { _equivOperation, _equivParentArray, _lastIndex } from './draggable'; import { _formatGate } from './formatters/gateFormatter'; import { GateType, Metadata } from './metadata'; @@ -26,8 +26,8 @@ const context: Context = { }; interface PanelOptions { - gateDictionary?: GateDictionary; displaySize?: number; + gateDictionary?: GateDictionary; } const extensionPanel = @@ -90,9 +90,10 @@ const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => }), ); - document.addEventListener('mouseup', () => { - dispatch({ type: 'REMOVE_GHOST_ELEMENT' }); - }); + svgElem && + svgElem.addEventListener('mouseup', () => { + dispatch({ type: 'REMOVE_GHOST_ELEMENT' }); + }); }; interface Action { @@ -212,18 +213,37 @@ const panel = (dispatch: Dispatch, context: Context, options?: PanelOptions) => }; const addPanel = (dispatch: Dispatch, context: Context, options?: PanelOptions) => { - const addPanelElem = elem('div', 'add-panel'); + let gateDictionary = defaultGateDictionary; + let objectKeys = Object.keys(gateDictionary); + if (options != null) { + const { displaySize, gateDictionary: optionGateDictionary } = options; + displaySize && (objectKeys = objectKeys.slice(0, displaySize)); + optionGateDictionary && (gateDictionary = optionGateDictionary); + } + + let prefixX = 0; + let prefixY = 0; + const gateElems = objectKeys.map((key) => { + const gateElem = gate(dispatch, gateDictionary, key.toString(), prefixX, prefixY); + if (prefixX + gateGap > panelWidth) { + prefixX = 0; + prefixY += gateGap; + } else { + prefixX += gateGap; + } + return gateElem; + }); + + // Generate svg container to store gate elements const svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - svgElem.setAttribute('width', '144px'); - svgElem.setAttribute('height', '100%'); - const hGate = gate(dispatch, 'H', 0, 0); - const xGate = gate(dispatch, 'X', 50, 0); - const x2Gate = gate(dispatch, 'X', 100, 0); - svgElem.appendChild(hGate); - svgElem.appendChild(xGate); - svgElem.appendChild(x2Gate); + svgElem.classList.add('add-panel-svg'); + childrenSvg(svgElem, gateElems); + + // Generate add panel + const addPanelElem = elem('div', 'add-panel'); children(addPanelElem, [title('ADD')]); addPanelElem.appendChild(svgElem); + return addPanelElem; }; @@ -257,6 +277,11 @@ const children = (parentElem: HTMLElement, childElems: HTMLElement[]) => { return parentElem; }; +const childrenSvg = (parentElem: SVGElement, childElems: SVGElement[]) => { + childElems.map((elem) => parentElem.appendChild(elem)); + return parentElem; +}; + const title = (text: string) => { const titleElem = elem('h2'); titleElem.className = 'title'; @@ -431,7 +456,7 @@ const toMetadata = (operation: Operation | undefined, x: number, y: number): Met * @param dispatch * @param type i.e. 'H' or 'X' */ -const gate = (dispatch: Dispatch, type: string, x: number, y: number) => { +const gate = (dispatch: Dispatch, gateDictionary: GateDictionary, type: string, x: number, y: number) => { const operation = gateDictionary[type]; if (operation == null) throw new Error(`Gate ${type} not available`); const metadata = toMetadata(operation, x, y); @@ -457,20 +482,22 @@ interface GateDictionary { [index: string]: Operation; } -const gateDictionary: GateDictionary = { +const defaultGateDictionary: GateDictionary = { + RX: { + gate: 'RX', + targets: [{ qId: 0 }], + }, H: { gate: 'H', targets: [{ qId: 0 }], }, X: { gate: 'X', - isControlled: true, targets: [{ qId: 0 }], }, ZZ: { gate: 'ZZ', - targets: [{ qId: 0 }, { qId: 1 }], - isControlled: true, + targets: [{ qId: 0 }], }, }; diff --git a/src/styles.ts b/src/styles.ts index 86a341d3..68ee107e 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { gateHeight, minGateWidth } from './constants'; +import { gateHeight, minGateWidth, panelWidth } from './constants'; /** * Provides configuration for CSS styles of visualization. @@ -271,7 +271,7 @@ const _panel = ` display: flex; } .panel { - width: 144px; + width: ${panelWidth}; border: solid 1px black; padding: 8px; } @@ -295,6 +295,10 @@ const _panel = ` height: 40px; border: 1px solid black; } + .add-panel-svg { + width: ${panelWidth}px; + height: 100%; + } .ghost { width: ${minGateWidth}px; height: ${gateHeight}px; From 8fa5804f14c458cba2bb97530b22412bb1b8d18c Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 28 Jul 2022 11:12:24 -0400 Subject: [PATCH 076/108] Refactor payload for addMode & cancel event when dragging --- src/panel.ts | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index 70a25038..1bbcdb05 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -58,7 +58,7 @@ const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => const dataId = elem.getAttribute('data-id'); const operation = _equivOperation(dataId, sqore.circuit.operations); dispatch({ type: 'OPERATION', payload: operation }); - dispatch({ type: 'ADD_MODE', payload: false }); + dispatch({ type: 'EDIT_MODE' }); }), ); @@ -69,10 +69,9 @@ const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => }); const svgElem = container.querySelector('svg[id]'); - svgElem && - svgElem.addEventListener('mousedown', () => { - dispatch({ type: 'ADD_MODE', payload: true }); - }); + svgElem?.addEventListener('mousedown', () => { + dispatch({ type: 'ADD_MODE' }); + }); const dropzoneLayer = container.querySelector('.dropzone-layer') as SVGGElement; const dropzoneElems = dropzoneLayer.querySelectorAll<SVGRectElement>('.dropzone'); @@ -90,10 +89,12 @@ const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => }), ); - svgElem && - svgElem.addEventListener('mouseup', () => { - dispatch({ type: 'REMOVE_GHOST_ELEMENT' }); - }); + svgElem?.addEventListener('mouseup', () => { + dispatch({ type: 'REMOVE_GHOST_ELEMENT' }); + }); + container.querySelector('.add-panel')?.addEventListener('mouseup', () => { + dispatch({ type: 'REMOVE_GHOST_ELEMENT' }); + }); }; interface Action { @@ -104,7 +105,11 @@ interface Action { const update = (action: Action, context: Context, useRefresh: () => void) => { switch (action.type) { case 'ADD_MODE': { - context.addMode = action.payload as boolean; + context.addMode = true; + break; + } + case 'EDIT_MODE': { + context.addMode = false; break; } case 'OPERATION': { From 56285c3a5758864cf129ece0ee3f934353f2a3dd Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 28 Jul 2022 11:32:26 -0400 Subject: [PATCH 077/108] Add more gates into defaultGateDictionary --- src/panel.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/panel.ts b/src/panel.ts index 1bbcdb05..5fb255bd 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -492,6 +492,14 @@ const defaultGateDictionary: GateDictionary = { gate: 'RX', targets: [{ qId: 0 }], }, + RY: { + gate: 'RY', + targets: [{ qId: 0 }], + }, + RZ: { + gate: 'RZ', + targets: [{ qId: 0 }], + }, H: { gate: 'H', targets: [{ qId: 0 }], @@ -500,6 +508,22 @@ const defaultGateDictionary: GateDictionary = { gate: 'X', targets: [{ qId: 0 }], }, + S: { + gate: 'S', + targets: [{ qId: 0 }], + }, + T: { + gate: 'T', + targets: [{ qId: 0 }], + }, + Y: { + gate: 'Y', + targets: [{ qId: 0 }], + }, + Z: { + gate: 'Z', + targets: [{ qId: 0 }], + }, ZZ: { gate: 'ZZ', targets: [{ qId: 0 }], From b4d5127749b7b2c35f30c819970b0773e5d75140 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 28 Jul 2022 14:55:21 -0400 Subject: [PATCH 078/108] Support Entangle in Add Panel --- src/constants.ts | 3 ++- src/panel.ts | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 3cfb3579..71123456 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -42,4 +42,5 @@ export const regLineStart = 40; /** Panel width */ export const panelWidth = 144; /** Gap between gates in Add Panel */ -export const gateGap = 50; +export const horizontalGap = 10; +export const verticalGap = 10; diff --git a/src/panel.ts b/src/panel.ts index 5fb255bd..13956692 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -1,7 +1,7 @@ import cloneDeep from 'lodash/cloneDeep'; import range from 'lodash/range'; import { Operation } from './circuit'; -import { gateGap, gateHeight, minGateWidth, panelWidth } from './constants'; +import { gateHeight, horizontalGap, minGateWidth, panelWidth, verticalGap } from './constants'; import { _equivOperation, _equivParentArray, _lastIndex } from './draggable'; import { _formatGate } from './formatters/gateFormatter'; import { GateType, Metadata } from './metadata'; @@ -229,13 +229,13 @@ const addPanel = (dispatch: Dispatch, context: Context, options?: PanelOptions) let prefixX = 0; let prefixY = 0; const gateElems = objectKeys.map((key) => { - const gateElem = gate(dispatch, gateDictionary, key.toString(), prefixX, prefixY); - if (prefixX + gateGap > panelWidth) { + const { width: gateWidth } = toMetadata(gateDictionary[key], 0, 0); + if (prefixX + gateWidth + horizontalGap > panelWidth) { prefixX = 0; - prefixY += gateGap; - } else { - prefixX += gateGap; + prefixY += gateHeight + verticalGap; } + const gateElem = gate(dispatch, gateDictionary, key.toString(), prefixX, prefixY); + prefixX += gateWidth + horizontalGap; return gateElem; }); @@ -451,7 +451,9 @@ const toMetadata = (operation: Operation | undefined, x: number, y: number): Met } if (displayArgs != null) metadata.displayArgs = displayArgs; + metadata.width = getGateWidth(metadata); + metadata.x = x + 1 + metadata.width / 2; // offset by 1 for left padding return metadata; }; @@ -488,6 +490,10 @@ interface GateDictionary { } const defaultGateDictionary: GateDictionary = { + Entangle: { + gate: 'Entangle', + targets: [{ qId: 0 }], + }, RX: { gate: 'RX', targets: [{ qId: 0 }], From 961963c93d491dc5800f6a78e6d957f83488025e Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 28 Jul 2022 16:57:30 -0400 Subject: [PATCH 079/108] Fix selector bug --- src/draggable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/draggable.ts b/src/draggable.ts index 46cae392..2b678be1 100644 --- a/src/draggable.ts +++ b/src/draggable.ts @@ -187,7 +187,7 @@ const _dropzoneLayer = (context: Context) => { */ const _wireData = (container: HTMLElement): number[] => { // elems include qubit wires and lines of measure gates - const elems = container.querySelectorAll<SVGGElement>('svg > g:nth-child(3) > g'); + const elems = container.querySelectorAll<SVGGElement>('svg[id] > g:nth-child(3) > g'); // filter out <g> elements having more than 2 elements because // qubit wires contain only 2 elements: <line> and <text> // lines of measure gates contain 4 <line> elements From 54b66fdaa1ba84aa692d167f2a87aa8f7efb36ac Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Sat, 30 Jul 2022 14:21:58 -0400 Subject: [PATCH 080/108] Rename editable to draggable tests --- __tests__/{editable.test.ts => draggable.test.ts} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename __tests__/{editable.test.ts => draggable.test.ts} (98%) diff --git a/__tests__/editable.test.ts b/__tests__/draggable.test.ts similarity index 98% rename from __tests__/editable.test.ts rename to __tests__/draggable.test.ts index 0fde4705..a923d8cb 100644 --- a/__tests__/editable.test.ts +++ b/__tests__/draggable.test.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { exportedForTesting } from '../src/editable'; -import { Circuit, draw, Operation, STYLES } from '../src/index'; +import { exportedForTesting } from '../src/draggable'; +import { Circuit, create, Operation } from '../src/index'; const { _wireYs, @@ -49,7 +49,7 @@ describe('Test _hostElems', () => { }, ], }; - draw(circuit, container, STYLES['default']); + create(circuit).draw(container); }); test('should return 4 elements', () => { expect(_hostElems(container)).toMatchSnapshot(); @@ -142,7 +142,7 @@ describe('Test _wireData', () => { }, ], }; - draw(circuit, container, STYLES['default']); + create(circuit).draw(container); expect(_wireData(container)).toStrictEqual([40, 100]); }); test('3 wires should return [40,100, 180]', () => { @@ -168,7 +168,7 @@ describe('Test _wireData', () => { }, ], }; - draw(circuit, container, STYLES['default']); + create(circuit).draw(container); expect(_wireData(container)).toStrictEqual([40, 100, 180]); }); }); @@ -198,7 +198,7 @@ describe('Test _equivGateElem', () => { }, ], }; - draw(circuit, container, STYLES['default']); + create(circuit).draw(container); }); test('should return gate H', () => { const elem = container.querySelector('[class^="gate-"]') as SVGElement; From f2d8cd5e4f5e3772ead151db57ccd3911b0301b0 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Sat, 30 Jul 2022 14:22:31 -0400 Subject: [PATCH 081/108] Add return signatures --- src/panel.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index 13956692..681c60d8 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -206,7 +206,7 @@ const update = (action: Action, context: Context, useRefresh: () => void) => { } }; -const panel = (dispatch: Dispatch, context: Context, options?: PanelOptions) => { +const panel = (dispatch: Dispatch, context: Context, options?: PanelOptions): HTMLElement => { const panelElem = elem('div'); panelElem.className = 'panel'; children(panelElem, [ @@ -217,7 +217,7 @@ const panel = (dispatch: Dispatch, context: Context, options?: PanelOptions) => return panelElem; }; -const addPanel = (dispatch: Dispatch, context: Context, options?: PanelOptions) => { +const addPanel = (dispatch: Dispatch, context: Context, options?: PanelOptions): HTMLElement => { let gateDictionary = defaultGateDictionary; let objectKeys = Object.keys(gateDictionary); if (options != null) { @@ -252,7 +252,7 @@ const addPanel = (dispatch: Dispatch, context: Context, options?: PanelOptions) return addPanelElem; }; -const editPanel = (dispatch: Dispatch, context: Context) => { +const editPanel = (dispatch: Dispatch, context: Context): HTMLElement => { const { operation, registerSize } = context; const options = range(registerSize).map((i) => ({ value: `${i}`, text: `q${i}` })); const target = operation?.targets[0].qId; @@ -277,17 +277,17 @@ const elem = (tag: string, className?: string): HTMLElement => { /** * Append all child elements to a parent element */ -const children = (parentElem: HTMLElement, childElems: HTMLElement[]) => { +const children = (parentElem: HTMLElement, childElems: HTMLElement[]): HTMLElement => { childElems.map((elem) => parentElem.appendChild(elem)); return parentElem; }; -const childrenSvg = (parentElem: SVGElement, childElems: SVGElement[]) => { +const childrenSvg = (parentElem: SVGElement, childElems: SVGElement[]): SVGElement => { childElems.map((elem) => parentElem.appendChild(elem)); return parentElem; }; -const title = (text: string) => { +const title = (text: string): HTMLElement => { const titleElem = elem('h2'); titleElem.className = 'title'; titleElem.innerText = text; @@ -332,7 +332,7 @@ const select = ( return divElem; }; -const option = (value: string, text: string) => { +const option = (value: string, text: string): HTMLOptionElement => { const optionElem = elem('option') as HTMLOptionElement; optionElem.value = value; optionElem.textContent = text; @@ -346,7 +346,7 @@ const checkboxes = ( selectedIndexes: number[], dispatch: Dispatch, operation?: Operation, -) => { +): HTMLDivElement => { const checkboxElems = options.map((option, index) => { const elem = checkbox(option.value, option.text); const inputElem = elem.querySelector('input') as HTMLInputElement; @@ -378,7 +378,7 @@ const checkboxes = ( return divElem; }; -const checkbox = (value: string, text: string) => { +const checkbox = (value: string, text: string): HTMLLabelElement => { const inputElem = elem('input') as HTMLInputElement; inputElem.type = 'checkbox'; inputElem.value = value; @@ -389,7 +389,7 @@ const checkbox = (value: string, text: string) => { return labelElem; }; -const text = (label: string, className: string, dispatch: Dispatch, operation?: Operation) => { +const text = (label: string, className: string, dispatch: Dispatch, operation?: Operation): HTMLElement => { const labelElem = elem('label') as HTMLLabelElement; labelElem.className = 'block'; labelElem.textContent = label; @@ -463,7 +463,7 @@ const toMetadata = (operation: Operation | undefined, x: number, y: number): Met * @param dispatch * @param type i.e. 'H' or 'X' */ -const gate = (dispatch: Dispatch, gateDictionary: GateDictionary, type: string, x: number, y: number) => { +const gate = (dispatch: Dispatch, gateDictionary: GateDictionary, type: string, x: number, y: number): SVGElement => { const operation = gateDictionary[type]; if (operation == null) throw new Error(`Gate ${type} not available`); const metadata = toMetadata(operation, x, y); From 7d2e05a7f9ea8301436b8e04ad6daade921c1102 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Sat, 30 Jul 2022 14:34:36 -0400 Subject: [PATCH 082/108] Update draggable snapshot --- .../{editable.test.ts.snap => draggable.test.ts.snap} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename __tests__/__snapshots__/{editable.test.ts.snap => draggable.test.ts.snap} (100%) diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/draggable.test.ts.snap similarity index 100% rename from __tests__/__snapshots__/editable.test.ts.snap rename to __tests__/__snapshots__/draggable.test.ts.snap From aef2eb01ea024d974ab23699cec24d230748a16a Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Sun, 31 Jul 2022 11:54:42 -0400 Subject: [PATCH 083/108] Add tests --- __tests__/__snapshots__/panel.test.ts.snap | 403 +++++++++++++++++++++ __tests__/panel.test.ts | 300 +++++++++++++++ src/panel.ts | 27 +- 3 files changed, 727 insertions(+), 3 deletions(-) create mode 100644 __tests__/__snapshots__/panel.test.ts.snap create mode 100644 __tests__/panel.test.ts diff --git a/__tests__/__snapshots__/panel.test.ts.snap b/__tests__/__snapshots__/panel.test.ts.snap new file mode 100644 index 00000000..7b1a87e1 --- /dev/null +++ b/__tests__/__snapshots__/panel.test.ts.snap @@ -0,0 +1,403 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test checkbox Should return checkbox q0 1`] = ` +<label> + <input + type="checkbox" + value="0" + /> + q0 +</label> +`; + +exports[`Test checkbox Should return checkbox q1 1`] = ` +<label> + <input + type="checkbox" + value="1" + /> + q1 +</label> +`; + +exports[`Test checkbox Should return checkbox q2 1`] = ` +<label> + <input + type="checkbox" + value="2" + /> + q2 +</label> +`; + +exports[`Test checkboxes Test with gate X with 1 control 1`] = ` +<div + class="controls-input" +> + <label + class="block" + > + Controls + </label> + <label> + <input + type="checkbox" + value="0" + /> + q0 + </label> + <label> + <input + checked="true" + type="checkbox" + value="1" + /> + q1 + </label> +</div> +`; + +exports[`Test checkboxes Test with gate X with 2 controls 1`] = ` +<div + class="controls-input" +> + <label + class="block" + > + Controls + </label> + <label> + <input + checked="true" + type="checkbox" + value="0" + /> + q0 + </label> + <label> + <input + type="checkbox" + value="1" + /> + q1 + </label> + <label> + <input + checked="true" + type="checkbox" + value="2" + /> + q2 + </label> +</div> +`; + +exports[`Test children Add 0 with class to parent 1`] = `<div />`; + +exports[`Test children Add 1 child to parent 1`] = ` +<div> + <p /> +</div> +`; + +exports[`Test children Add 2 children to parent 1`] = ` +<div> + <p /> + <div /> +</div> +`; + +exports[`Test childrenSvg Add 0 child to parent 1`] = `<svg />`; + +exports[`Test childrenSvg Add 1 child to parent 1`] = ` +<svg> + <rect /> +</svg> +`; + +exports[`Test childrenSvg Add 2 children to parent 1`] = ` +<svg> + <rect /> + <circle /> +</svg> +`; + +exports[`Test editPanel 1`] = ` +<div + class="edit-panel" +> + <h2 + class="title" + > + EDIT + </h2> + <div + class="target-input" + > + <label + class="block" + > + Target + </label> + <select> + <option + value="0" + > + q0 + </option> + <option + value="1" + > + q1 + </option> + </select> + </div> + <div + class="controls-input" + > + <label + class="block" + > + Controls + </label> + <label> + <input + type="checkbox" + value="0" + /> + q0 + </label> + <label> + <input + type="checkbox" + value="1" + /> + q1 + </label> + </div> + <div + class="display-input" + > + <label + class="block" + > + Display + </label> + <input + autofocus="true" + type="text" + /> + </div> +</div> +`; + +exports[`Test elem Should return <div> 1`] = `<div />`; + +exports[`Test elem Should return <div> with className "panel" 1`] = ` +<div + class="panel" +/> +`; + +exports[`Test elem Should return <p> 1`] = `<p />`; + +exports[`Test gate Should return gate H 1`] = ` +<g + class="gate" +> + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="1" + /> + <text + font-size="14" + x="21" + y="21" + > + H + </text> + </g> + </g> +</g> +`; + +exports[`Test gate Should return gate RX 1`] = ` +<g + class="gate" +> + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="1" + /> + <text + font-size="14" + x="21" + y="21" + > + RX + </text> + </g> + </g> +</g> +`; + +exports[`Test gate Should return gate X 1`] = ` +<g + class="gate" +> + <g + class="oplus" + > + <circle + cx="21" + cy="21" + r="15" + /> + <line + x1="21" + x2="21" + y1="6" + y2="36" + /> + <line + x1="6" + x2="36" + y1="21" + y2="21" + /> + </g> +</g> +`; + +exports[`Test option Should return option q0 1`] = ` +<option + value="0" +> + q0 +</option> +`; + +exports[`Test option Should return option q1 1`] = ` +<option + value="1" +> + q1 +</option> +`; + +exports[`Test option Should return option q2 1`] = ` +<option + value="2" +> + q2 +</option> +`; + +exports[`Test text Should return gate H without display-args 1`] = ` +<div + class="display-input" +> + <label + class="block" + > + Display + </label> + <input + autofocus="true" + type="text" + /> +</div> +`; + +exports[`Test text Should return gate RX with display-args 1`] = ` +<div + class="display-input" +> + <label + class="block" + > + Display + </label> + <input + autofocus="true" + type="text" + /> +</div> +`; + +exports[`Test title Should return title "ADD" 1`] = ` +<h2 + class="title" +> + ADD +</h2> +`; + +exports[`Test title Should return title "EDIT" 1`] = ` +<h2 + class="title" +> + EDIT +</h2> +`; + +exports[`Test title Should return title "PANEL" 1`] = ` +<h2 + class="title" +> + PANEL +</h2> +`; + +exports[`Test toMetadata Should return metadata of gate H 1`] = ` +Object { + "controlsY": Array [], + "label": "H", + "targetsY": Array [ + Array [ + 21, + ], + ], + "type": 4, + "width": 40, + "x": 21, +} +`; + +exports[`Test toMetadata Should return metadata of gate RX 1`] = ` +Object { + "controlsY": Array [], + "label": "H", + "targetsY": Array [ + Array [ + 21, + ], + ], + "type": 4, + "width": 40, + "x": 21, +} +`; + +exports[`Test toMetadata Should return metadata of gate X 1`] = ` +Object { + "controlsY": Array [], + "label": "X", + "targetsY": Array [ + 21, + ], + "type": 3, + "width": 40, + "x": 21, +} +`; diff --git a/__tests__/panel.test.ts b/__tests__/panel.test.ts new file mode 100644 index 00000000..d18c1d01 --- /dev/null +++ b/__tests__/panel.test.ts @@ -0,0 +1,300 @@ +import range from 'lodash/range'; +import { PanelContext } from '../src/panel'; +import { Action, Dispatch, exportedForTesting } from '../src/panel'; + +const { + editPanel, + elem, + children, + childrenSvg, + title, + select, + option, + checkboxes, + checkbox, + text, + toMetadata, + gate, + defaultGateDictionary, +} = exportedForTesting; + +describe('Test elem', () => { + test('Should return <div>', () => { + expect(elem('div')).toMatchSnapshot(); + }); + test('Should return <p>', () => { + expect(elem('p')).toMatchSnapshot(); + }); + test('Should return <div> with className "panel"', () => { + expect(elem('div', 'panel')).toMatchSnapshot(); + }); +}); + +describe('Test children', () => { + let parentElem: HTMLDivElement; + beforeEach(() => { + parentElem = document.createElement('div'); + }); + test('Add 1 child to parent', () => { + const childElems = [document.createElement('p')] as HTMLElement[]; + expect(children(parentElem, childElems)).toMatchSnapshot(); + }); + test('Add 2 children to parent', () => { + const childElems = [document.createElement('p'), document.createElement('div')] as HTMLElement[]; + expect(children(parentElem, childElems)).toMatchSnapshot(); + }); + test('Add 0 with class to parent', () => { + const childElems = [] as HTMLElement[]; + expect(children(parentElem, childElems)).toMatchSnapshot(); + }); +}); + +describe('Test childrenSvg', () => { + let parentElem: SVGElement; + beforeEach(() => { + parentElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + }); + test('Add 0 child to parent', () => { + const childElems = [] as SVGElement[]; + expect(childrenSvg(parentElem, childElems)).toMatchSnapshot(); + }); + test('Add 1 child to parent', () => { + const childElems = [document.createElementNS('http://www.w3.org/2000/svg', 'rect')] as SVGElement[]; + expect(childrenSvg(parentElem, childElems)).toMatchSnapshot(); + }); + test('Add 2 children to parent', () => { + const childElems = [ + document.createElementNS('http://www.w3.org/2000/svg', 'rect'), // + document.createElementNS('http://www.w3.org/2000/svg', 'circle'), // + ] as SVGElement[]; + expect(childrenSvg(parentElem, childElems)).toMatchSnapshot(); + }); +}); + +describe('Test title', () => { + test('Should return title "PANEL"', () => { + expect(title('PANEL')).toMatchSnapshot(); + }); + test('Should return title "ADD"', () => { + expect(title('ADD')).toMatchSnapshot(); + }); + test('Should return title "EDIT"', () => { + expect(title('EDIT')).toMatchSnapshot(); + }); +}); + +describe('Test text', () => { + const emptyDispatch: Dispatch = (action: Action) => { + action; + }; + test('Should return gate H without display-args', () => { + const operation = { + gate: 'H', + targets: [{ qId: 0 }], + }; + expect(text('Display', 'display-input', emptyDispatch, operation)).toMatchSnapshot(); + }); + test('Should return gate RX with display-args', () => { + const operation = { + gate: 'RX', + displayArgs: '(0.25)', + isControlled: true, + controls: [{ qId: 1 }], + targets: [{ qId: 0 }], + }; + expect(text('Display', 'display-input', emptyDispatch, operation)).toMatchSnapshot(); + }); +}); + +describe('Test toMetadata', () => { + test('Should return metadata of gate H', () => { + const operation = { + gate: 'H', + targets: [{ qId: 0 }], + }; + expect(toMetadata(operation, 0, 0)).toMatchSnapshot(); + }); + test('Should return metadata of gate RX', () => { + const operation = { + gate: 'H', + targets: [{ qId: 0 }], + }; + expect(toMetadata(operation, 0, 0)).toMatchSnapshot(); + }); + test('Should return metadata of gate X', () => { + const operation = { + gate: 'X', + targets: [{ qId: 3 }], + }; + expect(toMetadata(operation, 0, 0)).toMatchSnapshot(); + }); +}); + +describe('Test select', () => { + const emptyDispatch: Dispatch = (action: Action) => { + action; + }; + test('Test with gate X', () => { + const operation = { + gate: 'X', + targets: [{ qId: 0 }], + controls: [{ qId: 1 }], + }; + const registerSize = 2; + const options = range(registerSize).map((i) => ({ value: `${i}`, text: `q${i}` })); + const target = operation?.targets[0].qId; + select('Target', 'target-input', options, target || 0, emptyDispatch, operation); + }); + test('Test with gate H', () => { + const operation = { + gate: 'H', + targets: [{ qId: 0 }], + }; + const registerSize = 2; + const options = range(registerSize).map((i) => ({ value: `${i}`, text: `q${i}` })); + const target = operation?.targets[0].qId; + select('Target', 'target-input', options, target || 0, emptyDispatch, operation); + }); +}); + +describe('Test option', () => { + test('Should return option q0', () => { + expect(option('0', 'q0')).toMatchSnapshot(); + }); + test('Should return option q1', () => { + expect(option('1', 'q1')).toMatchSnapshot(); + }); + test('Should return option q2', () => { + expect(option('2', 'q2')).toMatchSnapshot(); + }); +}); + +describe('Test checkboxes', () => { + const emptyDispatch: Dispatch = (action: Action) => { + action; + }; + test('Test with gate X with 1 control', () => { + const operation = { + gate: 'X', + targets: [{ qId: 0 }], + controls: [{ qId: 1 }], + }; + const registerSize = 2; + const options = range(registerSize).map((i) => ({ value: `${i}`, text: `q${i}` })); + const controls = operation.controls?.map((control) => control.qId); + expect( + checkboxes('Controls', 'controls-input', options, controls || [], emptyDispatch, operation), + ).toMatchSnapshot(); + }); + test('Test with gate X with 2 controls', () => { + const operation = { + gate: 'X', + targets: [{ qId: 1 }], + controls: [{ qId: 0 }, { qId: 2 }], + }; + const registerSize = 3; + const options = range(registerSize).map((i) => ({ value: `${i}`, text: `q${i}` })); + const controls = operation.controls?.map((control) => control.qId); + expect( + checkboxes('Controls', 'controls-input', options, controls || [], emptyDispatch, operation), + ).toMatchSnapshot(); + }); +}); + +describe('Test checkbox', () => { + test('Should return checkbox q0', () => { + expect(checkbox('0', 'q0')).toMatchSnapshot(); + }); + test('Should return checkbox q1', () => { + expect(checkbox('1', 'q1')).toMatchSnapshot(); + }); + test('Should return checkbox q2', () => { + expect(checkbox('2', 'q2')).toMatchSnapshot(); + }); +}); + +describe('Test gate', () => { + const emptyDispatch: Dispatch = (action: Action) => { + action; + }; + test('Should return gate H', () => { + expect(gate(emptyDispatch, defaultGateDictionary, 'H', 0, 0)).toMatchSnapshot(); + }); + test('Should return gate X', () => { + expect(gate(emptyDispatch, defaultGateDictionary, 'X', 0, 0)).toMatchSnapshot(); + }); + test('Should return gate RX', () => { + expect(gate(emptyDispatch, defaultGateDictionary, 'RX', 0, 0)).toMatchSnapshot(); + }); +}); + +describe('Test defaulGateDictionary', () => { + test('Verify defaultGateDictionary', () => { + const expected = { + Entangle: { + gate: 'Entangle', + targets: [{ qId: 0 }], + }, + RX: { + gate: 'RX', + targets: [{ qId: 0 }], + }, + RY: { + gate: 'RY', + targets: [{ qId: 0 }], + }, + RZ: { + gate: 'RZ', + targets: [{ qId: 0 }], + }, + H: { + gate: 'H', + targets: [{ qId: 0 }], + }, + X: { + gate: 'X', + targets: [{ qId: 0 }], + }, + S: { + gate: 'S', + targets: [{ qId: 0 }], + }, + T: { + gate: 'T', + targets: [{ qId: 0 }], + }, + Y: { + gate: 'Y', + targets: [{ qId: 0 }], + }, + Z: { + gate: 'Z', + targets: [{ qId: 0 }], + }, + ZZ: { + gate: 'ZZ', + targets: [{ qId: 0 }], + }, + }; + expect(defaultGateDictionary).toMatchObject(expected); + }); +}); + +describe('Test editPanel', () => { + const emptyDispatch: Dispatch = (action: Action) => { + action; + }; + test('', () => { + const context: PanelContext = { + addMode: false, + operations: [], + operation: { + gate: 'X', + targets: [{ qId: 0 }], + }, + registerSize: 2, + container: undefined, + }; + expect(editPanel(emptyDispatch, context)).toMatchSnapshot(); + }); +}); diff --git a/src/panel.ts b/src/panel.ts index 681c60d8..f2d2e4dd 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -270,7 +270,7 @@ const editPanel = (dispatch: Dispatch, context: Context): HTMLElement => { const elem = (tag: string, className?: string): HTMLElement => { const _elem = document.createElement(tag); - _elem.className = className || ''; + className && (_elem.className = className); return _elem; }; @@ -290,7 +290,7 @@ const childrenSvg = (parentElem: SVGElement, childElems: SVGElement[]): SVGEleme const title = (text: string): HTMLElement => { const titleElem = elem('h2'); titleElem.className = 'title'; - titleElem.innerText = text; + titleElem.textContent = text; return titleElem; }; @@ -536,4 +536,25 @@ const defaultGateDictionary: GateDictionary = { }, }; -export { extensionPanel, PanelOptions }; +/** + * Object exported for unit testing + */ +const exportedForTesting = { + panel, + addPanel, + editPanel, + elem, + children, + childrenSvg, + title, + select, + option, + checkboxes, + checkbox, + text, + toMetadata, + gate, + defaultGateDictionary, +}; + +export { extensionPanel, PanelOptions, exportedForTesting, Dispatch, Action, Context as PanelContext }; From 141f4752af927d7e10131a8b465f9f055a429243 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Sun, 31 Jul 2022 12:00:46 -0400 Subject: [PATCH 084/108] Add tests for addPanel --- __tests__/__snapshots__/panel.test.ts.snap | 323 ++++++++++++++++++++- __tests__/panel.test.ts | 38 ++- 2 files changed, 358 insertions(+), 3 deletions(-) diff --git a/__tests__/__snapshots__/panel.test.ts.snap b/__tests__/__snapshots__/panel.test.ts.snap index 7b1a87e1..04caf3ac 100644 --- a/__tests__/__snapshots__/panel.test.ts.snap +++ b/__tests__/__snapshots__/panel.test.ts.snap @@ -1,5 +1,326 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Test addPanel Should return default addPanel 1`] = ` +<div + class="add-panel" +> + <h2 + class="title" + > + ADD + </h2> + <svg + class="add-panel-svg" + > + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="76" + x="1" + y="1" + /> + <text + font-size="14" + x="39" + y="21" + > + Entangle + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="87" + y="1" + /> + <text + font-size="14" + x="107" + y="21" + > + RX + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="51" + /> + <text + font-size="14" + x="21" + y="71" + > + RY + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="51" + y="51" + /> + <text + font-size="14" + x="71" + y="71" + > + RZ + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="101" + /> + <text + font-size="14" + x="21" + y="121" + > + H + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g + class="oplus" + > + <circle + cx="71" + cy="121" + r="15" + /> + <line + x1="71" + x2="71" + y1="106" + y2="136" + /> + <line + x1="56" + x2="86" + y1="121" + y2="121" + /> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="151" + /> + <text + font-size="14" + x="21" + y="171" + > + S + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="51" + y="151" + /> + <text + font-size="14" + x="71" + y="171" + > + T + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="201" + /> + <text + font-size="14" + x="21" + y="221" + > + Y + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="51" + y="201" + /> + <text + font-size="14" + x="71" + y="221" + > + Z + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="251" + /> + <text + font-size="14" + x="21" + y="271" + > + ZZ + </text> + </g> + </g> + </g> + </svg> +</div> +`; + +exports[`Test addPanel Should return default addPanel with displaySize 2 1`] = ` +<div + class="add-panel" +> + <h2 + class="title" + > + ADD + </h2> + <svg + class="add-panel-svg" + > + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="76" + x="1" + y="1" + /> + <text + font-size="14" + x="39" + y="21" + > + Entangle + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="87" + y="1" + /> + <text + font-size="14" + x="107" + y="21" + > + RX + </text> + </g> + </g> + </g> + </svg> +</div> +`; + exports[`Test checkbox Should return checkbox q0 1`] = ` <label> <input @@ -122,7 +443,7 @@ exports[`Test childrenSvg Add 2 children to parent 1`] = ` </svg> `; -exports[`Test editPanel 1`] = ` +exports[`Test editPanel Should return editPanel editing X gate 1`] = ` <div class="edit-panel" > diff --git a/__tests__/panel.test.ts b/__tests__/panel.test.ts index d18c1d01..0d34fb1d 100644 --- a/__tests__/panel.test.ts +++ b/__tests__/panel.test.ts @@ -1,8 +1,9 @@ import range from 'lodash/range'; -import { PanelContext } from '../src/panel'; +import { PanelContext, PanelOptions } from '../src/panel'; import { Action, Dispatch, exportedForTesting } from '../src/panel'; const { + addPanel, editPanel, elem, children, @@ -284,7 +285,7 @@ describe('Test editPanel', () => { const emptyDispatch: Dispatch = (action: Action) => { action; }; - test('', () => { + test('Should return editPanel editing X gate', () => { const context: PanelContext = { addMode: false, operations: [], @@ -298,3 +299,36 @@ describe('Test editPanel', () => { expect(editPanel(emptyDispatch, context)).toMatchSnapshot(); }); }); + +describe('Test addPanel', () => { + const emptyDispatch: Dispatch = (action: Action) => { + action; + }; + test('Should return default addPanel', () => { + const context: PanelContext = { + addMode: true, + operations: [], + operation: { + gate: 'X', + targets: [{ qId: 0 }], + }, + registerSize: 2, + container: undefined, + }; + expect(addPanel(emptyDispatch, context)).toMatchSnapshot(); + }); + test('Should return default addPanel with displaySize 2', () => { + const context: PanelContext = { + addMode: true, + operations: [], + operation: { + gate: 'X', + targets: [{ qId: 0 }], + }, + registerSize: 2, + container: undefined, + }; + const options: PanelOptions = { displaySize: 2 }; + expect(addPanel(emptyDispatch, context, options)).toMatchSnapshot(); + }); +}); From 0ec4100caf1bd3ae08247095258aba5a6434fc69 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Sun, 31 Jul 2022 12:03:50 -0400 Subject: [PATCH 085/108] Add tests for panel --- __tests__/__snapshots__/panel.test.ts.snap | 338 +++++++++++++++++++++ __tests__/panel.test.ts | 33 ++ 2 files changed, 371 insertions(+) diff --git a/__tests__/__snapshots__/panel.test.ts.snap b/__tests__/__snapshots__/panel.test.ts.snap index 04caf3ac..3892b303 100644 --- a/__tests__/__snapshots__/panel.test.ts.snap +++ b/__tests__/__snapshots__/panel.test.ts.snap @@ -624,6 +624,344 @@ exports[`Test option Should return option q2 1`] = ` </option> `; +exports[`Test panel Should return panel with addPanel visible 1`] = ` +<div + class="panel" +> + <div + class="add-panel" + > + <h2 + class="title" + > + ADD + </h2> + <svg + class="add-panel-svg" + > + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="76" + x="1" + y="1" + /> + <text + font-size="14" + x="39" + y="21" + > + Entangle + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="87" + y="1" + /> + <text + font-size="14" + x="107" + y="21" + > + RX + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="51" + /> + <text + font-size="14" + x="21" + y="71" + > + RY + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="51" + y="51" + /> + <text + font-size="14" + x="71" + y="71" + > + RZ + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="101" + /> + <text + font-size="14" + x="21" + y="121" + > + H + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g + class="oplus" + > + <circle + cx="71" + cy="121" + r="15" + /> + <line + x1="71" + x2="71" + y1="106" + y2="136" + /> + <line + x1="56" + x2="86" + y1="121" + y2="121" + /> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="151" + /> + <text + font-size="14" + x="21" + y="171" + > + S + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="51" + y="151" + /> + <text + font-size="14" + x="71" + y="171" + > + T + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="201" + /> + <text + font-size="14" + x="21" + y="221" + > + Y + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="51" + y="201" + /> + <text + font-size="14" + x="71" + y="221" + > + Z + </text> + </g> + </g> + </g> + <g + class="gate" + > + <g> + <g> + <rect + class="gate-unitary" + height="40" + width="40" + x="1" + y="251" + /> + <text + font-size="14" + x="21" + y="271" + > + ZZ + </text> + </g> + </g> + </g> + </svg> + </div> +</div> +`; + +exports[`Test panel Should return panel with editPanel visible 1`] = ` +<div + class="panel" +> + <div + class="edit-panel" + > + <h2 + class="title" + > + EDIT + </h2> + <div + class="target-input" + > + <label + class="block" + > + Target + </label> + <select> + <option + value="0" + > + q0 + </option> + <option + value="1" + > + q1 + </option> + </select> + </div> + <div + class="controls-input" + > + <label + class="block" + > + Controls + </label> + <label> + <input + type="checkbox" + value="0" + /> + q0 + </label> + <label> + <input + type="checkbox" + value="1" + /> + q1 + </label> + </div> + <div + class="display-input" + > + <label + class="block" + > + Display + </label> + <input + autofocus="true" + type="text" + /> + </div> + </div> +</div> +`; + exports[`Test text Should return gate H without display-args 1`] = ` <div class="display-input" diff --git a/__tests__/panel.test.ts b/__tests__/panel.test.ts index 0d34fb1d..2dafcee7 100644 --- a/__tests__/panel.test.ts +++ b/__tests__/panel.test.ts @@ -3,6 +3,7 @@ import { PanelContext, PanelOptions } from '../src/panel'; import { Action, Dispatch, exportedForTesting } from '../src/panel'; const { + panel, addPanel, editPanel, elem, @@ -332,3 +333,35 @@ describe('Test addPanel', () => { expect(addPanel(emptyDispatch, context, options)).toMatchSnapshot(); }); }); + +describe('Test panel', () => { + const emptyDispatch: Dispatch = (action: Action) => { + action; + }; + test('Should return panel with addPanel visible', () => { + const context: PanelContext = { + addMode: true, + operations: [], + operation: { + gate: 'X', + targets: [{ qId: 0 }], + }, + registerSize: 2, + container: undefined, + }; + expect(panel(emptyDispatch, context)).toMatchSnapshot(); + }); + test('Should return panel with editPanel visible', () => { + const context: PanelContext = { + addMode: false, + operations: [], + operation: { + gate: 'X', + targets: [{ qId: 0 }], + }, + registerSize: 2, + container: undefined, + }; + expect(panel(emptyDispatch, context)).toMatchSnapshot(); + }); +}); From ec1c6b6b82be0ea5f901228244b03a765cc2dec1 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Sun, 31 Jul 2022 12:05:56 -0400 Subject: [PATCH 086/108] Reorganize imports --- __tests__/panel.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/__tests__/panel.test.ts b/__tests__/panel.test.ts index 2dafcee7..f5073f14 100644 --- a/__tests__/panel.test.ts +++ b/__tests__/panel.test.ts @@ -1,6 +1,5 @@ import range from 'lodash/range'; -import { PanelContext, PanelOptions } from '../src/panel'; -import { Action, Dispatch, exportedForTesting } from '../src/panel'; +import { Action, Dispatch, exportedForTesting, PanelContext, PanelOptions } from '../src/panel'; const { panel, From 3fd1fb463fdba7e449af038ccf9af6e24ee85a3f Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 1 Aug 2022 10:24:23 -0400 Subject: [PATCH 087/108] Add license --- __tests__/panel.test.ts | 3 +++ src/panel.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/__tests__/panel.test.ts b/__tests__/panel.test.ts index f5073f14..10256e60 100644 --- a/__tests__/panel.test.ts +++ b/__tests__/panel.test.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + import range from 'lodash/range'; import { Action, Dispatch, exportedForTesting, PanelContext, PanelOptions } from '../src/panel'; diff --git a/src/panel.ts b/src/panel.ts index f2d2e4dd..5e96f652 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + import cloneDeep from 'lodash/cloneDeep'; import range from 'lodash/range'; import { Operation } from './circuit'; From 8224df63a8aa857b61c3f123cf85d51961f5d54c Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 1 Aug 2022 11:24:29 -0400 Subject: [PATCH 088/108] Add documentation --- src/panel.ts | 159 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 150 insertions(+), 9 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index 5e96f652..d22b4f02 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -12,6 +12,9 @@ import { Register } from './register'; import { Sqore } from './sqore'; import { getGateWidth } from './utils'; +/** + * Interface for context + */ interface Context { addMode: boolean; operations: Operation[]; @@ -20,6 +23,9 @@ interface Context { container: HTMLElement | undefined; } +/** + * Object to maintain global state of extensionPanel + */ const context: Context = { addMode: true, operations: [], @@ -28,13 +34,34 @@ const context: Context = { container: undefined, }; +/** + * Interface for options provided through usePanel() + */ interface PanelOptions { displaySize?: number; gateDictionary?: GateDictionary; } +/** + * Interface for dispatch + */ +interface Dispatch { + (action: Action): void; +} + +/** + * Entry point to run extensionPanel + * @param options User-provided object to customize extensionPanel + * @returns Curried function of entry point to run extensionPanel + */ const extensionPanel = (options?: PanelOptions) => + /** + * Curried function of entry point to run extensionPanel + * @param container HTML element for rendering visualization into + * @param sqore Sqore object + * @param useRefresh Function to trigger circuit re-rendering + */ (container: HTMLElement, sqore: Sqore, useRefresh: () => void): void => { const dispatch = (action: Action) => { update(action, context, useRefresh); @@ -53,7 +80,14 @@ const extensionPanel = prevPanelElem == null && container.prepend(panelElem); }; -const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => { +/** + * Function to handle all event listeners + * @param dispatch Function to update state and trigger panel re-rendering + * @param container HTML element for rendering visualization into + * @param sqore Sqore object + */ +const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore): void => { + // Gates in SVG circuit are selectable const elems = container.querySelectorAll<SVGElement>('[data-id]'); elems.forEach((elem) => elem.addEventListener('mousedown', (ev: MouseEvent) => { @@ -65,17 +99,20 @@ const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => }), ); + // Context is updated when mouse is over container container.addEventListener('mouseover', () => { context.registerSize = sqore.circuit.qubits.length; context.operations = sqore.circuit.operations; context.container = container; }); + // addMode triggers const svgElem = container.querySelector('svg[id]'); svgElem?.addEventListener('mousedown', () => { dispatch({ type: 'ADD_MODE' }); }); + // Drag and drop const dropzoneLayer = container.querySelector('.dropzone-layer') as SVGGElement; const dropzoneElems = dropzoneLayer.querySelectorAll<SVGRectElement>('.dropzone'); dropzoneElems.forEach((dropzoneElem) => @@ -92,20 +129,32 @@ const addEvents = (dispatch: Dispatch, container: HTMLElement, sqore: Sqore) => }), ); + // Remove ghost element if drops gate in svgElement svgElem?.addEventListener('mouseup', () => { dispatch({ type: 'REMOVE_GHOST_ELEMENT' }); }); + + // Remove ghost element if drops gate in addPanel container.querySelector('.add-panel')?.addEventListener('mouseup', () => { dispatch({ type: 'REMOVE_GHOST_ELEMENT' }); }); }; +/** + * Interface for action + */ interface Action { type: string; payload?: unknown; } -const update = (action: Action, context: Context, useRefresh: () => void) => { +/** + * Primary function for state management + * @param action Object to have type and payload + * @param context Context object to manage extension state + * @param useRefresh Function to trigger circuit re-rendering + */ +const update = (action: Action, context: Context, useRefresh: () => void): void => { switch (action.type) { case 'ADD_MODE': { context.addMode = true; @@ -209,6 +258,13 @@ const update = (action: Action, context: Context, useRefresh: () => void) => { } }; +/** + * Function to produce panel element + * @param dispatch Function to update state and trigger panel re-rendering + * @param context Context object to manage extension state + * @param options User-provided object to customize extensionPanel + * @returns HTML element for panel + */ const panel = (dispatch: Dispatch, context: Context, options?: PanelOptions): HTMLElement => { const panelElem = elem('div'); panelElem.className = 'panel'; @@ -220,6 +276,13 @@ const panel = (dispatch: Dispatch, context: Context, options?: PanelOptions): HT return panelElem; }; +/** + * Function to produce addPanel element + * @param dispatch Function to update state and trigger panel re-rendering + * @param context Context object to manage extension state + * @param options User-provided object to customize extensionPanel + * @returns HTML element for addPanel + */ const addPanel = (dispatch: Dispatch, context: Context, options?: PanelOptions): HTMLElement => { let gateDictionary = defaultGateDictionary; let objectKeys = Object.keys(gateDictionary); @@ -255,6 +318,12 @@ const addPanel = (dispatch: Dispatch, context: Context, options?: PanelOptions): return addPanelElem; }; +/** + * Function to produce editPanel element + * @param dispatch Function to update state and trigger panel re-rendering + * @param context Context object to manage extension state + * @returns HTML element for editPanel + */ const editPanel = (dispatch: Dispatch, context: Context): HTMLElement => { const { operation, registerSize } = context; const options = range(registerSize).map((i) => ({ value: `${i}`, text: `q${i}` })); @@ -271,6 +340,12 @@ const editPanel = (dispatch: Dispatch, context: Context): HTMLElement => { return editPanelElem; }; +/** + * Factory function to produce HTML element + * @param tag Tag name + * @param className Class name + * @returns HTML element + */ const elem = (tag: string, className?: string): HTMLElement => { const _elem = document.createElement(tag); className && (_elem.className = className); @@ -278,18 +353,32 @@ const elem = (tag: string, className?: string): HTMLElement => { }; /** - * Append all child elements to a parent element + * Append all child elements to a parent HTML element + * @param parentElem Parent HTML element + * @param childElems Array of HTML child elements + * @returns Parent HTML element with all children appended */ const children = (parentElem: HTMLElement, childElems: HTMLElement[]): HTMLElement => { childElems.map((elem) => parentElem.appendChild(elem)); return parentElem; }; +/** + * Append all child elements to a parent SVG element + * @param parentElem Parent SVG element + * @param childElems Array of SVG child elements + * @returns Parent SVG element with all children appended + */ const childrenSvg = (parentElem: SVGElement, childElems: SVGElement[]): SVGElement => { childElems.map((elem) => parentElem.appendChild(elem)); return parentElem; }; +/** + * Function to produce title element + * @param text Text + * @returns Title element + */ const title = (text: string): HTMLElement => { const titleElem = elem('h2'); titleElem.className = 'title'; @@ -297,15 +386,24 @@ const title = (text: string): HTMLElement => { return titleElem; }; +/** + * Interface for option element + */ interface Option { value: string; text: string; } -interface Dispatch { - (action: Action): void; -} - +/** + * Function to produce select element + * @param label Label + * @param className Class name + * @param options Array of Option objects contain value and text + * @param selectedIndex Index of current selected option + * @param dispatch Function to update state and trigger panel re-rendering + * @param operation Optional Operation object + * @returns Select element + */ const select = ( label: string, className: string, @@ -335,6 +433,12 @@ const select = ( return divElem; }; +/** + * Function to produce option element + * @param value Value + * @param text Text + * @returns Option element + */ const option = (value: string, text: string): HTMLOptionElement => { const optionElem = elem('option') as HTMLOptionElement; optionElem.value = value; @@ -342,6 +446,16 @@ const option = (value: string, text: string): HTMLOptionElement => { return optionElem; }; +/** + * Function to produce checkbox elements + * @param label Label + * @param className Class name + * @param options Array of Option objects contain value and text + * @param selectedIndexes Array of indexes of current selected options + * @param dispatch Function to update state and trigger panel re-rendering + * @param operation Optional Operation object + * @returns Parent div containing checkbox elements + */ const checkboxes = ( label: string, className: string, @@ -381,6 +495,12 @@ const checkboxes = ( return divElem; }; +/** + * Function to produce checkbox element + * @param value Value + * @param text Text + * @returns Checkbox element + */ const checkbox = (value: string, text: string): HTMLLabelElement => { const inputElem = elem('input') as HTMLInputElement; inputElem.type = 'checkbox'; @@ -392,6 +512,14 @@ const checkbox = (value: string, text: string): HTMLLabelElement => { return labelElem; }; +/** + * Function to produce input text element + * @param label Label + * @param className Class name + * @param dispatch Function to update state and trigger panel re-rendering + * @param operation Optional Operation object + * @returns Parent div containing input text element + */ const text = (label: string, className: string, dispatch: Dispatch, operation?: Operation): HTMLElement => { const labelElem = elem('label') as HTMLLabelElement; labelElem.className = 'block'; @@ -414,6 +542,13 @@ const text = (label: string, className: string, dispatch: Dispatch, operation?: return divElem; }; +/** + * Wrapper to generate metadata based on _opToMetadata with mock registers and limited support + * @param operation Operation object + * @param x x coordinate at starting point from the left + * @param y y coordinate at starting point from the top + * @returns Metata object + */ const toMetadata = (operation: Operation | undefined, x: number, y: number): Metadata => { const metadata: Metadata = { type: GateType.Invalid, @@ -463,8 +598,8 @@ const toMetadata = (operation: Operation | undefined, x: number, y: number): Met /** * Generate gate element for Add Panel based on type of gate - * @param dispatch - * @param type i.e. 'H' or 'X' + * @param dispatch Function to update state and trigger panel re-rendering + * @param type Type of gate. Example: 'H' or 'X' */ const gate = (dispatch: Dispatch, gateDictionary: GateDictionary, type: string, x: number, y: number): SVGElement => { const operation = gateDictionary[type]; @@ -488,10 +623,16 @@ const gate = (dispatch: Dispatch, gateDictionary: GateDictionary, type: string, return gateElem; }; +/** + * Interface for gate dictionary + */ interface GateDictionary { [index: string]: Operation; } +/** + * Object for default gate dictionary + */ const defaultGateDictionary: GateDictionary = { Entangle: { gate: 'Entangle', From 11646302692c75b692a5482dcf31b4461185f4d5 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 1 Aug 2022 12:09:50 -0400 Subject: [PATCH 089/108] Fix up comments --- src/draggable.ts | 6 +- src/editable.ts | 559 ----------------------------------------------- src/sqore.ts | 20 +- 3 files changed, 7 insertions(+), 578 deletions(-) delete mode 100644 src/editable.ts diff --git a/src/draggable.ts b/src/draggable.ts index 2b678be1..6c05f32c 100644 --- a/src/draggable.ts +++ b/src/draggable.ts @@ -22,9 +22,9 @@ interface Context { /** * Add editable elements and events. * - * @param container HTML element for rendering visualization into. - * @param sqore Sqore object - * @param onCircuitChange User-provided callback function triggered when circuit is changed + * @param Container HTML element for rendering visualization into. + * @param sqore Sqore object + * @param useRefresh Function to trigger circuit re-rendering */ const extensionDraggable = (container: HTMLElement, sqore: Sqore, useRefresh: () => void): void => { const svg = container.querySelector('svg[id]') as SVGElement; diff --git a/src/editable.ts b/src/editable.ts deleted file mode 100644 index 4c16c9cf..00000000 --- a/src/editable.ts +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -import { Circuit, Operation } from './circuit'; -import { box } from './formatters/formatUtils'; -import { Register } from './register'; -import { Sqore } from './sqore'; - -interface Context { - container: HTMLElement; - svg: SVGElement; - operations: Operation[]; - wireData: number[]; - renderFn: () => void; - paddingY: number; - selectedId: string | null; - selectedWire: string | null; -} - -/** - * Add editable elements and events. - * - * @param container HTML element for rendering visualization into. - * @param sqore Sqore object - * @param onCircuitChange User-provided callback function triggered when circuit is changed - */ -const addEditable = (container: HTMLElement, sqore: Sqore, onCircuitChange?: (circuit: Circuit) => void): void => { - const svg = container.querySelector('svg') as SVGElement; - - const context: Context = { - container: container, - svg, - operations: sqore.circuit.operations, - wireData: _wireData(container), - renderFn: _renderFn(container, sqore, onCircuitChange), - paddingY: 20, - selectedId: null, - selectedWire: null, - }; - - _addStyles(container, _wireData(container)); - _addDataWires(container); - svg.appendChild(_dropzoneLayer(context)); - _addEvents(context); -}; - -/** - * Add data-wire to all host elements - */ -const _addDataWires = (container: HTMLElement) => { - const elems = _hostElems(container); - elems.forEach((elem) => { - const { cY } = _center(elem); - // i.e. cY = 40, wireData returns [40, 100, 140, 180] - // dataWire will return 0, which is the index of 40 in wireData - const dataWire = _wireData(container).findIndex((y) => y === cY); - if (dataWire !== -1) { - elem.setAttribute('data-wire', `${dataWire}`); - } else { - const { y, height } = elem.getBBox(); - const wireData = _wireData(container); - const groupDataWire = wireData.findIndex((wireY) => wireY > y && wireY < y + height); - elem.setAttribute('data-wire', `${groupDataWire}`); - } - }); -}; - -/** - * Create a list of wires that element is spanning on - * i.e. Gate 'Foo' spans on wire 0 (y=40), 1 (y=100), and 2 (y=140) - * Function returns [40, 100, 140] - */ -const _wireYs = (elem: SVGGraphicsElement, wireData: number[]): number[] => { - const { y, height } = elem.getBBox(); - return wireData.filter((wireY) => wireY > y && wireY < y + height); -}; - -/** - * Get list of host elements that dropzones can be attached to - */ -const _hostElems = (container: HTMLElement): SVGGraphicsElement[] => { - return Array.from( - container.querySelectorAll<SVGGraphicsElement>( - '[class^="gate-"]:not(.gate-control, .gate-swap), .control-dot, .oplus, .cross', - ), - ); -}; - -/** - * Add custom styles specific to this module - */ -const _addStyles = (container: HTMLElement, wireData: number[]): void => { - const elems = _hostElems(container); - elems.forEach((elem) => { - if (_wireYs(elem, wireData).length < 2) elem.style.cursor = 'grab'; - }); -}; - -/** - * Generate an array of wire prefixes from wire data - */ -const _wirePrefixes = (wireData: number[]): { index: number; wireY: number; prefixX: number }[] => - wireData.map((wireY, index) => ({ index, wireY, prefixX: 40 })); - -/** - * Find center point of element - */ -const _center = (elem: SVGGraphicsElement): { cX: number; cY: number } => { - const { x, y, width, height } = elem.getBBox(); - return { cX: x + width / 2, cY: y + height / 2 }; -}; - -/** - * Create dropzone layer with all dropzones popullated - */ -const _dropzoneLayer = (context: Context) => { - const dropzoneLayer = document.createElementNS('http://www.w3.org/2000/svg', 'g'); - dropzoneLayer.classList.add('dropzone-layer'); - - const { container, svg, wireData, operations, paddingY } = context; - const elems = _hostElems(container); - - const wirePrefixes = _wirePrefixes(wireData); - - // Sort host elements by its x property - const sortedElems = Array.from(elems).sort((first, second) => { - const { x: x1 } = first.getBBox(); - const { x: x2 } = second.getBBox(); - return x1 - x2; - }); - - // Add dropzones for each host elements - sortedElems.map((elem) => { - const { cX, cY } = _center(elem); - const wirePrefix = wirePrefixes.find((item) => item.wireY === cY); - - // Check to prevent group gates creating dropzones between wires - if (wirePrefix) { - const prefixX = wirePrefix.prefixX; - const elemDropzone = box(prefixX, cY - paddingY, cX - prefixX, paddingY * 2, 'dropzone'); - elemDropzone.setAttribute('data-dropzone-id', _equivDataId(elem) || ''); - elemDropzone.setAttribute('data-dropzone-wire', `${wirePrefix.index}`); - - wirePrefix.prefixX = cX; - - dropzoneLayer.appendChild(elemDropzone); - } else { - // Let group gates creating dropzones for each wire - const { x } = elem.getBBox(); - const wireYs = _wireYs(elem, wireData); - - wireYs.map((wireY) => { - const wirePrefix = wirePrefixes.find((item) => item.wireY === wireY); - if (wirePrefix) { - const prefixX = wirePrefix.prefixX; - const elemDropzone = box(prefixX, wireY - paddingY, x - prefixX, paddingY * 2, 'dropzone'); - elemDropzone.setAttribute('data-dropzone-id', _equivDataId(elem) || ''); - elemDropzone.setAttribute('data-dropzone-wire', `${wirePrefix.index}`); - - wirePrefix.prefixX = x; - - dropzoneLayer.appendChild(elemDropzone); - } - }); - } - }); - - // Add remaining dropzones to fit max-width of the circuit - wirePrefixes.map(({ wireY, prefixX }) => { - const maxWidth = Number(svg.getAttribute('width')); - const elemDropzone = box(prefixX, wireY - paddingY, maxWidth - prefixX, paddingY * 2, 'dropzone'); - elemDropzone.setAttribute('data-dropzone-id', `${operations.length}`); - const index = wireData.findIndex((item) => item === wireY); - elemDropzone.setAttribute('data-dropzone-wire', `${index}`); - dropzoneLayer.appendChild(elemDropzone); - }); - - return dropzoneLayer; -}; - -/** - * Generate an array of y values based on circuit wires - */ -const _wireData = (container: HTMLElement): number[] => { - // elems include qubit wires and lines of measure gates - const elems = container.querySelectorAll<SVGGElement>('svg > g:nth-child(3) > g'); - // filter out <g> elements having more than 2 elements because - // qubit wires contain only 2 elements: <line> and <text> - // lines of measure gates contain 4 <line> elements - const wireElems = Array.from(elems).filter((elem) => elem.childElementCount < 3); - const wireData = wireElems.map((wireElem) => { - const lineElem = wireElem.children[0] as SVGLineElement; - return Number(lineElem.getAttribute('y1')); - }); - return wireData; -}; - -/** - * Find equivalent gate element of host element - */ -const _equivGateElem = (elem: SVGElement): SVGElement | null => { - return elem.closest<SVGElement>('[data-id]'); -}; - -/** - * Find data-id of host element - */ -const _equivDataId = (elem: SVGElement) => { - const gateElem = _equivGateElem(elem); - return gateElem != null ? gateElem.getAttribute('data-id') : null; -}; - -/** - * Disable contextmenu default behaviors - */ -const _addContextMenuEvents = (container: HTMLElement) => { - container.addEventListener('contextmenu', (ev: MouseEvent) => { - ev.preventDefault(); - }); -}; - -/** - * Add events specifically for dropzoneLayer - */ -const _addDropzoneLayerEvents = (container: HTMLElement, dropzoneLayer: SVGGElement) => { - container.addEventListener('mouseup', () => (dropzoneLayer.style.display = 'none')); -}; - -/** - * Add events for document - */ -const _addDocumentEvents = (context: Context) => { - const { container } = context; - - document.addEventListener('keydown', (ev: KeyboardEvent) => { - if (ev.ctrlKey && context.selectedId) { - container.classList.remove('moving'); - container.classList.add('copying'); - } - }); - - document.addEventListener('keyup', () => { - if (context.selectedId) { - container.classList.remove('copying'); - container.classList.add('moving'); - } - }); - - document.addEventListener('mouseup', () => { - container.classList.remove('moving', 'copying'); - context.selectedId = null; - context.selectedWire = null; - }); -}; - -/** - * Add all events - */ -const _addEvents = (context: Context) => { - const { container, operations, renderFn } = context; - const dropzoneLayer = container.querySelector('.dropzone-layer') as SVGGElement; - - _addContextMenuEvents(container); - _addDropzoneLayerEvents(container, dropzoneLayer); - _addDocumentEvents(context); - - // Host element events - const elems = _hostElems(container); - elems.forEach((elem) => { - elem.addEventListener('mousedown', () => { - context.selectedWire = elem.getAttribute('data-wire'); - container.classList.add('moving'); - }); - - const gateElem = _equivGateElem(elem); - gateElem?.addEventListener('mousedown', (ev: MouseEvent) => { - ev.stopPropagation(); - context.selectedId = _equivDataId(elem); - dropzoneLayer.style.display = 'block'; - }); - }); - - // Dropzone element events - const dropzoneElems = dropzoneLayer.querySelectorAll<SVGRectElement>('.dropzone'); - dropzoneElems.forEach((dropzoneElem) => { - dropzoneElem.addEventListener('mouseup', (ev: MouseEvent) => { - const targetId = dropzoneElem.getAttribute('data-dropzone-id'); - const targetWire = dropzoneElem.getAttribute('data-dropzone-wire'); - if ( - targetId == null || // - targetWire == null || - context.selectedId == null || - context.selectedWire == null - ) - return; - - const newSourceOperation = ev.ctrlKey - ? _copyX(context.selectedId, targetId, operations) - : _moveX(context.selectedId, targetId, operations); - - if (newSourceOperation != null) { - _moveY(context.selectedWire, targetWire, newSourceOperation, context.wireData.length); - const parentOperation = _equivParentOperation(context.selectedId, operations); - if (parentOperation) { - parentOperation.targets = _targets(parentOperation); - } - } - - renderFn(); - }); - }); -}; - -const _equivParentOperation = (dataId: string | null, operations: Operation[]): Operation | null => { - if (!dataId) return null; - - const indexes = _indexes(dataId); - indexes.pop(); - const lastIndex = indexes.pop(); - - if (lastIndex == null) return null; - - let parentOperation = operations; - for (const index of indexes) { - parentOperation = parentOperation[index].children || parentOperation; - } - return parentOperation[lastIndex]; -}; - -/** - * Find equivalent parent array of an operation - */ -const _equivParentArray = (dataId: string | null, operations: Operation[]): Operation[] | null => { - if (!dataId) return null; - - const indexes = _indexes(dataId); - indexes.pop(); - - let parentArray = operations; - for (const index of indexes) { - parentArray = parentArray[index].children || parentArray; - } - return parentArray; -}; - -/** - * Find an equivalent operation of an element based on its data-id - */ -const _equivOperation = (dataId: string | null, operations: Operation[]): Operation | null => { - if (!dataId) return null; - - const index = _lastIndex(dataId); - const operationParent = _equivParentArray(dataId, operations); - - if ( - operationParent == null || // - index == null - ) - return null; - - return operationParent[index]; -}; - -/** - * Move an operation horizontally - */ -const _moveX = (sourceId: string, targetId: string, operations: Operation[]): Operation | null => { - if (sourceId === targetId) return _equivOperation(sourceId, operations); - const sourceOperation = _equivOperation(sourceId, operations); - const sourceOperationParent = _equivParentArray(sourceId, operations); - const targetOperationParent = _equivParentArray(targetId, operations); - const targetLastIndex = _lastIndex(targetId); - - if ( - targetOperationParent == null || // - targetLastIndex == null || - sourceOperation == null || - sourceOperationParent == null - ) - return null; - - // Insert sourceOperation to target last index - const newSourceOperation: Operation = JSON.parse(JSON.stringify(sourceOperation)); - targetOperationParent.splice(targetLastIndex, 0, newSourceOperation); - - // Delete sourceOperation - sourceOperation.gate = 'removed'; - const indexToRemove = sourceOperationParent.findIndex((operation) => operation.gate === 'removed'); - sourceOperationParent.splice(indexToRemove, 1); - - return newSourceOperation; -}; - -/** - * Copy an operation horizontally - */ -const _copyX = (sourceId: string, targetId: string, operations: Operation[]): Operation | null => { - const sourceOperation = _equivOperation(sourceId, operations); - const sourceOperationParent = _equivParentArray(sourceId, operations); - const targetOperationParent = _equivParentArray(targetId, operations); - const targetLastIndex = _lastIndex(targetId); - - if ( - targetOperationParent == null || // - targetLastIndex == null || - sourceOperation == null || - sourceOperationParent == null - ) - return null; - - // Insert sourceOperation to target last index - const newSourceOperation: Operation = JSON.parse(JSON.stringify(sourceOperation)); - targetOperationParent.splice(targetLastIndex, 0, newSourceOperation); - - return newSourceOperation; -}; - -/** - * Move an operation vertically by changing its controls and targets - */ -const _moveY = (sourceWire: string, targetWire: string, operation: Operation, totalWires: number): Operation => { - if (operation.gate !== 'measure') { - const offset = parseInt(targetWire) - parseInt(sourceWire); - _offsetRecursively(operation, offset, totalWires); - } - return operation; -}; - -/** - * Recursively change object controls and targets - */ -const _offsetRecursively = (operation: Operation, wireOffset: number, totalWires: number): Operation => { - // Offset all targets by offsetY value - if (operation.targets != null) { - operation.targets.forEach((target) => { - target.qId = _circularMod(target.qId, wireOffset, totalWires); - if (target.cId) target.cId = _circularMod(target.cId, wireOffset, totalWires); - }); - } - - // Offset all controls by offsetY value - if (operation.controls != null) { - operation.controls.forEach((control) => { - control.qId = _circularMod(control.qId, wireOffset, totalWires); - if (control.cId) control.cId = _circularMod(control.qId, wireOffset, totalWires); - }); - } - - // Offset recursively through all children - if (operation.children != null) { - operation.children.forEach((child) => _offsetRecursively(child, wireOffset, totalWires)); - } - - return operation; -}; - -/** - * Find targets of an operation by recursively walkthrough all of its children controls and targets - * i.e. Gate Foo contains gate H and gate RX. - * qIds of Gate H is 1 - * qIds of Gate RX is 1, 2 - * This should return [{qId: 1}, {qId: 2}] - */ -const _targets = (operation: Operation): Register[] | [] => { - const _recurse = (operation: Operation) => { - registers.push(...operation.targets); - if (operation.controls) { - registers.push(...operation.controls); - // If there is more children, keep adding more to registers - if (operation.children) { - for (const child of operation.children) { - _recurse(child); - } - } - } - }; - - const registers: Register[] = []; - if (operation.children == null) return []; - - // Recursively walkthrough all children to populate registers - for (const child of operation.children) { - _recurse(child); - } - - // Extract qIds from array of object - // i.e. [{qId: 0}, {qId: 1}, {qId: 1}] -> [0, 1, 1] - const qIds = registers.map((register) => register.qId); - const uniqueQIds = Array.from(new Set(qIds)); - - // Transform array of numbers into array of qId object - // i.e. [0, 1] -> [{qId: 0}, {qId: 1}] - return uniqueQIds.map((qId) => ({ - qId, - })); -}; - -/** - * This modulo function always returns positive value based on total - * i.e: value=0, offset=-1, total=4 returns 3 instead of -1 - */ -const _circularMod = (value: number, offset: number, total: number): number => { - return (((value + offset) % total) + total) % total; -}; - -/** - * Split data-id into an array of indexes - */ -const _indexes = (dataId: string): number[] => - dataId !== '' // - ? dataId.split('-').map((segment) => parseInt(segment)) - : []; - -/** - * Get the last index of data-id - * i.e: data-id = "0-1-2", _lastIndex will return 2 - */ -const _lastIndex = (dataId: string): number | undefined => { - return _indexes(dataId).pop(); -}; - -/** - * Return a render function with the onCircuitChange callback attached to it - */ -const _renderFn = ( - container: HTMLElement, - sqore: Sqore, - onCircuitChange?: (circuit: Circuit) => void, -): (() => void) => { - return () => { - sqore.draw(container, 0, true, onCircuitChange); - if (onCircuitChange) onCircuitChange(sqore.circuit); - }; -}; - -/** - * Object exported for unit testing - */ -const exportedForTesting = { - _wireYs, - _hostElems, - _wirePrefixes, - _center, - _wireData, - _equivGateElem, - _equivOperation, - _equivParentOperation, - _equivParentArray, - _moveX, - _copyX, - _moveY, - _offsetRecursively, - _targets, - _circularMod, - _indexes, - _lastIndex, -}; - -export { addEditable, exportedForTesting }; diff --git a/src/sqore.ts b/src/sqore.ts index caa7c9f7..f188d1a2 100644 --- a/src/sqore.ts +++ b/src/sqore.ts @@ -4,11 +4,11 @@ import { Circuit, ConditionalRender, Operation } from './circuit'; import { svgNS } from './constants'; import { extensionDraggable } from './draggable'; -import { extensionPanel, PanelOptions } from './panel'; import { formatGates } from './formatters/gateFormatter'; import { formatInputs } from './formatters/inputFormatter'; import { formatRegisters } from './formatters/registerFormatter'; import { GateType, Metadata } from './metadata'; +import { extensionPanel, PanelOptions } from './panel'; import { processOperations } from './process'; import { style, StyleConfig, STYLES } from './styles'; import { createUUID } from './utils'; @@ -249,18 +249,11 @@ export class Sqore { * * @param container HTML element containing visualized circuit. * @param circuit Circuit to be visualized. - * @param isEditable Optional value enabling/disabling editable feature - * @param onCircuitChange Optional function to trigger when changing elements in circuit * */ - private addGateClickHandlers( - container: HTMLElement, - circuit: Circuit, - isEditable?: boolean, - onCircuitChange?: (circuit: Circuit) => void, - ): void { + private addGateClickHandlers(container: HTMLElement, circuit: Circuit): void { this.addClassicalControlHandlers(container); - this.addZoomHandlers(container, circuit, isEditable, onCircuitChange); + this.addZoomHandlers(container, circuit); } /** @@ -320,12 +313,7 @@ export class Sqore { * @param onCircuitChange Optional function to trigger when changing elements in circuit * */ - private addZoomHandlers( - container: HTMLElement, - circuit: Circuit, - isEditable?: boolean, - onCircuitChange?: (circuit: Circuit) => void, - ): void { + private addZoomHandlers(container: HTMLElement, circuit: Circuit): void { container.querySelectorAll('.gate .gate-control').forEach((ctrl) => { // Zoom in on clicked gate ctrl.addEventListener('click', (ev: Event) => { From d82dedabc1257df0113fa54ba1202f3688d5325c Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 1 Aug 2022 12:11:45 -0400 Subject: [PATCH 090/108] Remove old tests --- __tests__/editable.test.ts | 817 ------------------------------------- 1 file changed, 817 deletions(-) delete mode 100644 __tests__/editable.test.ts diff --git a/__tests__/editable.test.ts b/__tests__/editable.test.ts deleted file mode 100644 index 0fde4705..00000000 --- a/__tests__/editable.test.ts +++ /dev/null @@ -1,817 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -import { exportedForTesting } from '../src/editable'; -import { Circuit, draw, Operation, STYLES } from '../src/index'; - -const { - _wireYs, - _hostElems, - _wirePrefixes, - _center, - _wireData, - _equivGateElem, - _equivOperation, - _equivParentOperation, - _equivParentArray, - _moveX, - _copyX, - _moveY, - _offsetRecursively, - _targets, - _circularMod, - _indexes, - _lastIndex, -} = exportedForTesting; - -describe('Test _hostElems', () => { - let container: HTMLElement; - beforeAll(() => { - container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - draw(circuit, container, STYLES['default']); - }); - test('should return 4 elements', () => { - expect(_hostElems(container)).toMatchSnapshot(); - expect(_hostElems(container)).toHaveLength(4); - }); -}); - -describe('Test _wireYs', () => { - test('should return [40,100]', () => { - Object.defineProperty(window.SVGElement.prototype, 'getBBox', { - writable: true, - value: () => ({ - x: 0, - y: 20, - width: 0, - height: 120, - }), - }); - const elem = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); - expect(_wireYs(elem, [40, 100, 140])).toStrictEqual([40, 100]); - }); -}); - -describe('Test _wirePrefixes', () => { - test('2 wires', () => { - expect(_wirePrefixes([40, 100])).toStrictEqual([ - { index: 0, prefixX: 40, wireY: 40 }, - { index: 1, prefixX: 40, wireY: 100 }, - ]); - }); - test('3 wires', () => { - expect(_wirePrefixes([40, 100, 140])).toStrictEqual([ - { index: 0, prefixX: 40, wireY: 40 }, - { index: 1, prefixX: 40, wireY: 100 }, - { index: 2, prefixX: 40, wireY: 140 }, - ]); - }); -}); - -describe('Test _center', () => { - test('should return {25,50}', () => { - Object.defineProperty(window.SVGElement.prototype, 'getBBox', { - writable: true, - value: () => ({ - x: 0, - y: 0, - width: 50, - height: 100, - }), - }); - const elem = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); - expect(_center(elem)).toStrictEqual({ cX: 25, cY: 50 }); - }); - test('should return {105,210}', () => { - Object.defineProperty(window.SVGElement.prototype, 'getBBox', { - writable: true, - value: () => ({ - x: 100, - y: 200, - width: 10, - height: 20, - }), - }); - const elem = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); - expect(_center(elem)).toStrictEqual({ cX: 105, cY: 210 }); - }); -}); - -describe('Test _wireData', () => { - test('2 wires should return [40,100]', () => { - const container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - draw(circuit, container, STYLES['default']); - expect(_wireData(container)).toStrictEqual([40, 100]); - }); - test('3 wires should return [40,100, 180]', () => { - const container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }, { id: 2 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 2 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - draw(circuit, container, STYLES['default']); - expect(_wireData(container)).toStrictEqual([40, 100, 180]); - }); -}); - -describe('Test _equivGateElem', () => { - let container: HTMLElement; - beforeAll(() => { - container = document.createElement('div'); - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - draw(circuit, container, STYLES['default']); - }); - test('should return gate H', () => { - const elem = container.querySelector('[class^="gate-"]') as SVGElement; - expect(_equivGateElem(elem)).toMatchSnapshot(); - }); -}); - -describe('Test _equivOperation', () => { - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - test('should return H gate', () => { - expect(_equivOperation('0', circuit.operations)).toMatchSnapshot(); - }); - test('should return X gate', () => { - expect(_equivOperation('1', circuit.operations)).toMatchSnapshot(); - }); -}); - -describe('Test _equivParentOperation', () => { - test('should return Foo', () => { - const circuit = { - qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], - operations: [ - { - gate: 'Foo', - conditionalRender: 3, - targets: [{ qId: 0 }, { qId: 1 }], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - }, - { - gate: 'RX', - displayArgs: '(0.25)', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 0 }], - }, - ], - }, - { - gate: 'X', - targets: [{ qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 2 }, { qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }, { qId: 3 }], - targets: [{ qId: 1 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }, { qId: 3 }], - targets: [{ qId: 2 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'measure', - isMeasurement: true, - controls: [{ qId: 0 }], - targets: [{ type: 1, qId: 0, cId: 0 }], - }, - { - gate: 'ApplyIfElseR', - isConditional: true, - controls: [{ type: 1, qId: 0, cId: 0 }], - targets: [], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - conditionalRender: 2, - }, - { - gate: 'Foo', - targets: [{ qId: 3 }], - conditionalRender: 2, - }, - ], - }, - { - gate: 'SWAP', - targets: [{ qId: 0 }, { qId: 2 }], - children: [ - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - ], - }, - { - gate: 'ZZ', - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'ZZ', - targets: [{ qId: 0 }, { qId: 1 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }, { qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - ], - }; - expect(_equivParentOperation('0-1', circuit.operations)).toMatchSnapshot(); - }); -}); - -describe('Test _equivParentArray', () => { - test('should return Foo', () => { - const circuit = { - qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], - operations: [ - { - gate: 'Foo', - conditionalRender: 3, - targets: [{ qId: 0 }, { qId: 1 }], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - }, - { - gate: 'RX', - displayArgs: '(0.25)', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 0 }], - }, - ], - }, - { - gate: 'X', - targets: [{ qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 2 }, { qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }, { qId: 3 }], - targets: [{ qId: 1 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }, { qId: 3 }], - targets: [{ qId: 2 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'measure', - isMeasurement: true, - controls: [{ qId: 0 }], - targets: [{ type: 1, qId: 0, cId: 0 }], - }, - { - gate: 'ApplyIfElseR', - isConditional: true, - controls: [{ type: 1, qId: 0, cId: 0 }], - targets: [], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - conditionalRender: 2, - }, - { - gate: 'Foo', - targets: [{ qId: 3 }], - conditionalRender: 2, - }, - ], - }, - { - gate: 'SWAP', - targets: [{ qId: 0 }, { qId: 2 }], - children: [ - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - ], - }, - { - gate: 'ZZ', - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'ZZ', - targets: [{ qId: 0 }, { qId: 1 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }, { qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - ], - }; - expect(_equivParentArray('0-1', circuit.operations)).toMatchSnapshot(); - }); - test('should return all operations', () => { - const circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - expect(_equivParentArray('0', circuit.operations)).toMatchSnapshot(); - }); -}); - -describe('Test _moveX', () => { - let circuit: Circuit; - beforeEach(() => { - circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - }); - test('move elem from index 0 to index 1', () => { - _moveX('0', '2', circuit.operations); - expect(circuit.operations).toMatchSnapshot(); - }); - test('move elem from index 0 to last', () => { - _moveX('0', '3', circuit.operations); - expect(circuit.operations).toMatchSnapshot(); - }); -}); - -describe('Test _copyX', () => { - let circuit: Circuit; - beforeEach(() => { - circuit = { - qubits: [{ id: 0 }, { id: 1, numChildren: 1 }], - operations: [ - { - gate: 'H', - targets: [{ qId: 0 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - }, - { - gate: 'Measure', - isMeasurement: true, - controls: [{ qId: 1 }], - targets: [{ type: 1, qId: 1, cId: 0 }], - }, - ], - }; - }); - test('copy elem from index 0 to index 1', () => { - _copyX('0', '2', circuit.operations); - expect(circuit.operations).toMatchSnapshot(); - }); - test('copy elem from index 0 to last', () => { - _copyX('0', '3', circuit.operations); - expect(circuit.operations).toMatchSnapshot(); - }); -}); - -describe('Test _moveY', () => { - let operation: Operation; - beforeEach(() => { - operation = { - gate: 'ZZ', - targets: [{ qId: 1 }, { qId: 3 }], - }; - }); - test('offset by 1', () => { - _moveY('1', '2', operation, 4); - expect(operation).toStrictEqual({ - gate: 'ZZ', - targets: [{ qId: 2 }, { qId: 0 }], - }); - }); - test('offset by -3', () => { - _moveY('3', '0', operation, 4); - expect(operation).toStrictEqual({ - gate: 'ZZ', - targets: [{ qId: 2 }, { qId: 0 }], - }); - }); -}); - -describe('Test _offsetRecursively', () => { - let operation: Operation; - beforeEach(() => { - operation = { - gate: 'ZZ', - targets: [{ qId: 1 }, { qId: 3 }], - }; - }); - test('offset by 1', () => { - _offsetRecursively(operation, 1, 4); - expect(operation).toStrictEqual({ - gate: 'ZZ', - targets: [{ qId: 2 }, { qId: 0 }], - }); - }); - test('offset by 2', () => { - _offsetRecursively(operation, 2, 4); - expect(operation).toStrictEqual({ - gate: 'ZZ', - targets: [{ qId: 3 }, { qId: 1 }], - }); - }); -}); - -describe('Test _targets', () => { - let circuit: Circuit; - beforeEach(() => { - circuit = { - qubits: [{ id: 0, numChildren: 1 }, { id: 1 }, { id: 2 }, { id: 3 }], - operations: [ - { - gate: 'Foo', - conditionalRender: 3, - targets: [{ qId: 0 }, { qId: 1 }], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - }, - { - gate: 'RX', - displayArgs: '(0.25)', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 0 }], - }, - ], - }, - { - gate: 'X', - targets: [{ qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }], - targets: [{ qId: 2 }, { qId: 3 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }, { qId: 3 }], - targets: [{ qId: 1 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 1 }, { qId: 3 }], - targets: [{ qId: 2 }], - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'measure', - isMeasurement: true, - controls: [{ qId: 0 }], - targets: [{ type: 1, qId: 0, cId: 0 }], - }, - { - gate: 'ApplyIfElseR', - isConditional: true, - controls: [{ type: 1, qId: 0, cId: 0 }], - targets: [], - children: [ - { - gate: 'H', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - targets: [{ qId: 1 }], - conditionalRender: 1, - }, - { - gate: 'X', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }], - conditionalRender: 2, - }, - { - gate: 'Foo', - targets: [{ qId: 3 }], - conditionalRender: 2, - }, - ], - }, - { - gate: 'SWAP', - targets: [{ qId: 0 }, { qId: 2 }], - children: [ - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 2 }], targets: [{ qId: 0 }] }, - { gate: 'X', isControlled: true, controls: [{ qId: 0 }], targets: [{ qId: 2 }] }, - ], - }, - { - gate: 'ZZ', - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'ZZ', - targets: [{ qId: 0 }, { qId: 1 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - { - gate: 'XX', - isControlled: true, - controls: [{ qId: 0 }, { qId: 2 }], - targets: [{ qId: 1 }, { qId: 3 }], - }, - ], - }; - }); - test('move RX down 1, should return [{qId:1}, {qId:2}]', () => { - const parentOperation = circuit.operations[0]; - const parentArray = parentOperation.children; - if (parentArray) { - const operation = parentArray[1]; - _moveY('0', '1', operation, 4); - } - expect(_targets(parentOperation)).toStrictEqual([{ qId: 1 }, { qId: 2 }]); - }); - test('move RX down 2, should return [{qId:1}, {qId:2}, {qId:3}]', () => { - const parentOperation = circuit.operations[0]; - const parentArray = parentOperation.children; - if (parentArray) { - const operation = parentArray[1]; - _moveY('0', '2', operation, 4); - } - expect(_targets(parentOperation)).toStrictEqual([{ qId: 1 }, { qId: 2 }, { qId: 3 }]); - }); -}); - -describe('Test _circularMod', () => { - test('should return 2', () => { - expect(_circularMod(5, 1, 4)).toEqual(2); - }); - test('should return 1', () => { - expect(_circularMod(100, 1, 2)).toEqual(1); - }); - test('should return 3', () => { - expect(_circularMod(3, 0, 4)).toEqual(3); - }); -}); - -describe('Test _lastIndex', () => { - test('"" should return undefined', () => { - expect(_lastIndex('')).toBeUndefined(); - }); - test('"0-0-1" should return 1', () => { - expect(_lastIndex('0-0-1')).toEqual(1); - }); - test('"1-0-5" should return [1,0,5]', () => { - expect(_lastIndex('1-0-5')).toEqual(5); - }); -}); - -describe('Test _indexes', () => { - test('"" should return []', () => { - expect(_indexes('')).toStrictEqual([]); - }); - test('"0-0-1" should return [0,0,1]', () => { - expect(_indexes('0-0-1')).toStrictEqual([0, 0, 1]); - }); - test('"1-0-1" should return [1,0,1]', () => { - expect(_indexes('1-0-1')).toStrictEqual([1, 0, 1]); - }); -}); From b79b88b2a3acbfe07c7a35db29b5ca5ef0a7093b Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Mon, 1 Aug 2022 12:14:15 -0400 Subject: [PATCH 091/108] Remove old snapshots --- __tests__/__snapshots__/editable.test.ts.snap | 402 ------------------ 1 file changed, 402 deletions(-) delete mode 100644 __tests__/__snapshots__/editable.test.ts.snap diff --git a/__tests__/__snapshots__/editable.test.ts.snap b/__tests__/__snapshots__/editable.test.ts.snap deleted file mode 100644 index c29c1bad..00000000 --- a/__tests__/__snapshots__/editable.test.ts.snap +++ /dev/null @@ -1,402 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Test _copyX copy elem from index 0 to index 1 1`] = ` -Array [ - Object { - "gate": "H", - "targets": Array [ - Object { - "qId": 0, - }, - ], - }, - Object { - "controls": Array [ - Object { - "qId": 0, - }, - ], - "gate": "X", - "isControlled": true, - "targets": Array [ - Object { - "qId": 1, - }, - ], - }, - Object { - "gate": "H", - "targets": Array [ - Object { - "qId": 0, - }, - ], - }, - Object { - "controls": Array [ - Object { - "qId": 1, - }, - ], - "gate": "Measure", - "isMeasurement": true, - "targets": Array [ - Object { - "cId": 0, - "qId": 1, - "type": 1, - }, - ], - }, -] -`; - -exports[`Test _copyX copy elem from index 0 to last 1`] = ` -Array [ - Object { - "gate": "H", - "targets": Array [ - Object { - "qId": 0, - }, - ], - }, - Object { - "controls": Array [ - Object { - "qId": 0, - }, - ], - "gate": "X", - "isControlled": true, - "targets": Array [ - Object { - "qId": 1, - }, - ], - }, - Object { - "controls": Array [ - Object { - "qId": 1, - }, - ], - "gate": "Measure", - "isMeasurement": true, - "targets": Array [ - Object { - "cId": 0, - "qId": 1, - "type": 1, - }, - ], - }, - Object { - "gate": "H", - "targets": Array [ - Object { - "qId": 0, - }, - ], - }, -] -`; - -exports[`Test _equivGateElem should return gate H 1`] = ` -<g - class="gate" - data-id="0" - data-zoom-in="false" - data-zoom-out="false" -> - <g> - <g> - <rect - class="gate-unitary" - height="40" - width="40" - x="80" - y="20" - /> - <text - font-size="14" - x="100" - y="40" - > - H - </text> - </g> - </g> -</g> -`; - -exports[`Test _equivOperation should return H gate 1`] = ` -Object { - "gate": "H", - "targets": Array [ - Object { - "qId": 0, - }, - ], -} -`; - -exports[`Test _equivOperation should return X gate 1`] = ` -Object { - "controls": Array [ - Object { - "qId": 0, - }, - ], - "gate": "X", - "isControlled": true, - "targets": Array [ - Object { - "qId": 1, - }, - ], -} -`; - -exports[`Test _equivParentArray should return Foo 1`] = ` -Array [ - Object { - "gate": "H", - "targets": Array [ - Object { - "qId": 1, - }, - ], - }, - Object { - "controls": Array [ - Object { - "qId": 1, - }, - ], - "displayArgs": "(0.25)", - "gate": "RX", - "isControlled": true, - "targets": Array [ - Object { - "qId": 0, - }, - ], - }, -] -`; - -exports[`Test _equivParentArray should return all operations 1`] = ` -Array [ - Object { - "gate": "H", - "targets": Array [ - Object { - "qId": 0, - }, - ], - }, - Object { - "controls": Array [ - Object { - "qId": 0, - }, - ], - "gate": "X", - "isControlled": true, - "targets": Array [ - Object { - "qId": 1, - }, - ], - }, - Object { - "controls": Array [ - Object { - "qId": 1, - }, - ], - "gate": "Measure", - "isMeasurement": true, - "targets": Array [ - Object { - "cId": 0, - "qId": 1, - "type": 1, - }, - ], - }, -] -`; - -exports[`Test _equivParentOperation should return Foo 1`] = ` -Object { - "children": Array [ - Object { - "gate": "H", - "targets": Array [ - Object { - "qId": 1, - }, - ], - }, - Object { - "controls": Array [ - Object { - "qId": 1, - }, - ], - "displayArgs": "(0.25)", - "gate": "RX", - "isControlled": true, - "targets": Array [ - Object { - "qId": 0, - }, - ], - }, - ], - "conditionalRender": 3, - "gate": "Foo", - "targets": Array [ - Object { - "qId": 0, - }, - Object { - "qId": 1, - }, - ], -} -`; - -exports[`Test _hostElems should return 4 elements 1`] = ` -Array [ - <rect - class="gate-unitary" - height="40" - width="40" - x="80" - y="20" - />, - <circle - class="control-dot" - cx="160" - cy="40" - r="5" - />, - <g - class="oplus" - > - <circle - cx="160" - cy="100" - r="15" - /> - <line - x1="160" - x2="160" - y1="85" - y2="115" - /> - <line - x1="145" - x2="175" - y1="100" - y2="100" - /> - </g>, - <rect - class="gate-measure" - height="40" - width="40" - x="200" - y="80" - />, -] -`; - -exports[`Test _moveX move elem from index 0 to index 1 1`] = ` -Array [ - Object { - "controls": Array [ - Object { - "qId": 0, - }, - ], - "gate": "X", - "isControlled": true, - "targets": Array [ - Object { - "qId": 1, - }, - ], - }, - Object { - "gate": "H", - "targets": Array [ - Object { - "qId": 0, - }, - ], - }, - Object { - "controls": Array [ - Object { - "qId": 1, - }, - ], - "gate": "Measure", - "isMeasurement": true, - "targets": Array [ - Object { - "cId": 0, - "qId": 1, - "type": 1, - }, - ], - }, -] -`; - -exports[`Test _moveX move elem from index 0 to last 1`] = ` -Array [ - Object { - "controls": Array [ - Object { - "qId": 0, - }, - ], - "gate": "X", - "isControlled": true, - "targets": Array [ - Object { - "qId": 1, - }, - ], - }, - Object { - "controls": Array [ - Object { - "qId": 1, - }, - ], - "gate": "Measure", - "isMeasurement": true, - "targets": Array [ - Object { - "cId": 0, - "qId": 1, - "type": 1, - }, - ], - }, - Object { - "gate": "H", - "targets": Array [ - Object { - "qId": 0, - }, - ], - }, -] -`; From 5e7ec222cb4c95912a784f92d383d6beb1dcdd9f Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 2 Aug 2022 17:06:30 -0400 Subject: [PATCH 092/108] Increase panelWidth from 144 to 150 --- src/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants.ts b/src/constants.ts index 71123456..d98bbb66 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -40,7 +40,7 @@ export const regLineStart = 40; // Panel /** Panel width */ -export const panelWidth = 144; +export const panelWidth = 150; /** Gap between gates in Add Panel */ export const horizontalGap = 10; export const verticalGap = 10; From e36cb96f29d8107d75414e6887918caf4f737c53 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Tue, 2 Aug 2022 21:22:29 -0400 Subject: [PATCH 093/108] Update tests --- __tests__/__snapshots__/panel.test.ts.snap | 100 ++++++++++----------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/__tests__/__snapshots__/panel.test.ts.snap b/__tests__/__snapshots__/panel.test.ts.snap index 3892b303..d6848421 100644 --- a/__tests__/__snapshots__/panel.test.ts.snap +++ b/__tests__/__snapshots__/panel.test.ts.snap @@ -109,13 +109,13 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="1" - y="101" + x="101" + y="51" /> <text font-size="14" - x="21" - y="121" + x="121" + y="71" > H </text> @@ -129,19 +129,19 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="oplus" > <circle - cx="71" + cx="21" cy="121" r="15" /> <line - x1="71" - x2="71" + x1="21" + x2="21" y1="106" y2="136" /> <line - x1="56" - x2="86" + x1="6" + x2="36" y1="121" y2="121" /> @@ -156,13 +156,13 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="1" - y="151" + x="51" + y="101" /> <text font-size="14" - x="21" - y="171" + x="71" + y="121" > S </text> @@ -178,13 +178,13 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="51" - y="151" + x="101" + y="101" /> <text font-size="14" - x="71" - y="171" + x="121" + y="121" > T </text> @@ -201,12 +201,12 @@ exports[`Test addPanel Should return default addPanel 1`] = ` height="40" width="40" x="1" - y="201" + y="151" /> <text font-size="14" x="21" - y="221" + y="171" > Y </text> @@ -223,12 +223,12 @@ exports[`Test addPanel Should return default addPanel 1`] = ` height="40" width="40" x="51" - y="201" + y="151" /> <text font-size="14" x="71" - y="221" + y="171" > Z </text> @@ -244,13 +244,13 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="1" - y="251" + x="101" + y="151" /> <text font-size="14" - x="21" - y="271" + x="121" + y="171" > ZZ </text> @@ -736,13 +736,13 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="1" - y="101" + x="101" + y="51" /> <text font-size="14" - x="21" - y="121" + x="121" + y="71" > H </text> @@ -756,19 +756,19 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="oplus" > <circle - cx="71" + cx="21" cy="121" r="15" /> <line - x1="71" - x2="71" + x1="21" + x2="21" y1="106" y2="136" /> <line - x1="56" - x2="86" + x1="6" + x2="36" y1="121" y2="121" /> @@ -783,13 +783,13 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="1" - y="151" + x="51" + y="101" /> <text font-size="14" - x="21" - y="171" + x="71" + y="121" > S </text> @@ -805,13 +805,13 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="51" - y="151" + x="101" + y="101" /> <text font-size="14" - x="71" - y="171" + x="121" + y="121" > T </text> @@ -828,12 +828,12 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` height="40" width="40" x="1" - y="201" + y="151" /> <text font-size="14" x="21" - y="221" + y="171" > Y </text> @@ -850,12 +850,12 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` height="40" width="40" x="51" - y="201" + y="151" /> <text font-size="14" x="71" - y="221" + y="171" > Z </text> @@ -871,13 +871,13 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="1" - y="251" + x="101" + y="151" /> <text font-size="14" - x="21" - y="271" + x="121" + y="171" > ZZ </text> From 4e4ff7cc87f04561139300c0d596154e05db5343 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 4 Aug 2022 09:59:23 -0400 Subject: [PATCH 094/108] Rename Display to Parameters --- __tests__/__snapshots__/panel.test.ts.snap | 8 ++++---- src/panel.ts | 2 +- src/styles.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/__tests__/__snapshots__/panel.test.ts.snap b/__tests__/__snapshots__/panel.test.ts.snap index d6848421..888eebab 100644 --- a/__tests__/__snapshots__/panel.test.ts.snap +++ b/__tests__/__snapshots__/panel.test.ts.snap @@ -497,12 +497,12 @@ exports[`Test editPanel Should return editPanel editing X gate 1`] = ` </label> </div> <div - class="display-input" + class="parameters-input" > <label class="block" > - Display + Parameters </label> <input autofocus="true" @@ -946,12 +946,12 @@ exports[`Test panel Should return panel with editPanel visible 1`] = ` </label> </div> <div - class="display-input" + class="parameters-input" > <label class="block" > - Display + Parameters </label> <input autofocus="true" diff --git a/src/panel.ts b/src/panel.ts index d22b4f02..491b3772 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -335,7 +335,7 @@ const editPanel = (dispatch: Dispatch, context: Context): HTMLElement => { title('EDIT'), select('Target', 'target-input', options, target || 0, dispatch, operation), checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), - text('Display', 'display-input', dispatch, operation), + text('Parameters', 'parameters-input', dispatch, operation), ]); return editPanelElem; }; diff --git a/src/styles.ts b/src/styles.ts index 68ee107e..ee7ee3d9 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -287,7 +287,7 @@ const _panel = ` .block { display: block; } - .target-input, .controls-input, .display-input { + .target-input, .controls-input, .parameters-input { margin-bottom: 8px; } .add-panel-gate { From 651efc28cfd2f24fee0aa5c9832e675071773681 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 4 Aug 2022 10:15:49 -0400 Subject: [PATCH 095/108] Fix missing px in width --- src/styles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles.ts b/src/styles.ts index ee7ee3d9..3e9b8440 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -271,7 +271,7 @@ const _panel = ` display: flex; } .panel { - width: ${panelWidth}; + width: ${panelWidth}px; border: solid 1px black; padding: 8px; } From b77fe2de10abaa3672750b28c5d41f174c7eca80 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 4 Aug 2022 10:18:32 -0400 Subject: [PATCH 096/108] Not display Parameters on X (Not) gate --- __tests__/__snapshots__/panel.test.ts.snap | 26 ---------------------- src/panel.ts | 5 ++++- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/__tests__/__snapshots__/panel.test.ts.snap b/__tests__/__snapshots__/panel.test.ts.snap index 888eebab..53447d6f 100644 --- a/__tests__/__snapshots__/panel.test.ts.snap +++ b/__tests__/__snapshots__/panel.test.ts.snap @@ -496,19 +496,6 @@ exports[`Test editPanel Should return editPanel editing X gate 1`] = ` q1 </label> </div> - <div - class="parameters-input" - > - <label - class="block" - > - Parameters - </label> - <input - autofocus="true" - type="text" - /> - </div> </div> `; @@ -945,19 +932,6 @@ exports[`Test panel Should return panel with editPanel visible 1`] = ` q1 </label> </div> - <div - class="parameters-input" - > - <label - class="block" - > - Parameters - </label> - <input - autofocus="true" - type="text" - /> - </div> </div> </div> `; diff --git a/src/panel.ts b/src/panel.ts index 491b3772..92f3a6d2 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -330,13 +330,16 @@ const editPanel = (dispatch: Dispatch, context: Context): HTMLElement => { const target = operation?.targets[0].qId; const controls = operation?.controls?.map((control) => control.qId); + const shouldDisplayParameters = operation?.gate !== 'X'; + const editPanelElem = elem('div', 'edit-panel'); children(editPanelElem, [ title('EDIT'), select('Target', 'target-input', options, target || 0, dispatch, operation), checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), - text('Parameters', 'parameters-input', dispatch, operation), ]); + shouldDisplayParameters && editPanelElem.appendChild(text('Parameters', 'parameters-input', dispatch, operation)); + return editPanelElem; }; From 943ce1c94a82487d461135aab788a9de4d8f358f Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 4 Aug 2022 10:36:15 -0400 Subject: [PATCH 097/108] Add conditions to element renders --- src/panel.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index 92f3a6d2..8af2e50b 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -330,14 +330,18 @@ const editPanel = (dispatch: Dispatch, context: Context): HTMLElement => { const target = operation?.targets[0].qId; const controls = operation?.controls?.map((control) => control.qId); - const shouldDisplayParameters = operation?.gate !== 'X'; + const shouldDisplayTarget = operation?.gate.toLowerCase() !== 'measure'; + const shouldDisplayControls = operation?.gate.toLowerCase() !== 'measure'; + const shouldDisplayParameters = operation?.gate !== 'X' && operation?.gate.toLowerCase() !== 'measure'; const editPanelElem = elem('div', 'edit-panel'); - children(editPanelElem, [ - title('EDIT'), - select('Target', 'target-input', options, target || 0, dispatch, operation), - checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), - ]); + children(editPanelElem, [title('EDIT')]); + shouldDisplayTarget && + editPanelElem.appendChild(select('Target', 'target-input', options, target || 0, dispatch, operation)); + shouldDisplayControls && + editPanelElem.appendChild( + checkboxes('Controls', 'controls-input', options, controls || [], dispatch, operation), + ); shouldDisplayParameters && editPanelElem.appendChild(text('Parameters', 'parameters-input', dispatch, operation)); return editPanelElem; From 6af8e755d242f4e0115c322da3ddde9fa154cd30 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 4 Aug 2022 11:18:21 -0400 Subject: [PATCH 098/108] Fix composed gates disappearing --- src/draggable.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/draggable.ts b/src/draggable.ts index 6c05f32c..a1abcba7 100644 --- a/src/draggable.ts +++ b/src/draggable.ts @@ -271,14 +271,16 @@ const _addEvents = (context: Context) => { elems.forEach((elem) => { elem.addEventListener('mousedown', () => { context.selectedWire = elem.getAttribute('data-wire'); - container.classList.add('moving'); }); const gateElem = _equivGateElem(elem); gateElem?.addEventListener('mousedown', (ev: MouseEvent) => { ev.stopPropagation(); - context.selectedId = _equivDataId(elem); - dropzoneLayer.style.display = 'block'; + if (gateElem.getAttribute('data-expanded') !== 'true') { + context.selectedId = _equivDataId(elem); + container.classList.add('moving'); + dropzoneLayer.style.display = 'block'; + } }); }); From 4c3ec4d97412b7cd5ff18783d320a45d8fe4ed57 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 4 Aug 2022 11:41:22 -0400 Subject: [PATCH 099/108] Add Panel supports composed gates --- __tests__/panel.test.ts | 26 +++++++++++++++++++++++++- src/panel.ts | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/__tests__/panel.test.ts b/__tests__/panel.test.ts index 10256e60..1a28d0bf 100644 --- a/__tests__/panel.test.ts +++ b/__tests__/panel.test.ts @@ -237,7 +237,31 @@ describe('Test defaulGateDictionary', () => { const expected = { Entangle: { gate: 'Entangle', - targets: [{ qId: 0 }], + targets: [{ qId: 0 }, { qId: 1 }], + children: [ + { + gate: 'H', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'X', + isControlled: true, + controls: [ + { + qId: 0, + }, + ], + targets: [ + { + qId: 1, + }, + ], + }, + ], }, RX: { gate: 'RX', diff --git a/src/panel.ts b/src/panel.ts index 8af2e50b..1e28c42d 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -171,7 +171,15 @@ const update = (action: Action, context: Context, useRefresh: () => void): void case 'TARGET': { const { operation } = context; const payload = action.payload as Register[]; - operation && (operation.targets = payload); + if (operation) { + const difference = payload[0].qId - operation.targets[0].qId; + const newTargets = operation.targets.map((target) => { + const { qId } = target; + const newQId = qId + difference; + return { qId: newQId }; + }); + operation.targets = newTargets; + } useRefresh(); break; } @@ -643,7 +651,31 @@ interface GateDictionary { const defaultGateDictionary: GateDictionary = { Entangle: { gate: 'Entangle', - targets: [{ qId: 0 }], + targets: [{ qId: 0 }, { qId: 1 }], + children: [ + { + gate: 'H', + targets: [ + { + qId: 0, + }, + ], + }, + { + gate: 'X', + isControlled: true, + controls: [ + { + qId: 0, + }, + ], + targets: [ + { + qId: 1, + }, + ], + }, + ], }, RX: { gate: 'RX', From 89a91f17c1003b9aba77dbd20b01b42763650426 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 4 Aug 2022 12:00:56 -0400 Subject: [PATCH 100/108] Fix composed gate children don't change targets --- src/draggable.ts | 1 + src/panel.ts | 9 ++------- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/draggable.ts b/src/draggable.ts index a1abcba7..290ce6ab 100644 --- a/src/draggable.ts +++ b/src/draggable.ts @@ -553,5 +553,6 @@ export { _equivGateElem, _equivParentArray, _lastIndex, + _offsetRecursively, exportedForTesting, }; diff --git a/src/panel.ts b/src/panel.ts index 1e28c42d..fe3c0b79 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -5,7 +5,7 @@ import cloneDeep from 'lodash/cloneDeep'; import range from 'lodash/range'; import { Operation } from './circuit'; import { gateHeight, horizontalGap, minGateWidth, panelWidth, verticalGap } from './constants'; -import { _equivOperation, _equivParentArray, _lastIndex } from './draggable'; +import { _equivOperation, _equivParentArray, _lastIndex, _offsetRecursively } from './draggable'; import { _formatGate } from './formatters/gateFormatter'; import { GateType, Metadata } from './metadata'; import { Register } from './register'; @@ -173,12 +173,7 @@ const update = (action: Action, context: Context, useRefresh: () => void): void const payload = action.payload as Register[]; if (operation) { const difference = payload[0].qId - operation.targets[0].qId; - const newTargets = operation.targets.map((target) => { - const { qId } = target; - const newQId = qId + difference; - return { qId: newQId }; - }); - operation.targets = newTargets; + _offsetRecursively(operation, difference, context.registerSize); } useRefresh(); break; From 197fa8995efe42a7063322751e54d3db24e451d7 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 4 Aug 2022 14:40:32 -0400 Subject: [PATCH 101/108] Set panelMinHeight --- src/constants.ts | 2 ++ src/styles.ts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index d98bbb66..a2415ffa 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -41,6 +41,8 @@ export const regLineStart = 40; // Panel /** Panel width */ export const panelWidth = 150; +/** Panel minimum height */ +export const panelMinHeight = 300; /** Gap between gates in Add Panel */ export const horizontalGap = 10; export const verticalGap = 10; diff --git a/src/styles.ts b/src/styles.ts index 3e9b8440..9bd7d4e9 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { gateHeight, minGateWidth, panelWidth } from './constants'; +import { gateHeight, minGateWidth, panelMinHeight, panelWidth } from './constants'; /** * Provides configuration for CSS styles of visualization. @@ -297,7 +297,7 @@ const _panel = ` } .add-panel-svg { width: ${panelWidth}px; - height: 100%; + min-height: ${panelMinHeight}px; } .ghost { width: ${minGateWidth}px; From 0f637be81795085a174218bbbca415ba022ab57f Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 4 Aug 2022 14:41:02 -0400 Subject: [PATCH 102/108] Make customDictionary extended instead of replaced --- src/panel.ts | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index fe3c0b79..37be7a12 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -292,7 +292,10 @@ const addPanel = (dispatch: Dispatch, context: Context, options?: PanelOptions): if (options != null) { const { displaySize, gateDictionary: optionGateDictionary } = options; displaySize && (objectKeys = objectKeys.slice(0, displaySize)); - optionGateDictionary && (gateDictionary = optionGateDictionary); + if (optionGateDictionary) { + gateDictionary = { ...optionGateDictionary, ...defaultGateDictionary }; + objectKeys = Object.keys(gateDictionary); + } } let prefixX = 0; @@ -644,34 +647,6 @@ interface GateDictionary { * Object for default gate dictionary */ const defaultGateDictionary: GateDictionary = { - Entangle: { - gate: 'Entangle', - targets: [{ qId: 0 }, { qId: 1 }], - children: [ - { - gate: 'H', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'X', - isControlled: true, - controls: [ - { - qId: 0, - }, - ], - targets: [ - { - qId: 1, - }, - ], - }, - ], - }, RX: { gate: 'RX', targets: [{ qId: 0 }], From 05f8af4323886a5ffefaed0235178a61cdaa64f2 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 4 Aug 2022 14:46:33 -0400 Subject: [PATCH 103/108] Remove unnecessary useRefresh --- src/panel.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/panel.ts b/src/panel.ts index 37be7a12..52477d4b 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -205,7 +205,6 @@ const update = (action: Action, context: Context, useRefresh: () => void): void ) { targetOperationParent.splice(targetLastIndex, 0, context.operation); } - useRefresh(); break; } case 'DISPLAY_DROPZONE_LAYER': { @@ -290,10 +289,10 @@ const addPanel = (dispatch: Dispatch, context: Context, options?: PanelOptions): let gateDictionary = defaultGateDictionary; let objectKeys = Object.keys(gateDictionary); if (options != null) { - const { displaySize, gateDictionary: optionGateDictionary } = options; + const { displaySize, gateDictionary: customGateDictionary } = options; displaySize && (objectKeys = objectKeys.slice(0, displaySize)); - if (optionGateDictionary) { - gateDictionary = { ...optionGateDictionary, ...defaultGateDictionary }; + if (customGateDictionary) { + gateDictionary = { ...defaultGateDictionary, ...customGateDictionary }; objectKeys = Object.keys(gateDictionary); } } From ae819ed48e7f1768f44fdeb60dc07cb3493cfd15 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 4 Aug 2022 14:48:20 -0400 Subject: [PATCH 104/108] Update tests --- __tests__/__snapshots__/panel.test.ts.snap | 204 ++++++++------------- __tests__/panel.test.ts | 28 --- 2 files changed, 80 insertions(+), 152 deletions(-) diff --git a/__tests__/__snapshots__/panel.test.ts.snap b/__tests__/__snapshots__/panel.test.ts.snap index 53447d6f..b598866f 100644 --- a/__tests__/__snapshots__/panel.test.ts.snap +++ b/__tests__/__snapshots__/panel.test.ts.snap @@ -20,16 +20,16 @@ exports[`Test addPanel Should return default addPanel 1`] = ` <rect class="gate-unitary" height="40" - width="76" + width="40" x="1" y="1" /> <text font-size="14" - x="39" + x="21" y="21" > - Entangle + RX </text> </g> </g> @@ -43,35 +43,13 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="87" + x="51" y="1" /> <text font-size="14" - x="107" + x="71" y="21" - > - RX - </text> - </g> - </g> - </g> - <g - class="gate" - > - <g> - <g> - <rect - class="gate-unitary" - height="40" - width="40" - x="1" - y="51" - /> - <text - font-size="14" - x="21" - y="71" > RY </text> @@ -87,13 +65,13 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="51" - y="51" + x="101" + y="1" /> <text font-size="14" - x="71" - y="71" + x="121" + y="21" > RZ </text> @@ -109,12 +87,12 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="101" + x="1" y="51" /> <text font-size="14" - x="121" + x="21" y="71" > H @@ -129,21 +107,21 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="oplus" > <circle - cx="21" - cy="121" + cx="71" + cy="71" r="15" /> <line - x1="21" - x2="21" - y1="106" - y2="136" + x1="71" + x2="71" + y1="56" + y2="86" /> <line - x1="6" - x2="36" - y1="121" - y2="121" + x1="56" + x2="86" + y1="71" + y2="71" /> </g> </g> @@ -156,13 +134,13 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="51" - y="101" + x="101" + y="51" /> <text font-size="14" - x="71" - y="121" + x="121" + y="71" > S </text> @@ -178,12 +156,12 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="101" + x="1" y="101" /> <text font-size="14" - x="121" + x="21" y="121" > T @@ -200,13 +178,13 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="1" - y="151" + x="51" + y="101" /> <text font-size="14" - x="21" - y="171" + x="71" + y="121" > Y </text> @@ -222,13 +200,13 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="51" - y="151" + x="101" + y="101" /> <text font-size="14" - x="71" - y="171" + x="121" + y="121" > Z </text> @@ -244,12 +222,12 @@ exports[`Test addPanel Should return default addPanel 1`] = ` class="gate-unitary" height="40" width="40" - x="101" + x="1" y="151" /> <text font-size="14" - x="121" + x="21" y="171" > ZZ @@ -281,16 +259,16 @@ exports[`Test addPanel Should return default addPanel with displaySize 2 1`] = ` <rect class="gate-unitary" height="40" - width="76" + width="40" x="1" y="1" /> <text font-size="14" - x="39" + x="21" y="21" > - Entangle + RX </text> </g> </g> @@ -304,15 +282,15 @@ exports[`Test addPanel Should return default addPanel with displaySize 2 1`] = ` class="gate-unitary" height="40" width="40" - x="87" + x="51" y="1" /> <text font-size="14" - x="107" + x="71" y="21" > - RX + RY </text> </g> </g> @@ -634,16 +612,16 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` <rect class="gate-unitary" height="40" - width="76" + width="40" x="1" y="1" /> <text font-size="14" - x="39" + x="21" y="21" > - Entangle + RX </text> </g> </g> @@ -657,35 +635,13 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="87" + x="51" y="1" /> <text font-size="14" - x="107" + x="71" y="21" - > - RX - </text> - </g> - </g> - </g> - <g - class="gate" - > - <g> - <g> - <rect - class="gate-unitary" - height="40" - width="40" - x="1" - y="51" - /> - <text - font-size="14" - x="21" - y="71" > RY </text> @@ -701,13 +657,13 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="51" - y="51" + x="101" + y="1" /> <text font-size="14" - x="71" - y="71" + x="121" + y="21" > RZ </text> @@ -723,12 +679,12 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="101" + x="1" y="51" /> <text font-size="14" - x="121" + x="21" y="71" > H @@ -743,21 +699,21 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="oplus" > <circle - cx="21" - cy="121" + cx="71" + cy="71" r="15" /> <line - x1="21" - x2="21" - y1="106" - y2="136" + x1="71" + x2="71" + y1="56" + y2="86" /> <line - x1="6" - x2="36" - y1="121" - y2="121" + x1="56" + x2="86" + y1="71" + y2="71" /> </g> </g> @@ -770,13 +726,13 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="51" - y="101" + x="101" + y="51" /> <text font-size="14" - x="71" - y="121" + x="121" + y="71" > S </text> @@ -792,12 +748,12 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="101" + x="1" y="101" /> <text font-size="14" - x="121" + x="21" y="121" > T @@ -814,13 +770,13 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="1" - y="151" + x="51" + y="101" /> <text font-size="14" - x="21" - y="171" + x="71" + y="121" > Y </text> @@ -836,13 +792,13 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="51" - y="151" + x="101" + y="101" /> <text font-size="14" - x="71" - y="171" + x="121" + y="121" > Z </text> @@ -858,12 +814,12 @@ exports[`Test panel Should return panel with addPanel visible 1`] = ` class="gate-unitary" height="40" width="40" - x="101" + x="1" y="151" /> <text font-size="14" - x="121" + x="21" y="171" > ZZ diff --git a/__tests__/panel.test.ts b/__tests__/panel.test.ts index 1a28d0bf..428ede80 100644 --- a/__tests__/panel.test.ts +++ b/__tests__/panel.test.ts @@ -235,34 +235,6 @@ describe('Test gate', () => { describe('Test defaulGateDictionary', () => { test('Verify defaultGateDictionary', () => { const expected = { - Entangle: { - gate: 'Entangle', - targets: [{ qId: 0 }, { qId: 1 }], - children: [ - { - gate: 'H', - targets: [ - { - qId: 0, - }, - ], - }, - { - gate: 'X', - isControlled: true, - controls: [ - { - qId: 0, - }, - ], - targets: [ - { - qId: 1, - }, - ], - }, - ], - }, RX: { gate: 'RX', targets: [{ qId: 0 }], From 4c03bf020c7bfd4793f0d4b534da91257e975a45 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Fri, 5 Aug 2022 13:10:23 -0400 Subject: [PATCH 105/108] More examples --- example/index.html | 12 +++++++++--- example/script.js | 27 +++++++++++++++++++-------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/example/index.html b/example/index.html index 196a80c5..95bdfd82 100644 --- a/example/index.html +++ b/example/index.html @@ -46,11 +46,17 @@ <h1 id="title">quantum-viz.js</h1> <h4>1. Entangle</h4> <div id="entangle" class="container"> </div> - <h4>2. Sample</h4> + <h4>2. Entangle with useDraggable</h4> + <div id="entangle-usedraggable" class="container"> + </div> + <h4>3. Entangle with useDraggable and usePanel</h4> + <div id="entangle-usedraggable-usepanel" class="container"> + </div> + <h4>4. Sample</h4> <div id="sample" class="container"></div> - <h4>3. Teleport</h4> + <h4>5. Teleport</h4> <div id="teleport" class="container"></div> - <h4>4. Grover</h4> + <h4>6. Grover</h4> <div id="grover" class="container"></div> </div> </main> diff --git a/example/script.js b/example/script.js index 69b5639a..7d4ff864 100644 --- a/example/script.js +++ b/example/script.js @@ -8,20 +8,31 @@ if (typeof qviz != 'undefined') { const entangleDiv = document.getElementById('entangle'); if (entangleDiv != null) { qviz.create(entangle) // - .useDraggable() - .usePanel({ displaySize: 3 }) + .useOnCircuitChange((circuit) => { + console.log('New circuit ↓'); + console.log(circuit); + }) .draw(entangleDiv); } + const entangleUDDiv = document.getElementById('entangle-usedraggable'); + if (entangleUDDiv != null) { + qviz.create(entangle) // + .useDraggable() + .draw(entangleUDDiv); + } + + const entangleUDUPDiv = document.getElementById('entangle-usedraggable-usepanel'); + if (entangleUDUPDiv != null) { + qviz.create(entangle) // + .useDraggable() + .usePanel() + .draw(entangleUDUPDiv); + } + const sampleDiv = document.getElementById('sample'); if (sampleDiv != null) { qviz.create(sample) // - .useDraggable() - .usePanel() - .useOnCircuitChange((circuit) => { - console.log('New circuit ↓'); - console.log(circuit); - }) .draw(sampleDiv); } From c14219c64c0ea550ccf1c5ee59bf56937b5969ed Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Fri, 5 Aug 2022 13:18:10 -0400 Subject: [PATCH 106/108] Add extension usage instruction --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f3e9cd22..665c94bf 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,22 @@ const sampleCircuit = { 2. Draw it in a `div`: ```js const sampleDiv = document.getElementById('sample'); -qviz.draw(sampleCircuit, sampleDiv, qviz.STYLES['Default']); +qviz.create(sampleCircuit) + .draw(sampleDiv) ``` Refer to the [`example`](./example) folder for an example on how to use quantum-viz.js. Notice that in order to open the contents of this folder in a browser you will need first to install from source (see [below](#running-from-source)). +3. Enable extensions by: +```js +const sampleDiv = document.getElementById('sample'); +qviz.create(sampleCircuit) + .useDraggble() // drag and drop + .usePanel() // edit and add panel + .useOnCircuitChange(circuit => console.log(circuit)) // trigger when circuit changes + .draw(sampleDiv) +``` + ## Python usage To use this package with Python, use [quantum-viz](/quantum-viz). From 79b849aef0ad2baf53136fb583890f23d3be2b7d Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Fri, 5 Aug 2022 14:36:32 -0400 Subject: [PATCH 107/108] Disable control checkboxes if already in targets --- src/panel.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/panel.ts b/src/panel.ts index 52477d4b..ea39fa00 100755 --- a/src/panel.ts +++ b/src/panel.ts @@ -480,7 +480,11 @@ const checkboxes = ( const elem = checkbox(option.value, option.text); const inputElem = elem.querySelector('input') as HTMLInputElement; selectedIndexes.includes(index) && inputElem.setAttribute('checked', 'true'); - operation == undefined && inputElem.setAttribute('disabled', 'true'); + // Disable control checkboxes if already in targets + if (operation) { + const targetIndexes = operation.targets.map((register) => register.qId); + targetIndexes.includes(index) && inputElem.setAttribute('disabled', 'true'); + } inputElem.onchange = () => { // Get all checked options From 1e8f11c1ab09172ce7e2208f1391fe4341136825 Mon Sep 17 00:00:00 2001 From: Aaron Nguyen <me@aaronnguyen.dev> Date: Thu, 11 Aug 2022 11:14:30 -0400 Subject: [PATCH 108/108] Update tests --- __tests__/__snapshots__/panel.test.ts.snap | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/__tests__/__snapshots__/panel.test.ts.snap b/__tests__/__snapshots__/panel.test.ts.snap index b598866f..e2589485 100644 --- a/__tests__/__snapshots__/panel.test.ts.snap +++ b/__tests__/__snapshots__/panel.test.ts.snap @@ -340,6 +340,7 @@ exports[`Test checkboxes Test with gate X with 1 control 1`] = ` </label> <label> <input + disabled="true" type="checkbox" value="0" /> @@ -375,6 +376,7 @@ exports[`Test checkboxes Test with gate X with 2 controls 1`] = ` </label> <label> <input + disabled="true" type="checkbox" value="1" /> @@ -461,6 +463,7 @@ exports[`Test editPanel Should return editPanel editing X gate 1`] = ` </label> <label> <input + disabled="true" type="checkbox" value="0" /> @@ -875,6 +878,7 @@ exports[`Test panel Should return panel with editPanel visible 1`] = ` </label> <label> <input + disabled="true" type="checkbox" value="0" />