diff --git a/common/reviews/api/tools.api.md b/common/reviews/api/tools.api.md index 6adbb40db9..b7f2cd51e6 100644 --- a/common/reviews/api/tools.api.md +++ b/common/reviews/api/tools.api.md @@ -664,6 +664,62 @@ function clip(a: any, b: any, box: any, da?: any, db?: any): 1 | 0; // @public (undocumented) function clip_2(val: number, low: number, high: number): number; +// @public (undocumented) +export class CobbAngleTool extends AnnotationTool { + constructor(toolProps?: PublicToolProps, defaultToolProps?: ToolProps); + // (undocumented) + _activateDraw: (element: HTMLDivElement) => void; + // (undocumented) + _activateModify: (element: HTMLDivElement) => void; + // (undocumented) + addNewAnnotation: (evt: EventTypes_2.MouseDownActivateEventType) => AngleAnnotation; + // (undocumented) + angleStartedNotYetCompleted: boolean; + // (undocumented) + _calculateCachedStats(annotation: any, renderingEngine: any, enabledElement: any): any; + // (undocumented) + cancel: (element: HTMLDivElement) => any; + // (undocumented) + _deactivateDraw: (element: HTMLDivElement) => void; + // (undocumented) + _deactivateModify: (element: HTMLDivElement) => void; + // (undocumented) + editData: { + annotation: any; + viewportIdsToRender: string[]; + handleIndex?: number; + movingTextBox?: boolean; + newAnnotation?: boolean; + hasMoved?: boolean; + } | null; + // (undocumented) + _getTextLines(data: any, targetId: any): string[]; + // (undocumented) + handleSelectedCallback(evt: EventTypes_2.MouseDownEventType, annotation: AngleAnnotation, handle: ToolHandle, interactionType?: string): void; + // (undocumented) + isDrawing: boolean; + // (undocumented) + isHandleOutsideImage: boolean; + // (undocumented) + isPointNearTool: (element: HTMLDivElement, annotation: AngleAnnotation, canvasCoords: Types_2.Point2, proximity: number) => boolean; + // (undocumented) + mouseDragCallback: any; + // (undocumented) + _mouseDragCallback: (evt: EventTypes_2.MouseDragEventType | EventTypes_2.MouseMoveEventType) => void; + // (undocumented) + _mouseUpCallback: (evt: EventTypes_2.MouseUpEventType | EventTypes_2.MouseClickEventType) => void; + // (undocumented) + renderAnnotation: (enabledElement: Types_2.IEnabledElement, svgDrawingHelper: SVGDrawingHelper) => boolean; + // (undocumented) + _throttledCalculateCachedStats: any; + // (undocumented) + static toolName: any; + // (undocumented) + toolSelectedCallback: (evt: EventTypes_2.MouseDownEventType, annotation: AngleAnnotation, interactionType: InteractionTypes) => void; + // (undocumented) + touchDragCallback: any; +} + // @public (undocumented) type Color = [number, number, number, number]; diff --git a/package.json b/package.json index 3744a1504c..5333cde3d6 100644 --- a/package.json +++ b/package.json @@ -45,12 +45,14 @@ "@babel/preset-typescript": "^7.16.7", "@babel/runtime": "^7.16.7", "@cornerstonejs/calculate-suv": "1.0.2", - "@microsoft/api-extractor": "7.19.5", + "@microsoft/api-extractor": "7.21.3", "@types/node": "^14.18.9", "@types/react": "^17.0.38", "@types/react-dom": "^17.0.11", - "@typescript-eslint/eslint-plugin": "^4.33.0", - "@typescript-eslint/parser": "^4.33.0", + "@typescript-eslint/eslint-plugin": "^5.48.1", + "@typescript-eslint/parser": "^5.48.1", + "acorn": "^7.1.0", + "acorn-jsx": "^5.2.0", "autoprefixer": "^10.4.2", "babel-loader": "8.2.3", "babel-plugin-istanbul": "^6.1.1", @@ -60,18 +62,20 @@ "cross-env": "^7.0.3", "css-loader": "^5.2.7", "cssnano": "^4.1.11", - "eslint": "7.32.0", - "eslint-config-prettier": "^8.3.0", + "eslint": "^8.17.0", + "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "^2.25.4", "eslint-plugin-jsx-a11y": "6.x", "eslint-plugin-prettier": "^3.4.1", "eslint-plugin-tsdoc": "^0.2.14", "eslint-webpack-plugin": "^2.6.0", "file-loader": "^6.2.0", + "follow-redirects": "^1.10.0", "html-webpack-plugin": "^5.5.0", "husky": "^4.3.8", "istanbul-instrumenter-loader": "^3.0.1", "jasmine": "^4.0.2", + "jest": "^27.5.1", "karma": "^6.3.12", "karma-chrome-launcher": "^3.1.0", "karma-coverage": "^2.1.0", @@ -88,9 +92,16 @@ "postcss-import": "^14.0.2", "postcss-loader": "^6.2.1", "postcss-preset-env": "^7.4.1", - "prettier": "^2.5.1", + "prettier": "^2.8.3", "prop-types": "^15.8.1", "puppeteer": "^13.5.0", + "rollup": "^1.31.1", + "rollup-plugin-babel": "^4.3.3", + "rollup-plugin-commonjs": "^9.3.4", + "rollup-plugin-json": "^3.1.0", + "rollup-plugin-node-builtins": "^2.1.2", + "rollup-plugin-node-globals": "^1.4.0", + "rollup-plugin-node-resolve": "^4.2.4", "shader-loader": "^1.3.1", "shelljs": "^0.8.5", "sinon": "^10.0.0", @@ -100,13 +111,15 @@ "ts-loader": "^9.2.6", "typedoc": "^0.22.13", "typescript": "4.6.4", + "unzipper": "^0.10.9", "url-loader": "^4.1.1", "webpack": "5.67.0", "webpack-bundle-analyzer": "^4.5.0", "webpack-cli": "^4.9.2", "webpack-dev-server": "^3.11.3", "webpack-merge": "5.8.0", - "worker-loader": "^3.0.8" + "worker-loader": "^3.0.8", + "xml2js": "^0.4.23" }, "husky": { "hooks": { diff --git a/packages/adapters/src/adapters/Cornerstone3D/CobbAngle.js b/packages/adapters/src/adapters/Cornerstone3D/CobbAngle.js new file mode 100644 index 0000000000..c58d7fee68 --- /dev/null +++ b/packages/adapters/src/adapters/Cornerstone3D/CobbAngle.js @@ -0,0 +1,125 @@ +import { utilities } from "dcmjs"; +import CORNERSTONE_3D_TAG from "./cornerstone3DTag"; +import MeasurementReport from "./MeasurementReport"; + +const { CobbAngle: TID300CobbAngle } = utilities.TID300; + +const MEASUREMENT_TYPE = "CobbAngle"; +const trackingIdentifierTextValue = `${CORNERSTONE_3D_TAG}:${MEASUREMENT_TYPE}`; + +class CobbAngle { + // TODO: this function is required for all Cornerstone Tool Adapters, since it is called by MeasurementReport. + static getMeasurementData( + MeasurementGroup, + sopInstanceUIDToImageIdMap, + imageToWorldCoords, + metadata + ) { + const { defaultState, NUMGroup, SCOORDGroup, ReferencedFrameNumber } = + MeasurementReport.getSetupMeasurementData( + MeasurementGroup, + sopInstanceUIDToImageIdMap, + metadata, + CobbAngle.toolType + ); + + const referencedImageId = + defaultState.annotation.metadata.referencedImageId; + + const { GraphicData } = SCOORDGroup; + const worldCoords = []; + for (let i = 0; i < GraphicData.length; i += 2) { + const point = imageToWorldCoords(referencedImageId, [ + GraphicData[i], + GraphicData[i + 1] + ]); + worldCoords.push(point); + } + + const state = defaultState; + + state.annotation.data = { + handles: { + points: [ + worldCoords[0], + worldCoords[1], + worldCoords[2], + worldCoords[3] + ], + activeHandleIndex: 0, + textBox: { + hasMoved: false + } + }, + cachedStats: { + [`imageId:${referencedImageId}`]: { + angle: NUMGroup + ? NUMGroup.MeasuredValueSequence.NumericValue + : null + } + }, + frameNumber: ReferencedFrameNumber + }; + + return state; + } + + static getTID300RepresentationArguments(tool, worldToImageCoords) { + const { data, finding, findingSites, metadata } = tool; + const { cachedStats = {}, handles } = data; + + const { referencedImageId } = metadata; + + if (!referencedImageId) { + throw new Error( + "CobbAngle.getTID300RepresentationArguments: referencedImageId is not defined" + ); + } + + const start1 = worldToImageCoords(referencedImageId, handles.points[0]); + const end1 = worldToImageCoords(referencedImageId, handles.points[1]); + + const start2 = worldToImageCoords(referencedImageId, handles.points[2]); + const end2 = worldToImageCoords(referencedImageId, handles.points[3]); + + const point1 = { x: start1[0], y: start1[1] }; + const point2 = { x: end1[0], y: end1[1] }; + const point3 = { x: start2[0], y: start2[1] }; + const point4 = { x: end2[0], y: end2[1] }; + + const { angle } = cachedStats[`imageId:${referencedImageId}`] || {}; + + return { + point1, + point2, + point3, + point4, + rAngle: angle, + trackingIdentifierTextValue, + finding, + findingSites: findingSites || [] + }; + } +} + +CobbAngle.toolType = MEASUREMENT_TYPE; +CobbAngle.utilityToolType = MEASUREMENT_TYPE; +console.log("TID300CobbAngle=", TID300CobbAngle); +CobbAngle.TID300Representation = TID300CobbAngle; +CobbAngle.isValidCornerstoneTrackingIdentifier = TrackingIdentifier => { + if (!TrackingIdentifier.includes(":")) { + return false; + } + + const [cornerstone3DTag, toolType] = TrackingIdentifier.split(":"); + + if (cornerstone3DTag !== CORNERSTONE_3D_TAG) { + return false; + } + + return toolType === MEASUREMENT_TYPE; +}; + +MeasurementReport.registerTool(CobbAngle); + +export default CobbAngle; diff --git a/packages/adapters/src/adapters/Cornerstone3D/index.js b/packages/adapters/src/adapters/Cornerstone3D/index.js index 0fa1c55d24..65f9d25f16 100644 --- a/packages/adapters/src/adapters/Cornerstone3D/index.js +++ b/packages/adapters/src/adapters/Cornerstone3D/index.js @@ -4,6 +4,7 @@ import CORNERSTONE_3D_TAG from "./cornerstone3DTag"; import ArrowAnnotate from "./ArrowAnnotate"; import Bidirectional from "./Bidirectional"; +import CobbAngle from "./CobbAngle"; import EllipticalROI from "./EllipticalROI"; import Length from "./Length"; import PlanarFreehandROI from "./PlanarFreehandROI"; @@ -11,6 +12,7 @@ import Probe from "./Probe"; const Cornerstone3D = { Bidirectional, + CobbAngle, Length, EllipticalROI, ArrowAnnotate, diff --git a/packages/tools/examples/stackAnnotationTools/index.ts b/packages/tools/examples/stackAnnotationTools/index.ts index fb14398d5a..83bcabb5da 100644 --- a/packages/tools/examples/stackAnnotationTools/index.ts +++ b/packages/tools/examples/stackAnnotationTools/index.ts @@ -19,6 +19,7 @@ const { EllipticalROITool, BidirectionalTool, AngleTool, + CobbAngleTool, ToolGroupManager, ArrowAnnotateTool, Enums: csToolsEnums, @@ -60,6 +61,7 @@ const toolsNames = [ EllipticalROITool.toolName, BidirectionalTool.toolName, AngleTool.toolName, + CobbAngleTool.toolName, ArrowAnnotateTool.toolName, ]; let selectedToolName = toolsNames[0]; @@ -100,6 +102,7 @@ async function run() { cornerstoneTools.addTool(EllipticalROITool); cornerstoneTools.addTool(BidirectionalTool); cornerstoneTools.addTool(AngleTool); + cornerstoneTools.addTool(CobbAngleTool); cornerstoneTools.addTool(ArrowAnnotateTool); // Define a tool group, which defines how mouse events map to tool commands for @@ -113,6 +116,7 @@ async function run() { toolGroup.addTool(EllipticalROITool.toolName); toolGroup.addTool(BidirectionalTool.toolName); toolGroup.addTool(AngleTool.toolName); + toolGroup.addTool(CobbAngleTool.toolName); toolGroup.addTool(ArrowAnnotateTool.toolName); // Set the initial state of the tools, here we set one tool active on left click. @@ -131,6 +135,7 @@ async function run() { toolGroup.setToolPassive(EllipticalROITool.toolName); toolGroup.setToolPassive(BidirectionalTool.toolName); toolGroup.setToolPassive(AngleTool.toolName); + toolGroup.setToolPassive(CobbAngleTool.toolName); toolGroup.setToolPassive(ArrowAnnotateTool.toolName); // Get Cornerstone imageIds and fetch metadata into RAM diff --git a/packages/tools/examples/stackToVolumeWithAnnotations/index.ts b/packages/tools/examples/stackToVolumeWithAnnotations/index.ts index 1dde1ab718..aafd505bce 100644 --- a/packages/tools/examples/stackToVolumeWithAnnotations/index.ts +++ b/packages/tools/examples/stackToVolumeWithAnnotations/index.ts @@ -29,6 +29,7 @@ const { EllipticalROITool, BidirectionalTool, AngleTool, + CobbAngleTool, ToolGroupManager, ArrowAnnotateTool, StackScrollMouseWheelTool, @@ -71,6 +72,7 @@ const toolsNames = [ EllipticalROITool.toolName, BidirectionalTool.toolName, AngleTool.toolName, + CobbAngleTool.toolName, ArrowAnnotateTool.toolName, ]; let selectedToolName = toolsNames[0]; @@ -139,6 +141,7 @@ async function run() { cornerstoneTools.addTool(EllipticalROITool); cornerstoneTools.addTool(BidirectionalTool); cornerstoneTools.addTool(AngleTool); + cornerstoneTools.addTool(CobbAngleTool); cornerstoneTools.addTool(ArrowAnnotateTool); cornerstoneTools.addTool(StackScrollMouseWheelTool); @@ -153,6 +156,7 @@ async function run() { toolGroup.addTool(EllipticalROITool.toolName); toolGroup.addTool(BidirectionalTool.toolName); toolGroup.addTool(AngleTool.toolName); + toolGroup.addTool(CobbAngleTool.toolName); toolGroup.addTool(ArrowAnnotateTool.toolName); toolGroup.addTool(StackScrollMouseWheelTool.toolName); @@ -173,6 +177,7 @@ async function run() { toolGroup.setToolPassive(EllipticalROITool.toolName); toolGroup.setToolPassive(BidirectionalTool.toolName); toolGroup.setToolPassive(AngleTool.toolName); + toolGroup.setToolPassive(CobbAngleTool.toolName); toolGroup.setToolPassive(ArrowAnnotateTool.toolName); // Get Cornerstone imageIds and fetch metadata into RAM diff --git a/packages/tools/src/index.ts b/packages/tools/src/index.ts index 9f2c7b2968..196512e290 100644 --- a/packages/tools/src/index.ts +++ b/packages/tools/src/index.ts @@ -49,6 +49,7 @@ import { SegmentationDisplayTool, BrushTool, AngleTool, + CobbAngleTool, MagnifyTool, ReferenceCursors, ReferenceLines, @@ -88,6 +89,7 @@ export { PlanarFreehandROITool, ArrowAnnotateTool, AngleTool, + CobbAngleTool, MagnifyTool, ReferenceCursors, ReferenceLines, diff --git a/packages/tools/src/tools/annotation/CobbAngleTool.ts b/packages/tools/src/tools/annotation/CobbAngleTool.ts new file mode 100644 index 0000000000..31e6bed575 --- /dev/null +++ b/packages/tools/src/tools/annotation/CobbAngleTool.ts @@ -0,0 +1,813 @@ +import { Events } from '../../enums'; +import { + getEnabledElement, + triggerEvent, + eventTarget, +} from '@cornerstonejs/core'; +import type { Types } from '@cornerstonejs/core'; + +import { AnnotationTool } from '../base'; +import throttle from '../../utilities/throttle'; +import { + addAnnotation, + getAnnotations, + removeAnnotation, +} from '../../stateManagement/annotation/annotationState'; +import { isAnnotationLocked } from '../../stateManagement/annotation/annotationLocking'; +import * as lineSegment from '../../utilities/math/line'; +import angleBetweenLines from '../../utilities/math/angle/angleBetweenLines'; +import { midPoint2 } from '../../utilities/math/midPoint'; + +import { + drawHandles as drawHandlesSvg, + drawLine as drawLineSvg, + drawLinkedTextBox as drawLinkedTextBoxSvg, +} from '../../drawingSvg'; +import { state } from '../../store'; +import { getViewportIdsWithToolToRender } from '../../utilities/viewportFilters'; +import { getTextBoxCoordsCanvas } from '../../utilities/drawing'; +import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds'; +import { + AnnotationCompletedEventDetail, + AnnotationModifiedEventDetail, +} from '../../types/EventTypes'; + +import { + resetElementCursor, + hideElementCursor, +} from '../../cursors/elementCursor'; + +import { + EventTypes, + ToolHandle, + TextBoxHandle, + PublicToolProps, + ToolProps, + InteractionTypes, + SVGDrawingHelper, +} from '../../types'; +import { AngleAnnotation } from '../../types/ToolSpecificAnnotationTypes'; +import { StyleSpecifier } from '../../types/AnnotationStyle'; + +class CobbAngleTool extends AnnotationTool { + static toolName; + + public touchDragCallback: any; + public mouseDragCallback: any; + angleStartedNotYetCompleted: boolean; + _throttledCalculateCachedStats: any; + editData: { + annotation: any; + viewportIdsToRender: string[]; + handleIndex?: number; + movingTextBox?: boolean; + newAnnotation?: boolean; + hasMoved?: boolean; + } | null; + isDrawing: boolean; + isHandleOutsideImage: boolean; + + constructor( + toolProps: PublicToolProps = {}, + defaultToolProps: ToolProps = { + supportedInteractionTypes: ['Mouse', 'Touch'], + configuration: { + shadow: true, + preventHandleOutsideImage: false, + }, + } + ) { + super(toolProps, defaultToolProps); + + this._throttledCalculateCachedStats = throttle( + this._calculateCachedStats, + 100, + { trailing: true } + ); + } + + /** + * Based on the current position of the mouse and the current imageId to create + * a Length Annotation and stores it in the annotationManager + * + * @param evt - EventTypes.NormalizedMouseEventType + * @returns The annotation object. + * + */ + addNewAnnotation = ( + evt: EventTypes.MouseDownActivateEventType + ): AngleAnnotation => { + if (this.angleStartedNotYetCompleted) { + return; + } + + this.angleStartedNotYetCompleted = true; + const eventDetail = evt.detail; + const { currentPoints, element } = eventDetail; + const worldPos = currentPoints.world; + const enabledElement = getEnabledElement(element); + const { viewport, renderingEngine } = enabledElement; + + hideElementCursor(element); + this.isDrawing = true; + + const camera = viewport.getCamera(); + const { viewPlaneNormal, viewUp } = camera; + + const referencedImageId = this.getReferencedImageId( + viewport, + worldPos, + viewPlaneNormal, + viewUp + ); + + const annotation = { + highlighted: true, + invalidated: true, + metadata: { + toolName: this.getToolName(), + viewPlaneNormal: [...viewPlaneNormal], + viewUp: [...viewUp], + FrameOfReferenceUID: viewport.getFrameOfReferenceUID(), + referencedImageId, + }, + data: { + handles: { + points: [[...worldPos], [...worldPos]], + activeHandleIndex: null, + textBox: { + hasMoved: false, + worldPosition: [0, 0, 0], + worldBoundingBox: { + topLeft: [0, 0, 0], + topRight: [0, 0, 0], + bottomLeft: [0, 0, 0], + bottomRight: [0, 0, 0], + }, + }, + }, + label: '', + cachedStats: {}, + }, + }; + + addAnnotation(element, annotation); + + const viewportIdsToRender = getViewportIdsWithToolToRender( + element, + this.getToolName() + ); + + this.editData = { + annotation, + viewportIdsToRender, + handleIndex: 1, + movingTextBox: false, + newAnnotation: true, + hasMoved: false, + }; + this._activateDraw(element); + + evt.preventDefault(); + + triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender); + + return annotation; + }; + + /** + * It returns if the canvas point is near the provided length annotation in the provided + * element or not. A proximity is passed to the function to determine the + * proximity of the point to the annotation in number of pixels. + * + * @param element - HTML Element + * @param annotation - Annotation + * @param canvasCoords - Canvas coordinates + * @param proximity - Proximity to tool to consider + * @returns Boolean, whether the canvas point is near tool + */ + isPointNearTool = ( + element: HTMLDivElement, + annotation: AngleAnnotation, + canvasCoords: Types.Point2, + proximity: number + ): boolean => { + const enabledElement = getEnabledElement(element); + const { viewport } = enabledElement; + const { data } = annotation; + const [point1, point2, point3, point4] = data.handles.points; + const canvasPoint1 = viewport.worldToCanvas(point1); + const canvasPoint2 = viewport.worldToCanvas(point2); + const canvasPoint3 = viewport.worldToCanvas(point3); + const canvasPoint4 = viewport.worldToCanvas(point4); + + const line1 = { + start: { + x: canvasPoint1[0], + y: canvasPoint1[1], + }, + end: { + x: canvasPoint2[0], + y: canvasPoint2[1], + }, + }; + + const line2 = { + start: { + x: canvasPoint3[0], + y: canvasPoint3[1], + }, + end: { + x: canvasPoint4[0], + y: canvasPoint4[1], + }, + }; + + const distanceToPoint = lineSegment.distanceToPoint( + [line1.start.x, line1.start.y], + [line1.end.x, line1.end.y], + [canvasCoords[0], canvasCoords[1]] + ); + + const distanceToPoint2 = lineSegment.distanceToPoint( + [line2.start.x, line2.start.y], + [line2.end.x, line2.end.y], + [canvasCoords[0], canvasCoords[1]] + ); + + if (distanceToPoint <= proximity || distanceToPoint2 <= proximity) { + return true; + } + + return false; + }; + + toolSelectedCallback = ( + evt: EventTypes.MouseDownEventType, + annotation: AngleAnnotation, + interactionType: InteractionTypes + ): void => { + const eventDetail = evt.detail; + const { element } = eventDetail; + + annotation.highlighted = true; + + const viewportIdsToRender = getViewportIdsWithToolToRender( + element, + this.getToolName() + ); + + this.editData = { + annotation, + viewportIdsToRender, + movingTextBox: false, + }; + + this._activateModify(element); + + hideElementCursor(element); + + const enabledElement = getEnabledElement(element); + const { renderingEngine } = enabledElement; + + triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender); + + evt.preventDefault(); + }; + + handleSelectedCallback( + evt: EventTypes.MouseDownEventType, + annotation: AngleAnnotation, + handle: ToolHandle, + interactionType = 'mouse' + ): void { + const eventDetail = evt.detail; + const { element } = eventDetail; + const { data } = annotation; + + annotation.highlighted = true; + + let movingTextBox = false; + let handleIndex; + + if ((handle as TextBoxHandle).worldPosition) { + movingTextBox = true; + } else { + handleIndex = data.handles.points.findIndex((p) => p === handle); + } + + // Find viewports to render on drag. + const viewportIdsToRender = getViewportIdsWithToolToRender( + element, + this.getToolName() + ); + + this.editData = { + annotation, + viewportIdsToRender, + handleIndex, + movingTextBox, + }; + this._activateModify(element); + + hideElementCursor(element); + + const enabledElement = getEnabledElement(element); + const { renderingEngine } = enabledElement; + + triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender); + + evt.preventDefault(); + } + + _mouseUpCallback = ( + evt: EventTypes.MouseUpEventType | EventTypes.MouseClickEventType + ) => { + const eventDetail = evt.detail; + const { element } = eventDetail; + + const { annotation, viewportIdsToRender, newAnnotation, hasMoved } = + this.editData; + + const { data } = annotation; + if (newAnnotation && !hasMoved) { + // when user starts the drawing by click, and moving the mouse, instead + // of click and drag + return; + } + + // If preventing new measurement means we are in the middle of an existing measurement + // we shouldn't deactivate modify or draw + if (this.angleStartedNotYetCompleted && data.handles.points.length < 4) { + resetElementCursor(element); + + // adds the first point of the second line + this.editData.handleIndex = data.handles.points.length; + return; + } + + this.angleStartedNotYetCompleted = false; + data.handles.activeHandleIndex = null; + + this._deactivateModify(element); + this._deactivateDraw(element); + resetElementCursor(element); + + const enabledElement = getEnabledElement(element); + const { renderingEngine } = enabledElement; + + if ( + this.isHandleOutsideImage && + this.configuration.preventHandleOutsideImage + ) { + removeAnnotation(annotation.annotationUID, element); + } + + triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender); + + if (newAnnotation) { + const eventType = Events.ANNOTATION_COMPLETED; + + const eventDetail: AnnotationCompletedEventDetail = { + annotation, + }; + + triggerEvent(eventTarget, eventType, eventDetail); + } + + this.editData = null; + this.isDrawing = false; + }; + + _mouseDragCallback = ( + evt: EventTypes.MouseDragEventType | EventTypes.MouseMoveEventType + ) => { + this.isDrawing = true; + const eventDetail = evt.detail; + const { element } = eventDetail; + + const { annotation, viewportIdsToRender, handleIndex, movingTextBox } = + this.editData; + const { data } = annotation; + + if (movingTextBox) { + // Drag mode - moving text box + const { deltaPoints } = eventDetail as EventTypes.MouseDragEventDetail; + const worldPosDelta = deltaPoints.world; + + const { textBox } = data.handles; + const { worldPosition } = textBox; + + worldPosition[0] += worldPosDelta[0]; + worldPosition[1] += worldPosDelta[1]; + worldPosition[2] += worldPosDelta[2]; + + textBox.hasMoved = true; + } else if (handleIndex === undefined) { + // Drag mode - moving handle + const { deltaPoints } = eventDetail as EventTypes.MouseDragEventDetail; + const worldPosDelta = deltaPoints.world; + + const points = data.handles.points; + + points.forEach((point) => { + point[0] += worldPosDelta[0]; + point[1] += worldPosDelta[1]; + point[2] += worldPosDelta[2]; + }); + annotation.invalidated = true; + } else { + // Move mode - after double click, and mouse move to draw + const { currentPoints } = eventDetail; + const worldPos = currentPoints.world; + + data.handles.points[handleIndex] = [...worldPos]; + annotation.invalidated = true; + } + + this.editData.hasMoved = true; + + const enabledElement = getEnabledElement(element); + const { renderingEngine } = enabledElement; + + triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender); + }; + + cancel = (element: HTMLDivElement) => { + // If it is mid-draw or mid-modify + if (this.isDrawing) { + this.isDrawing = false; + this._deactivateDraw(element); + this._deactivateModify(element); + resetElementCursor(element); + + const { annotation, viewportIdsToRender, newAnnotation } = this.editData; + const { data } = annotation; + + annotation.highlighted = false; + data.handles.activeHandleIndex = null; + + const enabledElement = getEnabledElement(element); + const { renderingEngine } = enabledElement; + + triggerAnnotationRenderForViewportIds( + renderingEngine, + viewportIdsToRender + ); + + if (newAnnotation) { + const eventType = Events.ANNOTATION_COMPLETED; + + const eventDetail: AnnotationCompletedEventDetail = { + annotation, + }; + + triggerEvent(eventTarget, eventType, eventDetail); + } + + this.editData = null; + this.angleStartedNotYetCompleted = false; + return annotation.annotationUID; + } + }; + + _activateModify = (element: HTMLDivElement) => { + state.isInteractingWithTool = true; + + element.addEventListener( + Events.MOUSE_UP, + this._mouseUpCallback as EventListener + ); + element.addEventListener( + Events.MOUSE_DRAG, + this._mouseDragCallback as EventListener + ); + element.addEventListener( + Events.MOUSE_CLICK, + this._mouseUpCallback as EventListener + ); + + // element.addEventListener(Events.TOUCH_END, this._mouseUpCallback) + // element.addEventListener(Events.TOUCH_DRAG, this._mouseDragCallback) + }; + + _deactivateModify = (element: HTMLDivElement) => { + state.isInteractingWithTool = false; + + element.removeEventListener( + Events.MOUSE_UP, + this._mouseUpCallback as EventListener + ); + element.removeEventListener( + Events.MOUSE_DRAG, + this._mouseDragCallback as EventListener + ); + element.removeEventListener( + Events.MOUSE_CLICK, + this._mouseUpCallback as EventListener + ); + + // element.removeEventListener(Events.TOUCH_END, this._mouseUpCallback) + // element.removeEventListener(Events.TOUCH_DRAG, this._mouseDragCallback) + }; + + _activateDraw = (element: HTMLDivElement) => { + state.isInteractingWithTool = true; + + element.addEventListener( + Events.MOUSE_UP, + this._mouseUpCallback as EventListener + ); + element.addEventListener( + Events.MOUSE_DRAG, + this._mouseDragCallback as EventListener + ); + element.addEventListener( + Events.MOUSE_MOVE, + this._mouseDragCallback as EventListener + ); + element.addEventListener( + Events.MOUSE_CLICK, + this._mouseUpCallback as EventListener + ); + + // element.addEventListener(Events.TOUCH_END, this._mouseUpCallback) + // element.addEventListener(Events.TOUCH_DRAG, this._mouseDragCallback) + }; + + _deactivateDraw = (element: HTMLDivElement) => { + state.isInteractingWithTool = false; + + element.removeEventListener( + Events.MOUSE_UP, + this._mouseUpCallback as EventListener + ); + element.removeEventListener( + Events.MOUSE_DRAG, + this._mouseDragCallback as EventListener + ); + element.removeEventListener( + Events.MOUSE_MOVE, + this._mouseDragCallback as EventListener + ); + element.removeEventListener( + Events.MOUSE_CLICK, + this._mouseUpCallback as EventListener + ); + + // element.removeEventListener(Events.TOUCH_END, this._mouseUpCallback) + // element.removeEventListener(Events.TOUCH_DRAG, this._mouseDragCallback) + }; + + /** + * it is used to draw the length annotation in each + * request animation frame. It calculates the updated cached statistics if + * data is invalidated and cache it. + * + * @param enabledElement - The Cornerstone's enabledElement. + * @param svgDrawingHelper - The svgDrawingHelper providing the context for drawing. + */ + renderAnnotation = ( + enabledElement: Types.IEnabledElement, + svgDrawingHelper: SVGDrawingHelper + ): boolean => { + let renderStatus = false; + + const { viewport } = enabledElement; + const { element } = viewport; + + let annotations = getAnnotations(element, this.getToolName()); + + // Todo: We don't need this anymore, filtering happens in triggerAnnotationRender + if (!annotations?.length) { + return renderStatus; + } + + annotations = this.filterInteractableAnnotationsForElement( + element, + annotations + ); + + if (!annotations?.length) { + return renderStatus; + } + + const targetId = this.getTargetId(viewport); + const renderingEngine = viewport.getRenderingEngine(); + + const styleSpecifier: StyleSpecifier = { + toolGroupId: this.toolGroupId, + toolName: this.getToolName(), + viewportId: enabledElement.viewport.id, + }; + + // Draw SVG + for (let i = 0; i < annotations.length; i++) { + const annotation = annotations[i] as AngleAnnotation; + const { annotationUID, data } = annotation; + const { points, activeHandleIndex } = data.handles; + + styleSpecifier.annotationUID = annotationUID; + + const lineWidth = this.getStyle('lineWidth', styleSpecifier, annotation); + const lineDash = this.getStyle('lineDash', styleSpecifier, annotation); + const color = this.getStyle('color', styleSpecifier, annotation); + + const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p)); + + // WE HAVE TO CACHE STATS BEFORE FETCHING TEXT + if (!data.cachedStats[targetId]) { + data.cachedStats[targetId] = { + angle: null, + }; + + this._calculateCachedStats(annotation, renderingEngine, enabledElement); + } else if (annotation.invalidated) { + this._throttledCalculateCachedStats( + annotation, + renderingEngine, + enabledElement + ); + } + + let activeHandleCanvasCoords; + + if ( + !isAnnotationLocked(annotation) && + !this.editData && + activeHandleIndex !== null + ) { + // Not locked or creating and hovering over handle, so render handle. + activeHandleCanvasCoords = [canvasCoordinates[activeHandleIndex]]; + } + + // If rendering engine has been destroyed while rendering + if (!viewport.getRenderingEngine()) { + console.warn('Rendering Engine has been destroyed'); + return renderStatus; + } + + if (activeHandleCanvasCoords) { + const handleGroupUID = '0'; + + drawHandlesSvg( + svgDrawingHelper, + annotationUID, + handleGroupUID, + canvasCoordinates, + { + color, + lineDash, + lineWidth, + } + ); + } + + let lineUID = '1'; + drawLineSvg( + svgDrawingHelper, + annotationUID, + lineUID, + canvasCoordinates[0], + canvasCoordinates[1], + { + color, + width: lineWidth, + lineDash, + } + ); + + renderStatus = true; + + // Don't add textBox until annotation has 4 anchor points + if (canvasCoordinates.length < 4) { + return renderStatus; + } + + lineUID = '2'; + + drawLineSvg( + svgDrawingHelper, + annotationUID, + lineUID, + canvasCoordinates[2], + canvasCoordinates[3], + { + color, + width: lineWidth, + lineDash, + } + ); + + lineUID = '3'; + const mid1 = midPoint2(canvasCoordinates[0], canvasCoordinates[1]); + const mid2 = midPoint2(canvasCoordinates[2], canvasCoordinates[3]); + drawLineSvg(svgDrawingHelper, annotationUID, lineUID, mid1, mid2, { + color, + lineWidth: '1', + lineDash: '1,4', + }); + + if (!data.cachedStats[targetId]?.angle) { + continue; + } + + const textLines = this._getTextLines(data, targetId); + + if (!data.handles.textBox.hasMoved) { + const canvasTextBoxCoords = getTextBoxCoordsCanvas(canvasCoordinates); + + data.handles.textBox.worldPosition = + viewport.canvasToWorld(canvasTextBoxCoords); + } + + const textBoxPosition = viewport.worldToCanvas( + data.handles.textBox.worldPosition + ); + + const textBoxUID = '1'; + const boundingBox = drawLinkedTextBoxSvg( + svgDrawingHelper, + annotationUID, + textBoxUID, + textLines, + textBoxPosition, + canvasCoordinates, + {}, + this.getLinkedTextBoxStyle(styleSpecifier, annotation) + ); + + const { x: left, y: top, width, height } = boundingBox; + + data.handles.textBox.worldBoundingBox = { + topLeft: viewport.canvasToWorld([left, top]), + topRight: viewport.canvasToWorld([left + width, top]), + bottomLeft: viewport.canvasToWorld([left, top + height]), + bottomRight: viewport.canvasToWorld([left + width, top + height]), + }; + } + + return renderStatus; + }; + + // text line for the current active angle annotation + _getTextLines(data, targetId) { + const cachedVolumeStats = data.cachedStats[targetId]; + const { angle } = cachedVolumeStats; + + if (angle === undefined) { + return; + } + + const textLines = [`${angle.toFixed(2)} ${String.fromCharCode(176)}`]; + + return textLines; + } + + _calculateCachedStats(annotation, renderingEngine, enabledElement) { + const data = annotation.data; + const { viewportId, renderingEngineId } = enabledElement; + + // Until we have all four anchors bail out + if (data.handles.points.length !== 4) { + return; + } + + const worldPos1 = data.handles.points[0]; + const worldPos2 = data.handles.points[1]; + const worldPos3 = data.handles.points[2]; + const worldPos4 = data.handles.points[3]; + + const { cachedStats } = data; + const targetIds = Object.keys(cachedStats); + + for (let i = 0; i < targetIds.length; i++) { + const targetId = targetIds[i]; + const angle = angleBetweenLines( + [worldPos1, worldPos2], + [worldPos3, worldPos4] + ); + + cachedStats[targetId] = { + angle, + }; + } + + annotation.invalidated = false; + + // Dispatching annotation modified + const eventType = Events.ANNOTATION_MODIFIED; + + const eventDetail: AnnotationModifiedEventDetail = { + annotation, + viewportId, + renderingEngineId, + }; + triggerEvent(eventTarget, eventType, eventDetail); + + return cachedStats; + } +} + +CobbAngleTool.toolName = 'CobbAngle'; +export default CobbAngleTool; diff --git a/packages/tools/src/tools/index.ts b/packages/tools/src/tools/index.ts index cfc9e9115f..3618da6f26 100644 --- a/packages/tools/src/tools/index.ts +++ b/packages/tools/src/tools/index.ts @@ -20,6 +20,7 @@ import EllipticalROITool from './annotation/EllipticalROITool'; import PlanarFreehandROITool from './annotation/PlanarFreehandROITool'; import ArrowAnnotateTool from './annotation/ArrowAnnotateTool'; import AngleTool from './annotation/AngleTool'; +import CobbAngleTool from './annotation/CobbAngleTool'; import ReferenceCursors from './ReferenceCursors'; import ReferenceLines from './ReferenceLinesTool'; @@ -60,6 +61,7 @@ export { PlanarFreehandROITool, ArrowAnnotateTool, AngleTool, + CobbAngleTool, ReferenceCursors, // Segmentations Display SegmentationDisplayTool, diff --git a/packages/tools/src/utilities/math/midPoint.ts b/packages/tools/src/utilities/math/midPoint.ts new file mode 100644 index 0000000000..b5b9784572 --- /dev/null +++ b/packages/tools/src/utilities/math/midPoint.ts @@ -0,0 +1,24 @@ +import { Types } from '@cornerstonejs/core'; + +/** + * Return the midpoint (think average) of all the provided points. + */ +const midPoint = ( + ...args: (Types.Point2 | Types.Point3)[] +): Types.Point2 | Types.Point3 => { + const ret = + args[0].length === 2 ? [0, 0] : [0, 0, 0]; + const len = args.length; + for (const arg of args) { + ret[0] += arg[0] / len; + ret[1] += arg[1] / len; + if (ret.length === 3) ret[2] += arg[2] / len; + } + return ret; +}; + +const midPoint2 = midPoint as (...args: Types.Point2[]) => Types.Point2; + +export default midPoint; + +export { midPoint2 }; diff --git a/yarn.lock b/yarn.lock index 7ca7502b8d..c94e2e08ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -242,13 +242,6 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" - integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== - dependencies: - "@babel/highlight" "^7.10.4" - "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" @@ -908,7 +901,7 @@ "@babel/traverse" "^7.20.7" "@babel/types" "^7.20.7" -"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.7": +"@babel/highlight@^7.16.7": version "7.17.12" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351" integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg== @@ -3063,21 +3056,6 @@ url-loader "^4.1.1" webpack "^5.73.0" -"@eslint/eslintrc@^0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" - integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== - dependencies: - ajv "^6.12.4" - debug "^4.1.1" - espree "^7.3.0" - globals "^13.9.0" - ignore "^4.0.6" - import-fresh "^3.2.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - strip-json-comments "^3.1.1" - "@eslint/eslintrc@^1.4.1": version "1.4.1" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" @@ -3119,21 +3097,12 @@ debug "^4.1.1" minimatch "^3.0.5" -"@humanwhocodes/config-array@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" - integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== - dependencies: - "@humanwhocodes/object-schema" "^1.2.0" - debug "^4.1.1" - minimatch "^3.0.4" - "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^1.2.0", "@humanwhocodes/object-schema@^1.2.1": +"@humanwhocodes/object-schema@^1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== @@ -4157,26 +4126,26 @@ resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== -"@microsoft/api-extractor-model@7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.15.4.tgz#59fc1e00530b7a604c719221a59dc265c76e9bc5" - integrity sha512-9bIXQKKQr5jAH1c9atXrukr4ua30fhqxMwWIOOjEnexPBPu3nhy9lC4/GpE0kPUp1Al3wSXgFnOEGzEH+HFz+w== - dependencies: - "@microsoft/tsdoc" "0.13.2" - "@microsoft/tsdoc-config" "~0.15.2" - "@rushstack/node-core-library" "3.45.1" - -"@microsoft/api-extractor@7.19.5": - version "7.19.5" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.19.5.tgz#85b2404135a4158864d448fde8991ef7dc39b6a7" - integrity sha512-ra5r8P7PocOpemrZRccI3Tf1+wukI0gT6ncRB448QSxSYlmqKuvez95YUSYPwHIN/ztKL0cn5PfMOauU1lZfGQ== - dependencies: - "@microsoft/api-extractor-model" "7.15.4" - "@microsoft/tsdoc" "0.13.2" - "@microsoft/tsdoc-config" "~0.15.2" - "@rushstack/node-core-library" "3.45.1" - "@rushstack/rig-package" "0.3.8" - "@rushstack/ts-command-line" "4.10.7" +"@microsoft/api-extractor-model@7.16.2": + version "7.16.2" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.16.2.tgz#58504311bba3e0f8375b49c5c8b92ffc7e576845" + integrity sha512-hnqKsG89iIiQlLDXasxFw8QR0LwakPVXejNVmlGpFL008R+IExgc1f+tBrUAm1in6Oq76t7Ea0TFhER56Qfhaw== + dependencies: + "@microsoft/tsdoc" "0.14.1" + "@microsoft/tsdoc-config" "~0.16.1" + "@rushstack/node-core-library" "3.45.2" + +"@microsoft/api-extractor@7.21.3": + version "7.21.3" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.21.3.tgz#ae47c7c7dfe96263439257b6f2d8f3184a2144d6" + integrity sha512-ZQwuu5QbJq/TMDGr8NGmt4p/kcceaQAhQYQ4DszwNKDaCi/IhGVtO2zRcjSt8DEI2XD40s/CAOPYyF2C+Y99Ow== + dependencies: + "@microsoft/api-extractor-model" "7.16.2" + "@microsoft/tsdoc" "0.14.1" + "@microsoft/tsdoc-config" "~0.16.1" + "@rushstack/node-core-library" "3.45.2" + "@rushstack/rig-package" "0.3.9" + "@rushstack/ts-command-line" "4.10.8" colors "~1.2.1" lodash "~4.17.15" resolve "~1.17.0" @@ -4194,26 +4163,26 @@ jju "~1.4.0" resolve "~1.19.0" -"@microsoft/tsdoc-config@~0.15.2": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz#eb353c93f3b62ab74bdc9ab6f4a82bcf80140f14" - integrity sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA== +"@microsoft/tsdoc-config@~0.16.1": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz#b786bb4ead00d54f53839a458ce626c8548d3adf" + integrity sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw== dependencies: - "@microsoft/tsdoc" "0.13.2" + "@microsoft/tsdoc" "0.14.2" ajv "~6.12.6" jju "~1.4.0" resolve "~1.19.0" -"@microsoft/tsdoc@0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz#3b0efb6d3903bd49edb073696f60e90df08efb26" - integrity sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg== - "@microsoft/tsdoc@0.14.1": version "0.14.1" resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.14.1.tgz#155ef21065427901994e765da8a0ba0eaae8b8bd" integrity sha512-6Wci+Tp3CgPt/B9B0a3J4s3yMgLNSku6w5TV6mN+61C71UqsRBv2FUibBf3tPGlNxebgPHMEUzKpb1ggE8KCKw== +"@microsoft/tsdoc@0.14.2": + version "0.14.2" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz#c3ec604a0b54b9a9b87e9735dfc59e1a5da6a5fb" + integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug== + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -5007,10 +4976,10 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@rushstack/node-core-library@3.45.1": - version "3.45.1" - resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.45.1.tgz#787361b61a48d616eb4b059641721a3dc138f001" - integrity sha512-BwdssTNe007DNjDBxJgInHg8ePytIPyT0La7ZZSQZF9+rSkT42AygXPGvbGsyFfEntjr4X37zZSJI7yGzL16cQ== +"@rushstack/node-core-library@3.45.2": + version "3.45.2" + resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.45.2.tgz#68fc89c5bea4007359fa4ff203bf3eca27037f40" + integrity sha512-MJKdB6mxOoIkks3htGVCo7aiTzllm2I6Xua+KbTSb0cp7rBp8gTCOF/4d8R4HFMwpRdEdwzKgqMM6k9rAK73iw== dependencies: "@types/node" "12.20.24" colors "~1.2.1" @@ -5022,18 +4991,18 @@ timsort "~0.3.0" z-schema "~5.0.2" -"@rushstack/rig-package@0.3.8": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@rushstack/rig-package/-/rig-package-0.3.8.tgz#0e8b2fbc7a35d96f6ccf34e773f7c1adb1524296" - integrity sha512-MDWg1xovea99PWloSiYMjFcCLsrdjFtYt6aOyHNs5ojn5mxrzR6U9F83hvbQjTWnKPMvZtr0vcek+4n+OQOp3Q== +"@rushstack/rig-package@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@rushstack/rig-package/-/rig-package-0.3.9.tgz#5e10ada5a8348f886b6ebe3eed436492d6ccf70c" + integrity sha512-z3Oxpfb4n9mGXwseX+ifpkmUf9B8Fy8oieVwg8eFgpCbzllkgOwEiwLKEnRWVQ8owFcd46NCKz+7ICH35CRsAw== dependencies: resolve "~1.17.0" strip-json-comments "~3.1.1" -"@rushstack/ts-command-line@4.10.7": - version "4.10.7" - resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-4.10.7.tgz#21e3757a756cbd4f7eeab8f89ec028a64d980efc" - integrity sha512-CjS+DfNXUSO5Ab2wD1GBGtUTnB02OglRWGqfaTcac9Jn45V5MeUOsq/wA8wEeS5Y/3TZ2P1k+IWdVDiuOFP9Og== +"@rushstack/ts-command-line@4.10.8": + version "4.10.8" + resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-4.10.8.tgz#f4bec690e7f4838e6f91028d8a557e67c3a75f68" + integrity sha512-G7CQYY/m3aZU5fVxbebv35yDeua7sSumrDAB2pJp0d60ZEsxGkUQW8771CeMcGWwSKqT9PxPzKpmIakiWv54sA== dependencies: "@types/argparse" "1.0.38" argparse "~1.0.9" @@ -5575,7 +5544,7 @@ resolved "https://registry.yarnpkg.com/@types/json-buffer/-/json-buffer-3.0.0.tgz#85c1ff0f0948fc159810d4b5be35bf8c20875f64" integrity sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ== -"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== @@ -5781,6 +5750,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.9.tgz#152c6c20a7688c30b967ec1841d31ace569863fc" integrity sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ== +"@types/semver@^7.3.12": + version "7.3.13" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" + integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== + "@types/serve-index@^1.9.1": version "1.9.1" resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" @@ -5884,49 +5858,48 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" - integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== +"@typescript-eslint/eslint-plugin@^5.48.1": + version "5.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.49.0.tgz#d0b4556f0792194bf0c2fb297897efa321492389" + integrity sha512-IhxabIpcf++TBaBa1h7jtOWyon80SXPRLDq0dVz5SLFC/eW6tofkw/O7Ar3lkx5z5U6wzbKDrl2larprp5kk5Q== dependencies: - "@typescript-eslint/experimental-utils" "4.33.0" - "@typescript-eslint/scope-manager" "4.33.0" - debug "^4.3.1" - functional-red-black-tree "^1.0.1" - ignore "^5.1.8" - regexpp "^3.1.0" - semver "^7.3.5" + "@typescript-eslint/scope-manager" "5.49.0" + "@typescript-eslint/type-utils" "5.49.0" + "@typescript-eslint/utils" "5.49.0" + debug "^4.3.4" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + regexpp "^3.2.0" + semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" - integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== +"@typescript-eslint/parser@^5.48.1": + version "5.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.49.0.tgz#d699734b2f20e16351e117417d34a2bc9d7c4b90" + integrity sha512-veDlZN9mUhGqU31Qiv2qEp+XrJj5fgZpJ8PW30sHU+j/8/e5ruAhLaVDAeznS7A7i4ucb/s8IozpDtt9NqCkZg== dependencies: - "@types/json-schema" "^7.0.7" - "@typescript-eslint/scope-manager" "4.33.0" - "@typescript-eslint/types" "4.33.0" - "@typescript-eslint/typescript-estree" "4.33.0" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" + "@typescript-eslint/scope-manager" "5.49.0" + "@typescript-eslint/types" "5.49.0" + "@typescript-eslint/typescript-estree" "5.49.0" + debug "^4.3.4" -"@typescript-eslint/parser@^4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899" - integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA== +"@typescript-eslint/scope-manager@5.49.0": + version "5.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.49.0.tgz#81b5d899cdae446c26ddf18bd47a2f5484a8af3e" + integrity sha512-clpROBOiMIzpbWNxCe1xDK14uPZh35u4QaZO1GddilEzoCLAEz4szb51rBpdgurs5k2YzPtJeTEN3qVbG+LRUQ== dependencies: - "@typescript-eslint/scope-manager" "4.33.0" - "@typescript-eslint/types" "4.33.0" - "@typescript-eslint/typescript-estree" "4.33.0" - debug "^4.3.1" + "@typescript-eslint/types" "5.49.0" + "@typescript-eslint/visitor-keys" "5.49.0" -"@typescript-eslint/scope-manager@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" - integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== +"@typescript-eslint/type-utils@5.49.0": + version "5.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.49.0.tgz#8d5dcc8d422881e2ccf4ebdc6b1d4cc61aa64125" + integrity sha512-eUgLTYq0tR0FGU5g1YHm4rt5H/+V2IPVkP0cBmbhRyEmyGe4XvJ2YJ6sYTmONfjmdMqyMLad7SB8GvblbeESZA== dependencies: - "@typescript-eslint/types" "4.33.0" - "@typescript-eslint/visitor-keys" "4.33.0" + "@typescript-eslint/typescript-estree" "5.49.0" + "@typescript-eslint/utils" "5.49.0" + debug "^4.3.4" + tsutils "^3.21.0" "@typescript-eslint/types@4.33.0": version "4.33.0" @@ -5938,7 +5911,25 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.27.0.tgz#c3f44b9dda6177a9554f94a74745ca495ba9c001" integrity sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A== -"@typescript-eslint/typescript-estree@4.33.0", "@typescript-eslint/typescript-estree@^4.33.0": +"@typescript-eslint/types@5.49.0": + version "5.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.49.0.tgz#ad66766cb36ca1c89fcb6ac8b87ec2e6dac435c3" + integrity sha512-7If46kusG+sSnEpu0yOz2xFv5nRz158nzEXnJFCGVEHWnuzolXKwrH5Bsf9zsNlOQkyZuk0BZKKoJQI+1JPBBg== + +"@typescript-eslint/typescript-estree@5.49.0": + version "5.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.49.0.tgz#ebd6294c0ea97891fce6af536048181e23d729c8" + integrity sha512-PBdx+V7deZT/3GjNYPVQv1Nc0U46dAHbIuOG8AZ3on3vuEKiPDwFE/lG1snN2eUB9IhF7EyF7K1hmTcLztNIsA== + dependencies: + "@typescript-eslint/types" "5.49.0" + "@typescript-eslint/visitor-keys" "5.49.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/typescript-estree@^4.33.0": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== @@ -5964,6 +5955,20 @@ semver "^7.3.7" tsutils "^3.21.0" +"@typescript-eslint/utils@5.49.0": + version "5.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.49.0.tgz#1c07923bc55ff7834dfcde487fff8d8624a87b32" + integrity sha512-cPJue/4Si25FViIb74sHCLtM4nTSBXtLx1d3/QT6mirQ/c65bV8arBEebBJJizfq8W2YyMoPI/WWPFWitmNqnQ== + dependencies: + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.49.0" + "@typescript-eslint/types" "5.49.0" + "@typescript-eslint/typescript-estree" "5.49.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + semver "^7.3.7" + "@typescript-eslint/visitor-keys@4.33.0": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" @@ -5980,6 +5985,14 @@ "@typescript-eslint/types" "5.27.0" eslint-visitor-keys "^3.3.0" +"@typescript-eslint/visitor-keys@5.49.0": + version "5.49.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.49.0.tgz#2561c4da3f235f5c852759bf6c5faec7524f90fe" + integrity sha512-v9jBMjpNWyn8B6k/Mjt6VbUS4J1GvUlR4x3Y+ibnP1z7y7V4n0WRz+50DY6+Myj0UaXVSuUlHohO+eZ8IJEnkg== + dependencies: + "@typescript-eslint/types" "5.49.0" + eslint-visitor-keys "^3.3.0" + "@vercel/nft@^0.17.0": version "0.17.5" resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.17.5.tgz#eab288a3786b8bd6fc08c0ef0b70d162984d1643" @@ -6213,7 +6226,7 @@ acorn-import-assertions@^1.7.6: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== -acorn-jsx@^5.2.0, acorn-jsx@^5.3.1, acorn-jsx@^5.3.2: +acorn-jsx@^5.2.0, acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== @@ -6233,7 +6246,7 @@ acorn@^5.7.3: resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== -acorn@^7.1.0, acorn@^7.1.1, acorn@^7.4.0: +acorn@^7.1.0, acorn@^7.1.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== @@ -10412,7 +10425,7 @@ enhanced-resolve@^5.10.0: graceful-fs "^4.2.4" tapable "^2.2.0" -enquirer@^2.3.5, enquirer@^2.3.6: +enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -10730,11 +10743,6 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^8.3.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" - integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== - eslint-config-prettier@^8.5.0: version "8.6.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz#dec1d29ab728f4fa63061774e1672ac4e363d207" @@ -10824,13 +10832,6 @@ eslint-scope@^7.1.1: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - dependencies: - eslint-visitor-keys "^1.1.0" - eslint-utils@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" @@ -10838,11 +10839,6 @@ eslint-utils@^3.0.0: dependencies: eslint-visitor-keys "^2.0.0" -eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" @@ -10865,52 +10861,6 @@ eslint-webpack-plugin@^2.6.0: normalize-path "^3.0.0" schema-utils "^3.1.1" -eslint@7.32.0: - version "7.32.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" - integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== - dependencies: - "@babel/code-frame" "7.12.11" - "@eslint/eslintrc" "^0.4.3" - "@humanwhocodes/config-array" "^0.5.0" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.0.1" - doctrine "^3.0.0" - enquirer "^2.3.5" - escape-string-regexp "^4.0.0" - eslint-scope "^5.1.1" - eslint-utils "^2.1.0" - eslint-visitor-keys "^2.0.0" - espree "^7.3.1" - esquery "^1.4.0" - esutils "^2.0.2" - 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.6.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.0.4" - natural-compare "^1.4.0" - optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.1.0" - semver "^7.2.1" - strip-ansi "^6.0.0" - strip-json-comments "^3.1.0" - table "^6.0.9" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - eslint@^8.17.0: version "8.32.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.32.0.tgz#d9690056bb6f1a302bd991e7090f5b68fbaea861" @@ -10956,15 +10906,6 @@ eslint@^8.17.0: strip-json-comments "^3.1.0" text-table "^0.2.0" -espree@^7.3.0, espree@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" - integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== - dependencies: - acorn "^7.4.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^1.3.0" - espree@^9.4.0: version "9.4.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" @@ -11940,11 +11881,6 @@ function.prototype.name@^1.1.5: es-abstract "^1.19.0" functions-have-names "^1.2.2" -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== - functions-have-names@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" @@ -12308,13 +12244,6 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" -globals@^13.6.0, globals@^13.9.0: - version "13.15.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" - integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== - dependencies: - type-fest "^0.20.2" - globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -13129,7 +13058,7 @@ ignore@^3.3.5: resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== -ignore@^4.0.3, ignore@^4.0.6: +ignore@^4.0.3: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== @@ -16558,6 +16487,11 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -19075,12 +19009,7 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.5.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" - integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== - -prettier@^2.6.2: +prettier@^2.6.2, prettier@^2.8.3: version "2.8.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.3.tgz#ab697b1d3dd46fb4626fbe2f543afe0cc98d8632" integrity sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw== @@ -19157,7 +19086,7 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -progress@2.0.3, progress@^2.0.0: +progress@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -19962,7 +19891,7 @@ regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" -regexpp@^3.1.0, regexpp@^3.2.0: +regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== @@ -20709,7 +20638,7 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@~7.3.0: +semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@~7.3.0: version "7.3.7" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== @@ -21930,7 +21859,7 @@ synchronous-promise@^2.0.6: resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.17.tgz#38901319632f946c982152586f2caf8ddc25c032" integrity sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g== -table@^6.0.9, table@^6.6.0: +table@^6.6.0: version "6.8.0" resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca" integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA== @@ -22166,7 +22095,7 @@ timed-out@^4.0.1: timsort@^0.3.0, timsort@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= + integrity sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A== tiny-invariant@^1.0.2: version "1.2.0" @@ -22998,7 +22927,7 @@ uuid@^9.0.0: resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== -v8-compile-cache@^2.0.3, v8-compile-cache@^2.3.0: +v8-compile-cache@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==