diff --git a/.gitignore b/.gitignore index a4e7175e..786e5933 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ coverage npm-debug.log node_modules debug.log -types \ No newline at end of file +types diff --git a/.npmignore b/.npmignore index 6f9435ea..130f1344 100644 --- a/.npmignore +++ b/.npmignore @@ -2,4 +2,4 @@ **/tsconfig.json **/webpack.config.js node_modules -src \ No newline at end of file +src diff --git a/README.md b/README.md index 67b7812e..78866d01 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ +README.md is a mess, need to start from manifesto's and re-do! + # manifesto [![Build Status](https://github.com/IIIF-Commons/manifesto/actions/workflows/build-test.yml/badge.svg?branch=main)](https://github.com/IIIF-Commons/manifesto/actions/workflows/build-test.yml) -IIIF Presentation API client and server utility library. +Forked from [IIIF-Commons/manifesto](https://github.com/IIIF-Commons/manifesto). - npm install manifesto.js --save +Goal of implementing the [Draft API](https://github.com/IIIF/3d/blob/main/temp-draft-4.md) under development by the [IIIF 3D Technical Study Group](https://github.com/IIIF/3d/). > [!NOTE] > 3D extensions to the manifesto.js library are under development in a fork [IIIF-Commons/manifesto-3d](https://github.com/IIIF-Commons/manifesto-3d). @@ -15,21 +17,61 @@ IIIF Presentation API client and server utility library. ### Documentation -https://iiif-commons.github.io/manifesto/ +[Manifesto-3D.js](https://iiif-commons.github.io/manifesto-3d/) + +### Loading through package manager + + npm install manifesto-3d.js --save + +### Demonstration Projects +[Example manifests](https://github.com/IIIF/3d/tree/main/manifests) conforming to the [Draft API](https://github.com/IIIF/3d/blob/main/temp-draft-4.md) . + +[Prototype Viewers](https://github.com/IIIF/3d/issues/28) rendering the example manifests. +- [Three-JS based viewer](https://codesandbox.io/p/github/JulieWinchester/iiif-threejs-demo) +- [X3D/X3DOM based viewer](https://codesandbox.io/p/github/vincentmarchetti/iiif-x3dom-demo/main) +- [Smithsonian Voyager](https://codesandbox.io/p/sandbox/voyager-annotations-demo-forked-l83l6w) + +### ChangeLog + +From start point of the version distributed from [JulieWinchester/manifesto](https://github.com/JulieWinchester/manifesto/tree/3dtsg-dev-dist) + +#### To package.json version 4.3.0-draft3dapi.0.1.0 +distributed from [vincentmarchetti/manifesto#3dtsg-main]() there were these changes: + +1. This test is no longer useful for the Target of an Annotation: + + if ( typeof(target) === "string" ){ + // handle case where target is a Scene + } + + Draft manifest [ 3_lights/direction_light_transform ]( https://github.com/IIIF/3d/blob/main/manifests/3_lights/direction_light_transform_rotate.json ) uses two ways of encoding the value of a target property for an Annotation: with a json string value of the IRI, or with an object with `id` property of the IRI for the Scene. To avoid exponential expansion of if-else code when combined with target property which can also be `SpecificResource` resources, the parsing code was changed so tha the value returned from `getTarget()` is always an object. + + Since the Target property will always be an object referencing a `Scene`, or a `SpecificResource` whose `source` property is a `Scene`, the code for handling either would be + + if (target.isSpecificResource){ + // handle a SpecificResource, with selector property + // and whose source property is the Scene + } + else{ + // handle a Scene directly + } + +2. Annotation.getBody3D() is deprecated. + + The `Annotation.getBody()` from the Presentation 3 code has been extended to support the resources that can be included in a 3d Annotation body property. An important difference is that the `getBody()` function returns an array of objects, while the `getBody3D()` returns a single object. The deprecated function `getBody3D()` should be replaced with `getBody()[0]` + +#### To package.json version 4.3.0-draft3dapi.0.2.0 + +1. Fixed a bug that occurred in determining the 'source' property of a SpecificResource resource that is the "target" property of an Annotation. This bug escaped detection previously because in the 3D case this 'source' property has always been a Scene resource, and the value is not needed for visualization. + +#### To package.json version 4.3.0-draft3dapi.0.3.0 + +1. Added isSpecificResource and isAnnotationBody properties to the SpecificResource and AnnotationBody classes, in response to developer suggestion. (Slack, Apr 24 2024) -### Developer Setup +#### To package.json version 4.3.0-draft3dapi.0.4.0 - git clone https://github.com/iiif-commons/manifesto.git - npm install - npm build - npm test +1. Implemented Perspective Camera properties in the Camera class. -### Publishing Package +#### To package.json version 4.3.0-draft3dapi.0.5.0 - git checkout main - npm version patch - npm run docs - git add . - git commit -m "Release v1.2.3" - git tag v1.2.3 - git push origin main v1.2.3 +1. Implement lookAt property of Camera class and of Light class. diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..a29188c9 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,9 @@ +# Release + +To create a new release on NPM you need to create a [release](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release) on Github and the [release.yml](.github/workflows/release.yml) action will then deploy a release on NPM. + +This requires NPM_TOKEN to be setup as a repository secret. This will update the package at: + +https://www.npmjs.com/package/@iiif/3d-manifesto-dev + +To update the version number in NPM you will also need to update the version number in [package.json](package.json). \ No newline at end of file diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css index eaa8dacc..0b09ad48 100644 --- a/docs/assets/highlight.css +++ b/docs/assets/highlight.css @@ -1,16 +1,20 @@ :root { - --light-hl-0: #000000; - --dark-hl-0: #D4D4D4; - --light-hl-1: #098658; - --dark-hl-1: #B5CEA8; - --light-hl-2: #795E26; - --dark-hl-2: #DCDCAA; - --light-hl-3: #001080; - --dark-hl-3: #9CDCFE; - --light-hl-4: #0000FF; - --dark-hl-4: #569CD6; - --light-hl-5: #A31515; - --dark-hl-5: #CE9178; + --light-hl-0: #0000FF; + --dark-hl-0: #569CD6; + --light-hl-1: #000000; + --dark-hl-1: #D4D4D4; + --light-hl-2: #001080; + --dark-hl-2: #9CDCFE; + --light-hl-3: #795E26; + --dark-hl-3: #DCDCAA; + --light-hl-4: #008000; + --dark-hl-4: #6A9955; + --light-hl-5: #098658; + --dark-hl-5: #B5CEA8; + --light-hl-6: #267F99; + --dark-hl-6: #4EC9B0; + --light-hl-7: #A31515; + --dark-hl-7: #CE9178; --light-code-background: #FFFFFF; --dark-code-background: #1E1E1E; } @@ -22,6 +26,8 @@ --hl-3: var(--light-hl-3); --hl-4: var(--light-hl-4); --hl-5: var(--light-hl-5); + --hl-6: var(--light-hl-6); + --hl-7: var(--light-hl-7); --code-background: var(--light-code-background); } } @@ -32,6 +38,8 @@ --hl-3: var(--dark-hl-3); --hl-4: var(--dark-hl-4); --hl-5: var(--dark-hl-5); + --hl-6: var(--dark-hl-6); + --hl-7: var(--dark-hl-7); --code-background: var(--dark-code-background); } } @@ -42,6 +50,8 @@ --hl-3: var(--light-hl-3); --hl-4: var(--light-hl-4); --hl-5: var(--light-hl-5); + --hl-6: var(--light-hl-6); + --hl-7: var(--light-hl-7); --code-background: var(--light-code-background); } @@ -52,6 +62,8 @@ --hl-3: var(--dark-hl-3); --hl-4: var(--dark-hl-4); --hl-5: var(--dark-hl-5); + --hl-6: var(--dark-hl-6); + --hl-7: var(--dark-hl-7); --code-background: var(--dark-code-background); } @@ -61,4 +73,6 @@ .hl-3 { color: var(--hl-3); } .hl-4 { color: var(--hl-4); } .hl-5 { color: var(--hl-5); } +.hl-6 { color: var(--hl-6); } +.hl-7 { color: var(--hl-7); } pre, code { background: var(--code-background); } diff --git a/docs/classes/AnnotationBodyParser.html b/docs/classes/AnnotationBodyParser.html new file mode 100644 index 00000000..fd67daa2 --- /dev/null +++ b/docs/classes/AnnotationBodyParser.html @@ -0,0 +1,3 @@ +AnnotationBodyParser | manifesto
manifesto
    Preparing search index...

    Class AnnotationBodyParser

    Index

    Constructors

    Methods

    Constructors

    Methods

    diff --git a/docs/classes/Camera.html b/docs/classes/Camera.html new file mode 100644 index 00000000..39b871d7 --- /dev/null +++ b/docs/classes/Camera.html @@ -0,0 +1,102 @@ +Camera | manifesto
    manifesto
      Preparing search index...

      Class Camera

      With the 3D extensions to the IIIF Presentation API the name of this +class is misleading, but for now is being retained for the sake backward +compatibility with earlier manifesto code and tests.

      +

      The 3D extensions allow that the body property of an annotation can be +a light, camera, or model, or a SpecificResource object wrapping a light, camera, +or model. +*

      +

      Hierarchy (View Summary)

      Index

      Constructors

      Properties

      __jsonld: any
      context: string
      externalResource: IExternalResource
      id: string

      Accessors

      • get Far(): undefined | number

        Far plane value of the camera. +*

        +

        Returns undefined | number

      • get FieldOfView(): undefined | number

        Full angular size of perspective viewport in vertical direction. +Angular unit is degrees +*

        +

        Returns undefined | number

      • get Near(): undefined | number

        Near plane value of the camera. +*

        +

        Returns undefined | number

      • get ViewHeight(): undefined | number

        Returns undefined | number

      Methods

      • Returns undefined | number

        the far plane value, i.e. the maximum distance from the camera at +which something in the space must exist in order to be viewed by the camera. +*

        +
      • Returns undefined | number

        full angular size of perspective viewport in vertical direction. +Angular unit is degrees +*

        +
      • returns the PropertyValue which in turn allows a language-specific string +encoded in the json as the "label" property

        +

        Returns PropertyValue

        var label = manifest.getLabel().getValue(); // returns the string for default locale
        +
        + +
        var label = manifest.getLabel().getValue(locale); // locale a string , examples
        // would be "fr", "en-US", +
        + +
      • Returns undefined | number

        the near plane value, i.e. the minimum distance from the camera at +which something in the space must exist in order to be viewed by the camera. +*

        +
      • A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier

        +

        If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.

        +
          +
        • +
        +

        Parameters

        • name: string

        Returns any

      • Returns undefined | number

        full linear size of orthographic viewport in vertical direction. +linear unit is Scene global unit of measure

        +

        Name of this property was originally Height, has been changed +at this revision to ViewHeight: +See issues at https://github.com/IIIF/api/issues/2289 +*

        +
      diff --git a/docs/classes/Color.html b/docs/classes/Color.html new file mode 100644 index 00000000..f2251d67 --- /dev/null +++ b/docs/classes/Color.html @@ -0,0 +1,19 @@ +Color | manifesto
      manifesto
        Preparing search index...

        Class Color

        class structure with red, green, blue values in 0-255 range +Uses the color-string +library for conversion from and to string representations of color.

        +
        Index

        Constructors

        Properties

        Accessors

        Methods

        Constructors

        • Parameters

          • rgbValue: number[]

            Array of three 0-255 integers for r,g,b value. Ex: [255.0,0] for red

            +

          Returns Color

        Properties

        value: number[]

        Array of 3 integers in range 0-255

        +

        Accessors

        • get blue(): number

          Returns number

          0 to 255 value of blue color component

          +
        • get CSS(): string

          Returns string

          hex string (as for CSS ) representation of r,g,b components

          +
        • get green(): number

          Returns number

          0 to 255 value of green color component

          +
        • get red(): number

          Returns number

          0 to 255 value of red color component

          +

        Methods

        • Parameters

          • cssTerm: string

            hex representtion of color as used in CSS. Ex "#FF0000" as red

            +

          Returns Color

          Color instance.

          +
        diff --git a/docs/classes/LanguageMap.html b/docs/classes/LanguageMap.html index 7c207551..f2f4e9f6 100644 --- a/docs/classes/LanguageMap.html +++ b/docs/classes/LanguageMap.html @@ -150,8 +150,8 @@ This method mutates the array and returns a reference to the same array.

        Parameters

        Returns this

        • Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.

          diff --git a/docs/classes/RotateTransform.html b/docs/classes/RotateTransform.html new file mode 100644 index 00000000..ab72f7c6 --- /dev/null +++ b/docs/classes/RotateTransform.html @@ -0,0 +1,31 @@ +RotateTransform | manifesto
          manifesto
            Preparing search index...

            Class RotateTransform

            Hierarchy (View Summary)

            Index

            Constructors

            Properties

            __jsonld: any
            context: string
            id: string
            isRotateTransform: undefined | boolean
            isScaleTransform: undefined | boolean
            isTransform: boolean = true
            isTranslateTransform: undefined | boolean

            Accessors

            • get Rotation(): object

              accessor Rotation is an object with x,y,z attributes whose values are +a counter-clockwise rotation in degrees about the fixed coordinate +system axes.

              +

              Returns object

            Methods

            • A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier

              +

              If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.

              +
                +
              • +
              +

              Parameters

              • name: string

              Returns any

            • Returns an object with x,y,z attributes whose values are +a counter-clockwise rotation in degrees about the fixed coordinate +system axes.

              +

              Returns object

              object

              +
            diff --git a/docs/classes/ScaleTransform.html b/docs/classes/ScaleTransform.html new file mode 100644 index 00000000..5d906470 --- /dev/null +++ b/docs/classes/ScaleTransform.html @@ -0,0 +1,23 @@ +ScaleTransform | manifesto
            manifesto
              Preparing search index...

              Class ScaleTransform

              Hierarchy (View Summary)

              Index

              Constructors

              Properties

              __jsonld: any
              context: string
              id: string
              isRotateTransform: undefined | boolean
              isScaleTransform: undefined | boolean
              isTransform: boolean = true
              isTranslateTransform: undefined | boolean

              Methods

              • A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier

                +

                If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.

                +
                  +
                • +
                +

                Parameters

                • name: string

                Returns any

              diff --git a/docs/classes/Scene.html b/docs/classes/Scene.html new file mode 100644 index 00000000..960fce92 --- /dev/null +++ b/docs/classes/Scene.html @@ -0,0 +1,51 @@ +Scene | manifesto
              manifesto
                Preparing search index...

                Class Scene

                Hierarchy (View Summary)

                Index

                Constructors

                Properties

                __jsonld: any
                context: string
                externalResource: IExternalResource
                id: string

                Accessors

                Methods

                • returns the PropertyValue which in turn allows a language-specific string +encoded in the json as the "label" property

                  +

                  Returns PropertyValue

                  var label = manifest.getLabel().getValue(); // returns the string for default locale
                  +
                  + +
                  var label = manifest.getLabel().getValue(locale); // locale a string , examples
                  // would be "fr", "en-US", +
                  + +
                • A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier

                  +

                  If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.

                  +
                    +
                  • +
                  +

                  Parameters

                  • name: string

                  Returns any

                diff --git a/docs/classes/SpecificResource.html b/docs/classes/SpecificResource.html new file mode 100644 index 00000000..d6e669b0 --- /dev/null +++ b/docs/classes/SpecificResource.html @@ -0,0 +1,61 @@ +SpecificResource | manifesto
                manifesto
                  Preparing search index...

                  Class SpecificResource

                  Developer note: This implementation does not strictly adhere +to the description of SpecificResource in the Web Annotation Model +document https://www.w3.org/TR/annotation-model/ +section 4 : https://www.w3.org/TR/annotation-model/#specific-resources

                  +

                  The getTransform() method returning an Array of 3D Transfom resources, is +an extension of SpecificResource beyond the web annotation model.

                  +

                  Hierarchy (View Summary)

                  Index

                  Constructors

                  Properties

                  __jsonld: any
                  context: string
                  externalResource: IExternalResource
                  id: string
                  isAnnotationBody: boolean = false
                  isSpecificResource: boolean = true

                  Accessors

                  Methods

                  • returns the PropertyValue which in turn allows a language-specific string +encoded in the json as the "label" property

                    +

                    Returns PropertyValue

                    var label = manifest.getLabel().getValue(); // returns the string for default locale
                    +
                    + +
                    var label = manifest.getLabel().getValue(locale); // locale a string , examples
                    // would be "fr", "en-US", +
                    + +
                  • A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier

                    +

                    If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.

                    +
                      +
                    • +
                    +

                    Parameters

                    • name: string

                    Returns any

                  diff --git a/docs/classes/TextualBody.html b/docs/classes/TextualBody.html new file mode 100644 index 00000000..5e266537 --- /dev/null +++ b/docs/classes/TextualBody.html @@ -0,0 +1,71 @@ +TextualBody | manifesto
                  manifesto
                    Preparing search index...

                    Class TextualBody

                    An implementation of the TextualBody class (class in JSON-LD sense) +as it is described in Web Annotation Data Model Section 3.2.4 +https://www.w3.org/TR/annotation-model/#embedded-textual-body +*

                    +

                    Hierarchy (View Summary)

                    Index

                    Constructors

                    Properties

                    __jsonld: any
                    context: string
                    externalResource: IExternalResource
                    id: string

                    Accessors

                    • get Value(): string

                      The simple string that is the data content of this resource +will return empty string as a default value +*

                      +

                      Returns string

                    Methods

                    • returns the PropertyValue which in turn allows a language-specific string +encoded in the json as the "label" property

                      +

                      Returns PropertyValue

                      var label = manifest.getLabel().getValue(); // returns the string for default locale
                      +
                      + +
                      var label = manifest.getLabel().getValue(locale); // locale a string , examples
                      // would be "fr", "en-US", +
                      + +
                    • A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier

                      +

                      If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.

                      +
                        +
                      • +
                      +

                      Parameters

                      • name: string

                      Returns any

                    diff --git a/docs/classes/Transform.html b/docs/classes/Transform.html new file mode 100644 index 00000000..24859cfe --- /dev/null +++ b/docs/classes/Transform.html @@ -0,0 +1,22 @@ +Transform | manifesto
                    manifesto
                      Preparing search index...

                      Class TransformAbstract

                      Hierarchy (View Summary)

                      Index

                      Constructors

                      Properties

                      __jsonld: any
                      context: string
                      id: string
                      isRotateTransform: undefined | boolean
                      isScaleTransform: undefined | boolean
                      isTransform: boolean = true
                      isTranslateTransform: undefined | boolean

                      Methods

                      • A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier

                        +

                        If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.

                        +
                          +
                        • +
                        +

                        Parameters

                        • name: string

                        Returns any

                      diff --git a/docs/classes/TransformParser.html b/docs/classes/TransformParser.html new file mode 100644 index 00000000..65fea503 --- /dev/null +++ b/docs/classes/TransformParser.html @@ -0,0 +1,3 @@ +TransformParser | manifesto
                      manifesto
                        Preparing search index...

                        Class TransformParser

                        Index

                        Constructors

                        Methods

                        Constructors

                        Methods

                        diff --git a/docs/classes/TranslateTransform.html b/docs/classes/TranslateTransform.html new file mode 100644 index 00000000..25882e63 --- /dev/null +++ b/docs/classes/TranslateTransform.html @@ -0,0 +1,23 @@ +TranslateTransform | manifesto
                        manifesto
                          Preparing search index...

                          Class TranslateTransform

                          Hierarchy (View Summary)

                          Index

                          Constructors

                          Properties

                          __jsonld: any
                          context: string
                          id: string
                          isRotateTransform: undefined | boolean
                          isScaleTransform: undefined | boolean
                          isTransform: boolean = true
                          isTranslateTransform: undefined | boolean

                          Methods

                          • A function that wraps the getProperty function, which client +code can use if it is needed to identify when the json value of +a property is an IRI -- Internationalized Resource Identifier

                            +

                            If the value of the json value is a bare string, then it will be +wrapped in a json object with the string in the property 'id', +additionally that property will have a property 'isIRI' which will +be true for the literal string case, otherwise false meaning the +returned getProperty should be parsed as before.

                            +
                              +
                            • +
                            +

                            Parameters

                            • name: string

                            Returns any

                          diff --git a/docs/functions/cameraRelativeRotation.html b/docs/functions/cameraRelativeRotation.html new file mode 100644 index 00000000..b8659cc8 --- /dev/null +++ b/docs/functions/cameraRelativeRotation.html @@ -0,0 +1,15 @@ +cameraRelativeRotation | manifesto
                          manifesto
                            Preparing search index...

                            Function cameraRelativeRotation

                            • performs the calculation required for the lookAt +property of a camera resource. Determines the +required angles of two rotations, the first about +the x axis and the second about the y axis, which will +rotate the default camera direction (0,0,-1) into the +direction of the input arguments

                              +

                              Result of calculation is returned as a instance of EulerAngle from the +threejs-math library. The "axes order" of the EulerAngle is "YXZ": The +three-js library uses body-fixed axes to represent EulerAngles, which reverse +the ordering of the "relative rotation" algorithm described in the +draft 3d api.

                              +

                              Parameters

                              • direction: Vector3

                                A vector interpreted as a direction. Client code +responsible for not passing a 0-length vector, else a

                                +

                              Returns Euler

                              threejs-math.EulerAngle instance

                              +
                            diff --git a/docs/functions/combineTransformsToMatrix.html b/docs/functions/combineTransformsToMatrix.html new file mode 100644 index 00000000..2d889af4 --- /dev/null +++ b/docs/functions/combineTransformsToMatrix.html @@ -0,0 +1,6 @@ +combineTransformsToMatrix | manifesto
                            manifesto
                              Preparing search index...

                              Function combineTransformsToMatrix

                              • Given an array of Transform instances, returns a single Matrix4 +instance that represents the cumulative effect of the transforms +in the order they appear in the array.

                                +

                                Parameters

                                • transforms: Transform[]

                                  An array of Transform instances

                                  +

                                Returns Matrix4

                                A Matrix4 instance representing the cumulative effect of the transforms

                                +
                              diff --git a/docs/functions/combineTransformsToTRS.html b/docs/functions/combineTransformsToTRS.html new file mode 100644 index 00000000..53586a4b --- /dev/null +++ b/docs/functions/combineTransformsToTRS.html @@ -0,0 +1 @@ +combineTransformsToTRS | manifesto
                              manifesto
                                Preparing search index...

                                Function combineTransformsToTRS

                                diff --git a/docs/functions/decomposeMatrix.html b/docs/functions/decomposeMatrix.html new file mode 100644 index 00000000..25bbd623 --- /dev/null +++ b/docs/functions/decomposeMatrix.html @@ -0,0 +1 @@ +decomposeMatrix | manifesto
                                manifesto
                                  Preparing search index...

                                  Function decomposeMatrix

                                  • Parameters

                                    • matrix: Matrix4

                                    Returns { rotation: Euler; scale: Vector3; translation: Vector3 }

                                  diff --git a/docs/functions/eulerFromRotateTransform.html b/docs/functions/eulerFromRotateTransform.html new file mode 100644 index 00000000..177b9c00 --- /dev/null +++ b/docs/functions/eulerFromRotateTransform.html @@ -0,0 +1,7 @@ +eulerFromRotateTransform | manifesto
                                  manifesto
                                    Preparing search index...

                                    Function eulerFromRotateTransform

                                    • Implements the convention that the 3 component values for the RotateTranform +cass (properties x,y,z) are to be interpreted as Euler angles in the intrinsic XYZ +order

                                      +

                                      Parameters

                                      • transform: RotateTransform

                                        : A object with a Rotation member object, properties x,y,z

                                        +

                                      Returns Euler

                                      threejs-math.EulerAngle instance. From this threejs-math functionsa +allow conversion to other rotation representations.

                                      +
                                    diff --git a/docs/functions/lightRelativeRotation.html b/docs/functions/lightRelativeRotation.html new file mode 100644 index 00000000..f4109a5d --- /dev/null +++ b/docs/functions/lightRelativeRotation.html @@ -0,0 +1,12 @@ +lightRelativeRotation | manifesto
                                    manifesto
                                      Preparing search index...

                                      Function lightRelativeRotation

                                      • Evaluates the rotation required to transform a directional light +or spot ling, which in iiif 3D spec +have an initial direction in the -Y direction, to a direction +along the input argument

                                        +

                                        TODO : expand on this documentation taking into account the +implied specification that RotateTransform instances +are to be interpreted as an Euler angle definition of +the rotation

                                        +

                                        Parameters

                                        • direction: Vector3

                                          A vector interpreted as a direction. Client code +responsible for not passing a 0-length vector, else a

                                          +

                                        Returns Euler

                                        threejs-math.EulerAngle instance

                                        +
                                      diff --git a/package-lock.json b/package-lock.json index 295d8150..d611fbff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,10 @@ "dependencies": { "@edsilv/http-status-codes": "^1.0.3", "@iiif/vocabulary": "^1.0.28", + "color-string": "1.9", "isomorphic-unfetch": "^3.0.0", - "lodash": "^4.17.21" + "lodash": "^4.17.21", + "threejs-math": "^0.147" }, "devDependencies": { "@types/node": "24.0.10", @@ -26,7 +28,6 @@ "http": "0.0.0", "mocha": "^11.7.1", "prettier": "^3.6.2", - "prettier-check": "^2.0.0", "rimraf": "^6.0.1", "serve-static": "^2.2.0", "ts-loader": "^9", @@ -47,6 +48,7 @@ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.17.0" } @@ -54,7 +56,8 @@ "node_modules/@edsilv/http-status-codes": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@edsilv/http-status-codes/-/http-status-codes-1.0.3.tgz", - "integrity": "sha512-HLK2FS5sZqxPqD53D6hhZxC6C8THTVwlyZDZ7J0iWsrB8JmMA69m/CQuNKZc1kki9WSVeck2fXna26NL0SE7cg==" + "integrity": "sha512-HLK2FS5sZqxPqD53D6hhZxC6C8THTVwlyZDZ7J0iWsrB8JmMA69m/CQuNKZc1kki9WSVeck2fXna26NL0SE7cg==", + "license": "MIT" }, "node_modules/@eslint-community/eslint-utils": { "version": "4.7.0", @@ -113,19 +116,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@eslint/config-helpers": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.3.tgz", @@ -173,43 +163,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@eslint/js": { "version": "9.27.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz", @@ -261,15 +214,16 @@ } }, "node_modules/@gerrit0/mini-shiki": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.7.0.tgz", - "integrity": "sha512-7iY9wg4FWXmeoFJpUL2u+tsmh0d0jcEJHAIzVxl3TG4KL493JNnisdLAILZ77zcD+z3J0keEXZ+lFzUgzQzPDg==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.8.0.tgz", + "integrity": "sha512-tloLVqvvoyv636PilYZwNhCmZ+xxgRicysMvpKdZ4Y6+9IH6v4lp7GodbDDncApNQjflwTSnXuYQoe3el5C59w==", "dev": true, + "license": "MIT", "dependencies": { - "@shikijs/engine-oniguruma": "^3.7.0", - "@shikijs/langs": "^3.7.0", - "@shikijs/themes": "^3.7.0", - "@shikijs/types": "^3.7.0", + "@shikijs/engine-oniguruma": "^3.8.0", + "@shikijs/langs": "^3.8.0", + "@shikijs/themes": "^3.8.0", + "@shikijs/types": "^3.8.0", "@shikijs/vscode-textmate": "^10.0.2" } }, @@ -342,7 +296,8 @@ "node_modules/@iiif/vocabulary": { "version": "1.0.28", "resolved": "https://registry.npmjs.org/@iiif/vocabulary/-/vocabulary-1.0.28.tgz", - "integrity": "sha512-+6D5FYv5fHvYpJHZKOoX0FYsU/w+cOLKcIrL2lFKkrCoD2LfMf5JzdxvgrAqdcBbwIa3AGJwWaHhXPhYbS40iQ==" + "integrity": "sha512-+6D5FYv5fHvYpJHZKOoX0FYsU/w+cOLKcIrL2lFKkrCoD2LfMf5JzdxvgrAqdcBbwIa3AGJwWaHhXPhYbS40iQ==", + "license": "MIT" }, "node_modules/@isaacs/balanced-match": { "version": "4.0.1", @@ -372,6 +327,7 @@ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -384,90 +340,12 @@ "node": ">=12" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.12", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" @@ -478,6 +356,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -487,6 +366,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz", "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -496,13 +376,15 @@ "version": "1.5.4", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.29", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -551,6 +433,7 @@ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=14" @@ -570,38 +453,42 @@ } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.7.0.tgz", - "integrity": "sha512-5BxcD6LjVWsGu4xyaBC5bu8LdNgPCVBnAkWTtOCs/CZxcB22L8rcoWfv7Hh/3WooVjBZmFtyxhgvkQFedPGnFw==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.8.0.tgz", + "integrity": "sha512-Tx7kR0oFzqa+rY7t80LjN8ZVtHO3a4+33EUnBVx2qYP3fGxoI9H0bvnln5ySelz9SIUTsS0/Qn+9dg5zcUMsUw==", "dev": true, + "license": "MIT", "dependencies": { - "@shikijs/types": "3.7.0", + "@shikijs/types": "3.8.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "node_modules/@shikijs/langs": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.7.0.tgz", - "integrity": "sha512-1zYtdfXLr9xDKLTGy5kb7O0zDQsxXiIsw1iIBcNOO8Yi5/Y1qDbJ+0VsFoqTlzdmneO8Ij35g7QKF8kcLyznCQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.8.0.tgz", + "integrity": "sha512-mfGYuUgjQ5GgXinB5spjGlBVhG2crKRpKkfADlp8r9k/XvZhtNXxyOToSnCEnF0QNiZnJjlt5MmU9PmhRdwAbg==", "dev": true, + "license": "MIT", "dependencies": { - "@shikijs/types": "3.7.0" + "@shikijs/types": "3.8.0" } }, "node_modules/@shikijs/themes": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.7.0.tgz", - "integrity": "sha512-VJx8497iZPy5zLiiCTSIaOChIcKQwR0FebwE9S3rcN0+J/GTWwQ1v/bqhTbpbY3zybPKeO8wdammqkpXc4NVjQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.8.0.tgz", + "integrity": "sha512-yaZiLuyO23sXe16JFU76KyUMTZCJi4EMQKIrdQt7okoTzI4yAaJhVXT2Uy4k8yBIEFRiia5dtD7gC1t8m6y3oQ==", "dev": true, + "license": "MIT", "dependencies": { - "@shikijs/types": "3.7.0" + "@shikijs/types": "3.8.0" } }, "node_modules/@shikijs/types": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.7.0.tgz", - "integrity": "sha512-MGaLeaRlSWpnP0XSAum3kP3a8vtcTsITqoEPYdt3lQG3YCdQH4DnEhodkYcNMcU0uW0RffhoD1O3e0vG5eSBBg==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.8.0.tgz", + "integrity": "sha512-I/b/aNg0rP+kznVDo7s3UK8jMcqEGTtoPDdQ+JlQ2bcJIyu/e2iRvl42GLIDMK03/W1YOHOuhlhQ7aM+XbKUeg==", "dev": true, + "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" @@ -611,7 +498,8 @@ "version": "10.0.2", "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/eslint": { "version": "9.6.1", @@ -629,6 +517,7 @@ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, + "license": "MIT", "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -638,13 +527,15 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/unist": "*" } @@ -653,13 +544,15 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { "version": "24.0.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.10.tgz", "integrity": "sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA==", "dev": true, + "license": "MIT", "dependencies": { "undici-types": "~7.8.0" } @@ -668,7 +561,8 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.32.1", @@ -819,6 +713,32 @@ "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/utils": { "version": "8.32.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", @@ -866,6 +786,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" @@ -875,25 +796,29 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", @@ -904,13 +829,15 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -923,6 +850,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, + "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -932,6 +860,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } @@ -940,13 +869,15 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -963,6 +894,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", @@ -976,6 +908,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -988,6 +921,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", @@ -1002,6 +936,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, + "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" @@ -1012,6 +947,7 @@ "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-3.0.1.tgz", "integrity": "sha512-u8d0pJ5YFgneF/GuvEiDA61Tf1VDomHHYMjv/wc9XzYj7nopltpG96nXN5dJRstxZhcNpV1g+nT6CydO7pHbjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18.12.0" }, @@ -1025,6 +961,7 @@ "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-3.0.1.tgz", "integrity": "sha512-coEmDzc2u/ffMvuW9aCjoRzNSPDl/XLuhPdlFRpT9tZHmJ/039az33CE7uH+8s0uL1j5ZNtfdv0HkfaKRBGJsQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18.12.0" }, @@ -1038,6 +975,7 @@ "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-3.0.1.tgz", "integrity": "sha512-sbgw03xQaCLiT6gcY/6u3qBDn01CWw/nbaXl3gTdTFuJJ75Gffv3E3DBpgvY2fkkrdS1fpjaXNOmJlnbtKauKg==", "dev": true, + "license": "MIT", "engines": { "node": ">=18.12.0" }, @@ -1055,13 +993,15 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/acorn": { "version": "8.15.0", @@ -1076,6 +1016,19 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -1087,16 +1040,16 @@ } }, "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "peer": true, "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { "type": "github", @@ -1108,6 +1061,7 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^8.0.0" }, @@ -1120,25 +1074,41 @@ } } }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, - "peerDependencies": { - "ajv": "^8.8.2" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { @@ -1146,6 +1116,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -1160,28 +1131,32 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" } }, "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1204,7 +1179,8 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/browserslist": { "version": "4.25.1", @@ -1243,7 +1219,8 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/callsites": { "version": "3.1.0", @@ -1255,10 +1232,23 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/caniuse-lite": { - "version": "1.0.30001726", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", - "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", + "version": "1.0.30001727", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", + "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", "dev": true, "funding": [ { @@ -1273,13 +1263,15 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chai": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", "dev": true, + "license": "MIT", "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", @@ -1308,24 +1300,12 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/check-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 16" } @@ -1335,6 +1315,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, + "license": "MIT", "dependencies": { "readdirp": "^4.0.1" }, @@ -1346,29 +1327,84 @@ } }, "node_modules/chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, + "license": "MIT", "engines": { "node": ">=6.0" } }, "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "dev": true, + "license": "ISC", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/clone-deep": { @@ -1376,6 +1412,7 @@ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -1390,6 +1427,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1401,31 +1439,45 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" }, "node_modules/cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.1" }, @@ -1444,6 +1496,7 @@ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1453,56 +1506,12 @@ "node": ">= 8" } }, - "node_modules/cross-spawn/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cross-spawn/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cross-spawn/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/debug": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -1515,11 +1524,25 @@ } } }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-eql": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1536,6 +1559,7 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -1545,6 +1569,7 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -1554,6 +1579,7 @@ "resolved": "https://registry.npmjs.org/dts-bundle-generator/-/dts-bundle-generator-9.5.1.tgz", "integrity": "sha512-DxpJOb2FNnEyOzMkG11sxO2dmxPjthoVWxfKqWYJ/bI/rT1rvTMktF5EKjAYrRZu6Z6t3NhOUZ0sZ5ZXevOfbA==", "dev": true, + "license": "MIT", "dependencies": { "typescript": ">=5.0.2", "yargs": "^17.6.0" @@ -1565,13 +1591,82 @@ "node": ">=14.0.0" } }, - "node_modules/dts-bundle-generator/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/dts-bundle-generator/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=8" + } + }, + "node_modules/dts-bundle-generator/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dts-bundle-generator/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/dts-bundle-generator/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dts-bundle-generator/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dts-bundle-generator/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/dts-bundle-generator/node_modules/yargs": { @@ -1579,6 +1674,7 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -1596,25 +1692,29 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.179", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.179.tgz", - "integrity": "sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==", - "dev": true + "version": "1.5.183", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.183.tgz", + "integrity": "sha512-vCrDBYjQCAEefWGjlK3EpoSKfKbT10pR4XXPdn65q7snuNOZnthoVpBfZPykmDapOKfoD+MMIPG8ZjKyyc9oHA==", + "dev": true, + "license": "ISC" }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" }, "node_modules/encodeurl": { "version": "2.0.0", @@ -1631,6 +1731,7 @@ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -1644,6 +1745,7 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -1656,6 +1758,7 @@ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", "dev": true, + "license": "MIT", "bin": { "envinfo": "dist/cli.js" }, @@ -1667,13 +1770,15 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1682,7 +1787,8 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", @@ -1760,206 +1866,81 @@ } }, "node_modules/eslint-config-prettier": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", - "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "funding": { - "url": "https://opencollective.com/eslint-config-prettier" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.0.tgz", - "integrity": "sha512-BvQOvUhkVQM1i63iMETK9Hjud9QhqBnbtT1Zc642p9ynzBuCe5pybkOnvqZIBypXmMlsGcnU4HZ8sCTPfpAexA==", - "dev": true, - "license": "MIT", - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.11.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", + "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" + "peer": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/eslint-plugin-prettier": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.0.tgz", + "integrity": "sha512-BvQOvUhkVQM1i63iMETK9Hjud9QhqBnbtT1Zc642p9ynzBuCe5pybkOnvqZIBypXmMlsGcnU4HZ8sCTPfpAexA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.0" }, "engines": { - "node": "*" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "yocto-queue": "^0.1.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, + "license": "Apache-2.0", "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { @@ -1993,21 +1974,12 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -2015,20 +1987,12 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -2048,6 +2012,7 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2057,46 +2022,17 @@ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", - "integrity": "sha512-/teX3MDLFBdYUhRk8WCBYboIMUmqeizu0m9Z3YF3JWrbEh/SlZg00vLJSaAGWw3wrZ9tE0buNw79eaAPYhUuvg==", - "dev": true, "license": "MIT", - "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, "engines": { - "node": ">=4" - } - }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "node": ">=0.8.x" } }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -2163,13 +2099,15 @@ "type": "opencollective", "url": "https://opencollective.com/fastify" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.9.1" } @@ -2215,6 +2153,7 @@ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", @@ -2228,16 +2167,20 @@ } }, "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { @@ -2245,6 +2188,7 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, + "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } @@ -2275,6 +2219,7 @@ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" @@ -2286,23 +2231,12 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/fresh": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -2312,15 +2246,27 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-east-asian-width": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -2328,15 +2274,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/glob": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", @@ -2375,7 +2312,34 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/globals": { "version": "14.0.0", @@ -2394,7 +2358,8 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", @@ -2408,6 +2373,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2417,6 +2383,7 @@ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -2429,6 +2396,7 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, + "license": "MIT", "bin": { "he": "bin/he" } @@ -2436,14 +2404,16 @@ "node_modules/http": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/http/-/http-0.0.0.tgz", - "integrity": "sha1-huYybSnF0Dnen6xYSkVon5KfT3I=", - "dev": true + "integrity": "sha512-epOGLlKUFT+yxfK9TqXRe7l6CbOk7mbLvzVqAyI05w0xIn+nXcYo0vR4ZBCVJYOyUglOFwtaIbD3d2TmG5ejJQ==", + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -2455,6 +2425,16 @@ "node": ">= 0.8" } }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2482,21 +2462,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, + "license": "MIT", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -2525,22 +2496,31 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/interpret": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.13.0" } }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT" + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, + "license": "MIT", "dependencies": { "hasown": "^2.0.2" }, @@ -2566,6 +2546,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2598,6 +2579,7 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2607,6 +2589,7 @@ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, + "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, @@ -2614,20 +2597,12 @@ "node": ">=0.10.0" } }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2638,14 +2613,16 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2665,6 +2642,7 @@ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -2680,13 +2658,30 @@ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, - "engines": { - "node": ">= 10.13.0" + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/js-yaml": { @@ -2713,13 +2708,15 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -2743,6 +2740,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2766,6 +2764,7 @@ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, + "license": "MIT", "dependencies": { "uc.micro": "^2.0.0" } @@ -2775,26 +2774,32 @@ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.11.5" } }, "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -2803,34 +2808,50 @@ "dev": true, "license": "MIT" }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/loupe": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz", "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "ISC", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } + "license": "ISC" }, "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -2847,13 +2868,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", @@ -2884,6 +2907,7 @@ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2893,6 +2917,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, @@ -2901,27 +2926,16 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimatch/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "node": "*" } }, "node_modules/minipass": { @@ -2929,6 +2943,7 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } @@ -2938,6 +2953,7 @@ "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.1.tgz", "integrity": "sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==", "dev": true, + "license": "MIT", "dependencies": { "browser-stdout": "^1.3.1", "chokidar": "^4.0.1", @@ -2968,90 +2984,124 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/mocha/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/mocha/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=12" } }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/mocha/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { - "p-locate": "^5.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/mocha/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8" } }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/mocha/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { - "p-limit": "^3.0.2" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/mocha/node_modules/yargs": { @@ -3059,6 +3109,7 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -3076,7 +3127,8 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -3089,7 +3141,8 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-fetch": { "version": "2.7.0", @@ -3115,25 +3168,15 @@ "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } + "license": "MIT" }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -3159,40 +3202,36 @@ "node": ">= 0.8.0" } }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-try": { @@ -3200,6 +3239,7 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3208,7 +3248,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true + "dev": true, + "license": "BlueOak-1.0.0" }, "node_modules/parent-module": { "version": "1.0.1", @@ -3228,6 +3269,7 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -3237,30 +3279,34 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -3272,17 +3318,12 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - }, "node_modules/pathval": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 14.16" } @@ -3291,7 +3332,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -3311,6 +3353,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -3318,6 +3361,62 @@ "node": ">=8" } }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3344,24 +3443,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/prettier-check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prettier-check/-/prettier-check-2.0.0.tgz", - "integrity": "sha512-HZG53XQTJ9Cyi5hi1VFVVFxdlhITJybpZAch3ib9KqI05VUxV+F5Hip0GhSWRItrlDzVyqjSoDQ9KqIn7AHYyw==", - "dev": true, - "dependencies": { - "execa": "^0.6.0" - }, - "bin": { - "prettier-check": "cli.js" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "prettier": "x.x.x" - } - }, "node_modules/prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", @@ -3375,13 +3456,6 @@ "node": ">=6.0.0" } }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true, - "license": "ISC" - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3397,6 +3471,7 @@ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3427,6 +3502,7 @@ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -3436,6 +3512,7 @@ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -3445,6 +3522,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 14.18.0" }, @@ -3458,6 +3536,7 @@ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "dev": true, + "license": "MIT", "dependencies": { "resolve": "^1.20.0" }, @@ -3468,8 +3547,9 @@ "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3479,6 +3559,7 @@ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3488,6 +3569,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", @@ -3508,6 +3590,7 @@ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -3515,15 +3598,26 @@ "node": ">=8" } }, - "node_modules/resolve-from": { + "node_modules/resolve-cwd/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -3540,6 +3634,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^11.0.0", "package-json-from-dist": "^1.0.0" @@ -3583,6 +3678,7 @@ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -3598,6 +3694,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", "dev": true, + "license": "ISC", "engines": { "node": "20 || >=22" } @@ -3623,6 +3720,7 @@ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" @@ -3684,6 +3782,7 @@ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -3698,6 +3797,43 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, "node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", @@ -3716,6 +3852,7 @@ "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.5", "encodeurl": "^2.0.0", @@ -3738,6 +3875,7 @@ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -3747,6 +3885,7 @@ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", "dev": true, + "license": "MIT", "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", @@ -3761,13 +3900,15 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, + "license": "MIT", "dependencies": { "kind-of": "^6.0.2" }, @@ -3776,37 +3917,56 @@ } }, "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { - "shebang-regex": "^1.0.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">= 8" } @@ -3816,6 +3976,7 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -3826,14 +3987,15 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "license": "MIT", "engines": { @@ -3841,17 +4003,21 @@ } }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/string-width-cjs": { @@ -3860,6 +4026,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3869,11 +4036,29 @@ "node": ">=8" } }, - "node_modules/strip-ansi": { + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3881,12 +4066,29 @@ "node": ">=8" } }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3894,13 +4096,14 @@ "node": ">=8" } }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/strip-json-comments": { @@ -3908,6 +4111,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -3916,18 +4120,16 @@ } }, "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -3935,6 +4137,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3963,6 +4166,7 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3972,6 +4176,7 @@ "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.14.0", @@ -3990,6 +4195,7 @@ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -4019,6 +4225,12 @@ } } }, + "node_modules/threejs-math": { + "version": "0.147.0", + "resolved": "https://registry.npmjs.org/threejs-math/-/threejs-math-0.147.0.tgz", + "integrity": "sha512-TUuW2RIN9p7hJcSsm37f5MGmRTTow5HHxVG93hep1gN9Qso4vcEIOKHZ/vczW3ZTY/IVTDNX/WudNPUHG5XULw==", + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4037,6 +4249,7 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.6" } @@ -4065,6 +4278,7 @@ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.2.tgz", "integrity": "sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "enhanced-resolve": "^5.0.0", @@ -4080,12 +4294,6 @@ "webpack": "^5.0.0" } }, - "node_modules/tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4104,6 +4312,7 @@ "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.7.tgz", "integrity": "sha512-lpz0Oxl6aidFkmS90VQDQjk/Qf2iw0IUvFqirdONBdj7jPSN9mGXhy66BcGNDxx5ZMyKKiBVAREvPEzT6Uxipw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@gerrit0/mini-shiki": "^3.7.0", "lunr": "^2.3.9", @@ -4122,10 +4331,36 @@ "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x" } }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -4164,13 +4399,15 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/undici-types": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/unfetch": { "version": "4.2.0", @@ -4197,6 +4434,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" @@ -4223,6 +4461,7 @@ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "dev": true, + "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -4238,22 +4477,23 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.99.9", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", - "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==", + "version": "5.100.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.100.1.tgz", + "integrity": "sha512-YJB/ESPUe2Locd0NKXmw72Dx8fZQk1gTzI6rc9TAT4+Sypbnhl8jd8RywB1bDsDF9Dy1RUR7gn3q/ZJTd0OZZg==", "dev": true, "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", + "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.14.0", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", + "enhanced-resolve": "^5.17.2", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -4267,7 +4507,7 @@ "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" + "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" @@ -4333,6 +4573,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" } @@ -4342,6 +4583,7 @@ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", "dev": true, + "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", @@ -4356,15 +4598,41 @@ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.13.0" } }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/webpack/node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -4374,6 +4642,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -4392,22 +4661,27 @@ } }, "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, "bin": { - "which": "bin/which" + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/word-wrap": { "version": "1.2.5", @@ -4423,20 +4697,22 @@ "version": "9.3.3", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.3.tgz", "integrity": "sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -4448,6 +4724,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -4460,27 +4737,80 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, - "node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true, - "license": "ISC" - }, "node_modules/yaml": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", "dev": true, + "license": "ISC", "bin": { "yaml": "bin.mjs" }, @@ -4493,6 +4823,7 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", @@ -4510,6 +4841,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } @@ -4519,6 +4851,7 @@ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, + "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -4529,88 +4862,19 @@ "node": ">=10" } }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/yargs/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/yargs/node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "dev": true, - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, "node_modules/yargs/node_modules/emoji-regex": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true - }, - "node_modules/yargs/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } + "license": "MIT" }, "node_modules/yargs/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -4623,43 +4887,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/yargs/node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/yargs/node_modules/yargs-parser": { "version": "22.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "dev": true, + "license": "ISC", "engines": { "node": "^20.19.0 || ^22.12.0 || >=23" } @@ -4669,6 +4902,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index cff2bfc8..b7266a91 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,6 @@ "http": "0.0.0", "mocha": "^11.7.1", "prettier": "^3.6.2", - "prettier-check": "^2.0.0", "rimraf": "^6.0.1", "serve-static": "^2.2.0", "ts-loader": "^9", @@ -67,7 +66,9 @@ "@edsilv/http-status-codes": "^1.0.3", "@iiif/vocabulary": "^1.0.28", "isomorphic-unfetch": "^3.0.0", - "lodash": "^4.17.21" + "lodash": "^4.17.21", + "color-string": "1.9", + "threejs-math": "^0.147" }, "directories": { "test": "test" diff --git a/src/Annotation.ts b/src/Annotation.ts index 9f8a394d..2bbe7178 100644 --- a/src/Annotation.ts +++ b/src/Annotation.ts @@ -1,48 +1,115 @@ import { AnnotationMotivation } from "@iiif/vocabulary/dist-commonjs"; import { AnnotationBody, + AnnotationBodyParser, + AnnotationPage, IManifestoOptions, ManifestResource, Resource, + SpecificResource, + TextualBody, } from "./internal"; +import { Vector3 } from "threejs-math"; + export class Annotation extends ManifestResource { constructor(jsonld: any, options: IManifestoOptions) { super(jsonld, options); } + /** + In spite of its name, this method returns an array of objects, each of which + represents a potential body annotations + + @see{ https://iiif.io/api/cookbook/recipe/0033-choice/ } + **/ getBody(): AnnotationBody[] { - const bodies: AnnotationBody[] = []; + let bodies: AnnotationBody[] = []; + + /* + A bodyValue property in the annotation json will short circuit + the parsing process and be interpreted as a shorthand version of + a TextualBody resource defining as the body + + This procedure is allowed, see Web Annotation Data Model section 3.2.5 + https://www.w3.org/TR/annotation-model/#string-body + */ + + var stringBody: string | undefined = this.getProperty("bodyValue"); + //console.log("retrieved stringBody " + stringBody); + if (stringBody) { + return [ + new TextualBody( + { + id: "https://example.com/TextualBody/1", + value: stringBody, + type: "TextualBody", + }, + this.options + ), + ]; + } + const body: any = this.getProperty("body"); - // todo: make this a generic "property that can be an object or array enumerator" util + // the following is intended to handle the following cases for + /// the raw json of the body property of __jsonld + // -- body is an array, each element of which is parsed + // == body is an object with property items, each item is parsed + // -- body is parsed if (body) { - if (Array.isArray(body)) { - for (let i = 0; i < body.length; i++) { - const b: any = body[i]; - if (b.items) { - for (let i = 0; i < b.items.length; i++) { - // todo: don't ignore that it's a choice. maybe add isChoice() to IAnnotationBody? - const c: any = b.items[i]; - bodies.push(new AnnotationBody(c, this.options)); - } - } else { - bodies.push(new AnnotationBody(b, this.options)); - } - } - } else if (body.items) { - for (let i = 0; i < body.items.length; i++) { - const b: any = body.items[i]; - bodies.push(new AnnotationBody(b, this.options)); - } - } else { - bodies.push(new AnnotationBody(body, this.options)); + for (var bd of [].concat(body)) { + var items = (bd as any).items; + if (items) bodies = bodies.concat(this.parseBodiesFromItemsList(items)); + else bodies.push(this.parseSingletonBody(bd)); } } return bodies; } + /** + auxiliary function to getBody; intended to hande an object that has an element items + which is a array of annotation- body-like objects. This : https://iiif.io/api/cookbook/recipe/0033-choice/ + seems to be the use case for this + **/ + private parseBodiesFromItemsList(rawbodies: any): AnnotationBody[] { + const retVal: AnnotationBody[] = []; + for (var bd of [].concat(rawbodies)) { + retVal.push(this.parseSingletonBody(bd)); + } + return retVal; + } + + /** + auxiliary function to parseBodiesFromItemsList and getBody, this is the last + step on recursively going through collections of bodies. + **/ + private parseSingletonBody(rawbody: any): AnnotationBody { + return AnnotationBodyParser.BuildFromJson(rawbody, this.options); + } + + /** + Developer Note: 8 April 2024 + getBody3D function was developed in the early stages of the 3D API Feb-March 2024 + as alternative to the existing Annotation getBody function, but the signature for + getBody3D was chosen to be a single object instance, not an array. + + At this stage, the merging of the 2D API anf the draft 3D API has been completed, so + 3D applications can use the getBody() function to retrieve the body of an Annotation intended + to target a scene. For compatibily the return value of the function is still an + array. + + 3D clients using getBody are responsible for choosing the appropriate instance from the + returned array. In most cases this will be the sole 0th element. + **/ + getBody3D(): AnnotationBody { + console.warn( + "Annotation.getBody3D is deprecated: replace with getBody3D() with getBody()[0]" + ); + return this.getBody()[0]; + } + getMotivation(): AnnotationMotivation | null { const motivation: string = this.getProperty("motivation"); @@ -59,11 +126,51 @@ export class Annotation extends ManifestResource { return this.getProperty("on"); } - getTarget(): string | null { - return this.getProperty("target"); + getTarget(): any { + const rawTarget = this.getPropertyAsObject("target"); + if (rawTarget.isIRI) return rawTarget; + + if (rawTarget.type && rawTarget.type == "SpecificResource") { + return new SpecificResource(rawTarget, this.options); + } else if (["Scene", "Canvas"].includes(rawTarget.type)) { + return rawTarget; + } else { + throw new Error("unknown target specified"); + } + } + + // Retrieves target scope content state annotations + getScopeContent(): Annotation[] { + const items = this.getTarget()?.getScope()?.getTarget()?.items; + if (!items) return []; + + return items + .filter((item) => item && item.type === "AnnotationPage") + .map((item) => new AnnotationPage(item, this.options).getItems()) + .flat() + .filter((item) => item && item.type === "Annotation") + .map((annotation) => new Annotation(annotation, this.options)); } getResource(): Resource { return new Resource(this.getProperty("resource"), this.options); } + + /** + * A 3D point coordinate object for the location of an Annotation + * to satisfy the requirements of the lookAt property of camera and + * spotlight resources, according to the draft v4 API as of April 1 2024 + * + * Is the position of the point for a target which is a SpecificResource with + * a PointSelector + * Otherwise, for example when the annotation target is an entire Scene, the + * location for lookAt is the origin (0,0,0) + **/ + get LookAtLocation(): Vector3 { + var target = this.getTarget() as any; + + if (target.isSpecificResource && target.getSelector()?.isPointSelector) + return target.getSelector().getLocation(); + else return new Vector3(0.0, 0.0, 0.0); + } } diff --git a/src/AnnotationBody.ts b/src/AnnotationBody.ts index d5178b81..1335587e 100644 --- a/src/AnnotationBody.ts +++ b/src/AnnotationBody.ts @@ -2,15 +2,51 @@ import { ExternalResourceType, MediaType, } from "@iiif/vocabulary/dist-commonjs"; -import { IManifestoOptions, ManifestResource, Utils } from "./internal"; +import { + AnnotationBodyParser, + IManifestoOptions, + ManifestResource, + Transform, + TransformParser, + TransformSet, + Utils, + combineTransformsToMatrix, + combineTransformsToTRS, +} from "./internal"; +import { Matrix4 } from "threejs-math"; + +/** +With the 3D extensions to the IIIF Presentation API the name of this +class is misleading, but for now is being retained for the sake backward +compatibility with earlier manifesto code and tests. +The 3D extensions allow that the body property of an annotation can be +a light, camera, or model, or a SpecificResource object wrapping a light, camera, +or model. +**/ export class AnnotationBody extends ManifestResource { constructor(jsonld?: any, options?: IManifestoOptions) { super(jsonld, options); } + // Get resource URI ID from either body (for content resource) or source (for specific resource) + getResourceID(): string | null { + if (this.isSpecificResource()) { + const source = this.getSource(); + if (source instanceof AnnotationBody) { + return source.id; + } else { + return source || this.id; + } + } else { + return this.id; + } + } + + // Format, Type, Width, and Height are the body properties supported + // in the code that supports Presentation 3 getFormat(): MediaType | null { - const format: string = this.getProperty("format"); + const format: string = this.getPropertyFromSelfOrSource("format"); if (format) { return Utils.getMediaType(format); @@ -20,12 +56,10 @@ export class AnnotationBody extends ManifestResource { } getType(): ExternalResourceType | null { - const type: string = this.getProperty("type"); + const type: string = this.getPropertyFromSelfOrSource("type"); if (type) { - return ( - Utils.normaliseType(this.getProperty("type")) - ); + return Utils.normaliseType(type); } return null; @@ -46,4 +80,71 @@ export class AnnotationBody extends ManifestResource { getHeight(): number { return this.getProperty("height"); } + + getTransform(): Transform[] | null { + const transform = this.getProperty("transform"); + + if (transform) { + return this.getProperty("transform").map((transform) => { + return TransformParser.BuildFromJson(transform); + }); + } + + return null; + } + + getTransformMatrix(): Matrix4 | null { + const transform = this.getTransform(); + + if (transform && transform.length) { + return combineTransformsToMatrix(transform); + } + + return null; + } + + getTransformSet(): TransformSet | null { + const transform = this.getTransform(); + + if (transform && transform.length) { + return combineTransformsToTRS(transform); + } + + return null; + } + + // Some properties may be on this object or (for SpecificResource) in source object + getPropertyFromSelfOrSource(prop): any { + if ( + this.isSpecificResource() && + this.getSource() instanceof AnnotationBody + ) { + return (this.getSource() as AnnotationBody).getProperty(prop); + } else { + return this.getProperty(prop); + } + } + + // Get the first source available on the annotation body, if any + getSource(): AnnotationBody | string | null { + const source: object = [].concat(this.getPropertyAsObject("source"))[0]; + + if (source) { + if (source["isIRI"] === true) { + return source["id"]; + } else { + return AnnotationBodyParser.BuildFromJson(source, this.options); + } + } + + return null; + } + + isModel(): boolean { + return this.getType() === ExternalResourceType.MODEL; + } + + isSpecificResource(): boolean { + return this.getProperty("type") === "SpecificResource"; + } } diff --git a/src/AnnotationBodyParser.ts b/src/AnnotationBodyParser.ts new file mode 100644 index 00000000..8a1ffcc2 --- /dev/null +++ b/src/AnnotationBodyParser.ts @@ -0,0 +1,42 @@ +import { + AnnotationBody, + IManifestoOptions, + Light, + Camera, + TextualBody, +} from "./internal"; + +// Todo: Add these to @iiif/vocabulary +const LightTypes: string[] = [ + "AmbientLight", + "DirectionalLight", + "PointLight", + "SpotLight", +]; +const CameraTypes: string[] = ["PerspectiveCamera", "OrthographicCamera"]; +const DisplayedTypes: string[] = [ + "Image", + "Document", + "Audio", + "Model", + "Video", +]; + +export class AnnotationBodyParser { + static BuildFromJson( + jsonld: any, + options?: IManifestoOptions + ): AnnotationBody { + const type = + jsonld.type === "SpecificResource" && jsonld.source + ? [].concat(jsonld.source)[0]["type"] + : jsonld.type; + + if (DisplayedTypes.includes(type)) + return new AnnotationBody(jsonld, options); + else if (LightTypes.includes(type)) return new Light(jsonld, options); + else if (CameraTypes.includes(type)) return new Camera(jsonld, options); + else if (type === "TextualBody") return new TextualBody(jsonld, options); + else throw new Error("unimplemented type for AnnotationBody: " + type); + } +} diff --git a/src/Camera.ts b/src/Camera.ts new file mode 100644 index 00000000..fcaefc78 --- /dev/null +++ b/src/Camera.ts @@ -0,0 +1,100 @@ +import { + IManifestoOptions, + Utils, + AnnotationBody, + PointSelector, + SpecificResource, +} from "./internal"; + +export class Camera extends AnnotationBody { + constructor(jsonld?: any, options?: IManifestoOptions) { + super(jsonld, options); + } + + /** + @returns full angular size of perspective viewport in vertical direction. + Angular unit is degrees + **/ + getFieldOfView(): number | undefined { + if (this.isPerspectiveCamera()) { + var value = this.getPropertyFromSelfOrSource("fieldOfView"); + if (value) { + if (value > 0 && value < 180) return value; + else { + console.warn( + "Camera fieldOfView out of range and will be considered undefined." + ); + return undefined; + } + } else return undefined; + } else return undefined; + } + + /** + @returns full linear size of orthographic viewport in vertical direction. + linear unit is Scene global unit of measure + + Name of this property was originally Height, has been changed + at this revision to ViewHeight: + See issues at https://github.com/IIIF/api/issues/2289 + **/ + getViewHeight(): number | undefined { + if (this.isOrthographicCamera()) { + // the term viewHeight for the resource Type was suggested + // in https://github.com/IIIF/api/issues/2289#issuecomment-2161608587 + var value = this.getProperty("viewHeight"); + if (value) return value; + else return undefined; + } else return undefined; + } + + /** + * @return : if not null, is either a PointSelector, an object + * with an id matching the id of an Annotation instance, or a + * SpecificResource with a PointSelector . + **/ + getLookAt(): object | PointSelector | SpecificResource | null { + const rawObj = this.getPropertyAsObject("lookAt") ?? null; + if (rawObj == null) return null; + + const rawType = (rawObj["type"] || rawObj["@type"]) ?? null; + if (rawType == null) return null; + + if (rawType == "Annotation") return rawObj; + else if (rawType == "PointSelector") return new PointSelector(rawObj); + else if (rawType == "SpecificResource") { + return new SpecificResource(rawObj, this.options); + } else { + console.error(`unidentified value of lookAt ${rawType}`); + return null; + } + } + + /** + @returns the near plane value, i.e. the minimum distance from the camera at + which something in the space must exist in order to be viewed by the camera. + **/ + getNear(): number | undefined { + var value = this.getPropertyFromSelfOrSource("near"); + if (value) return value; + else return undefined; + } + + /** + @returns the far plane value, i.e. the maximum distance from the camera at + which something in the space must exist in order to be viewed by the camera. + **/ + getFar(): number | undefined { + var value = this.getPropertyFromSelfOrSource("far"); + if (value) return value; + else return undefined; + } + + isPerspectiveCamera(): boolean { + return Utils.normaliseType(this.getType() || "") === "perspectivecamera"; + } + + isOrthographicCamera(): boolean { + return Utils.normaliseType(this.getType() || "") === "orthographiccamera"; + } +} diff --git a/src/Canvas.ts b/src/Canvas.ts index c6569ef0..19e24c15 100644 --- a/src/Canvas.ts +++ b/src/Canvas.ts @@ -34,7 +34,6 @@ export class Canvas extends Resource { const rotation: number = 0; let quality: string = "default"; let width: number | undefined = w; - const size: string = width + ","; // if an info.json has been loaded if ( @@ -101,7 +100,9 @@ export class Canvas extends Resource { if (images && images.length) { const firstImage: Annotation = images[0]; - const body: AnnotationBody[] = firstImage.getBody(); + // Developer note: Since Canvas in Presentation 3 doesn't use + // SpecificResource resources in the body, force a cast + const body: AnnotationBody[] = firstImage.getBody() as AnnotationBody[]; const anno: AnnotationBody = body[0]; const services: Service[] = anno.getServices(); @@ -144,6 +145,8 @@ export class Canvas extends Resource { } } + const size = width + ","; + // trim off trailing '/' if (id && id.endsWith("/")) { id = id.substr(0, id.length - 1); @@ -250,6 +253,29 @@ export class Canvas extends Resource { return this.getProperty("index"); } + // Annotations not rendered as part of the Canvas + // Have non-painting motivations and are listed in Canvas annotations property, not items property + getNonContentAnnotations(): Annotation[] { + const annotationPages = (this.__jsonld.annotations || []) + .filter( + (annotationPage) => + annotationPage && annotationPage.type === "AnnotationPage" + ) + .map( + (annotationPage) => new AnnotationPage(annotationPage, this.options) + ) as AnnotationPage[]; + if (!annotationPages.length) return []; + + const annotationsNested = annotationPages.map((page) => + page.getItems() + ) as Annotation[][]; + const annotationsFlat = flattenDeep(annotationsNested) as Annotation[]; + + return annotationsFlat.map( + (annotation) => new Annotation(annotation, this.options) + ); + } + getOtherContent(): Promise { const otherContent = Array.isArray(this.getProperty("otherContent")) ? this.getProperty("otherContent") diff --git a/src/Color.ts b/src/Color.ts new file mode 100644 index 00000000..2e76a64b --- /dev/null +++ b/src/Color.ts @@ -0,0 +1,61 @@ +//import { colorString } from "color-string" + +const colorString = require("color-string"); + +/** + * class structure with red, green, blue values in 0-255 range + * Uses the {@link https://www.npmjs.com/package.color-string | color-string } + * library for conversion from and to string representations of color. + **/ +export class Color { + /** + * @param cssTerm - hex representtion of color as used in CSS. Ex "#FF0000" as red + * @returns Color instance. + **/ + static fromCSS(cssTerm: string): Color { + var rv = colorString.get(cssTerm); + if (rv.model !== "rgb") + throw new Error("unsupported color string: " + cssTerm); + return new Color([rv.value[0], rv.value[1], rv.value[2]]); + } + + /** + * @param rgbValue - Array of three 0-255 integers for r,g,b value. Ex: [255.0,0] for red + **/ + constructor(rgbValue: number[]) { + this.value = rgbValue; + } + + /** + * @returns Array of 3 integers in range 0-255 + **/ + public value: number[]; + + /** + * @return 0 to 255 value of red color component + **/ + public get red(): number { + return this.value[0]; + } + + /** + * @return 0 to 255 value of green color component + **/ + public get green(): number { + return this.value[1]; + } + + /** + * @return 0 to 255 value of blue color component + **/ + public get blue(): number { + return this.value[2]; + } + + /** + * @returns hex string (as for CSS ) representation of r,g,b components + **/ + public get CSS(): string { + return colorString.to.hex(this.value); + } +} diff --git a/src/Geometry3d.ts b/src/Geometry3d.ts new file mode 100644 index 00000000..47dfcb0f --- /dev/null +++ b/src/Geometry3d.ts @@ -0,0 +1,217 @@ +import { + Vector3, + MathUtils, + Euler, + Quaternion, + IOrder, + Matrix4, +} from "threejs-math"; +import { + RotateTransform, + ScaleTransform, + Transform, + TranslateTransform, +} from "./internal"; +// https://ros2jsguy.github.io/threejs-math/index.html + +/** +* performs the calculation required for the lookAt +* property of a camera resource. Determines the +* required angles of two rotations, the first about +* the x axis and the second about the y axis, which will +* rotate the default camera direction (0,0,-1) into the +* direction of the input arguments +* +* Result of calculation is returned as a instance of EulerAngle from the +* threejs-math library. The "axes order" of the EulerAngle is "YXZ": The +* three-js library uses body-fixed axes to represent EulerAngles, which reverse +* the ordering of the "relative rotation" algorithm described in the +* draft 3d api. + +* @param direction A vector interpreted as a direction. Client code +* responsible for not passing a 0-length vector, else a + +* +* @returns threejs-math.EulerAngle instance +**/ +export function cameraRelativeRotation(direction: Vector3): Euler { + if (direction.length() == 0.0) + throw new Error("degenerate geometry: cameraRelativeRotation"); + + // projDirection is the direction projected onto the xz plane + var projDirection = direction.clone().setComponent(1, 0.0); + var projLength = projDirection.length(); + // handle the edge case, desired viewing direction is either straight up + // or straight down + if (projLength == 0.0) { + if (direction.y > 0.0) { + // looking straight up fro below + return new Euler( + MathUtils.degToRad(+90.0), + MathUtils.degToRad(180.0), + 0, + "YXZ" + ); + } else { + return new Euler( + MathUtils.degToRad(-90.0), + MathUtils.degToRad(180.0), + 0, + "YXZ" + ); + } + } + + var yAngleRad = Math.atan2(-projDirection.x, -projDirection.z); + var xAngleRad = Math.atan2(direction.y, projLength); + return new Euler(xAngleRad, yAngleRad, 0.0, "YXZ"); +} + +/** + * Evaluates the rotation required to transform a directional light + * or spot ling, which in iiif 3D spec + * have an initial direction in the -Y direction, to a direction + * along the input argument + * + * TODO : expand on this documentation taking into account the + * implied specification that RotateTransform instances + * are to be interpreted as an Euler angle definition of + * the rotation + * + * @param direction A vector interpreted as a direction. Client code + * responsible for not passing a 0-length vector, else a + * + * @returns threejs-math.EulerAngle instance + **/ + +export function lightRelativeRotation(direction: Vector3): Euler { + if (direction.length() == 0.0) + throw new Error("degenerate geometry: cameraRelativeRotation"); + + var unit_direction = direction.clone().divideScalar(direction.length()); + + // negative y axis is initial direction of DirectionalLight, SpotLight + // in draft 3D API + var ny_axis = new Vector3(0.0, -1.0, 0.0); + + var quat = new Quaternion().setFromUnitVectors(ny_axis, unit_direction); + var tmp = new Euler().setFromQuaternion(quat, "ZXY"); + // standard be setting the final intrinsic Y rotation, which is + // along desired direction, to 0 + return new Euler(tmp.x, 0.0, tmp.z, "ZXY"); +} + +/** +* Implements the convention that the 3 component values for the RotateTranform +* cass (properties x,y,z) are to be interpreted as Euler angles in the intrinsic XYZ +* order +* @param transform : A object with a Rotation member object, properties x,y,z + +* +* @returns threejs-math.EulerAngle instance. From this threejs-math functionsa +* allow conversion to other rotation representations. +**/ +export function eulerFromRotateTransform(transform: RotateTransform): Euler { + var eulerOrder: IOrder = "XYZ"; + var rdata: any = transform.getRotation(); + + return new Euler( + MathUtils.degToRad(rdata.x), + MathUtils.degToRad(rdata.y), + MathUtils.degToRad(rdata.z), + eulerOrder + ); +} + +/** + * Given an array of Transform instances, returns a single Matrix4 + * instance that represents the cumulative effect of the transforms + * in the order they appear in the array. + * + * @param transforms An array of Transform instances + * + * @returns A Matrix4 instance representing the cumulative effect of the transforms + **/ +export function combineTransformsToMatrix(transforms: Transform[]): Matrix4 { + const matrix = new Matrix4(); + + for (const transform of transforms) { + const tmat = new Matrix4(); + if (transform.isTranslateTransform) { + const translation: any = ( + transform as TranslateTransform + ).getTranslation(); + tmat.makeTranslation(translation.x, translation.y, translation.z); + } else if (transform.isRotateTransform) { + const euler = eulerFromRotateTransform(transform as RotateTransform); + tmat.makeRotationFromEuler(euler); + } else if (transform.isScaleTransform) { + const scale: any = (transform as ScaleTransform).getScale(); + tmat.makeScale(scale.x, scale.y, scale.z); + } + matrix.premultiply(tmat); + } + + return matrix; +} + +export type TransformSet = { + translation: Vector3; + rotation: Euler; + scale: Vector3; +}; + +export function combineTransformsToTRS(transforms: Transform[]): TransformSet { + const translation = new Vector3(); + const rotation = new Euler(); + const scale = new Vector3(1, 1, 1); + + for (const transform of transforms) { + if (transform.isTranslateTransform) { + const translationTransform: any = ( + transform as TranslateTransform + ).getTranslation(); + translation.add( + new Vector3( + translationTransform.x, + translationTransform.y, + translationTransform.z + ) + ); + } else if (transform.isRotateTransform) { + const euler = eulerFromRotateTransform(transform as RotateTransform); + const q1 = new Quaternion().setFromEuler(rotation); + const q2 = new Quaternion().setFromEuler(euler); + q1.premultiply(q2); + rotation.setFromQuaternion(q1, "XYZ"); + translation.applyEuler(euler); + } else if (transform.isScaleTransform) { + const scaleTransform: any = (transform as ScaleTransform).getScale(); + const newScale = new Vector3( + scaleTransform.x, + scaleTransform.y, + scaleTransform.z + ); + scale.multiply(newScale); + translation.multiply(newScale); + } + } + + return { translation, rotation, scale }; +} + +export function decomposeMatrix(matrix: Matrix4): { + translation: Vector3; + rotation: Euler; + scale: Vector3; +} { + const translation = new Vector3(); + const rotation = new Euler(); + const rotationQuaternion = new Quaternion(); + const scale = new Vector3(); + + matrix.decompose(translation, rotationQuaternion, scale); + rotation.setFromQuaternion(rotationQuaternion); + + return { translation, rotation, scale }; +} diff --git a/src/JSONLDResource.ts b/src/JSONLDResource.ts index 5b68b49a..bf6d59cb 100644 --- a/src/JSONLDResource.ts +++ b/src/JSONLDResource.ts @@ -23,4 +23,26 @@ export class JSONLDResource { return prop; } + + /** + A function that wraps the getProperty function, which client + code can use if it is needed to identify when the json value of + a property is an IRI -- Internationalized Resource Identifier + + If the value of the json value is a bare string, then it will be + wrapped in a json object with the string in the property 'id', + additionally that property will have a property 'isIRI' which will + be true for the literal string case, otherwise false meaning the + returned getProperty should be parsed as before. + + **/ + getPropertyAsObject(name: string): any { + const prop = this.getProperty(name); + + if (typeof prop === "string") return { id: prop, isIRI: true }; + else if (prop === Object(prop)) return prop; + else { + return null; + } + } } diff --git a/src/Light.ts b/src/Light.ts new file mode 100644 index 00000000..4a9fa6c4 --- /dev/null +++ b/src/Light.ts @@ -0,0 +1,108 @@ +import { + IManifestoOptions, + Utils, + AnnotationBody, + Color, + PointSelector, +} from "./internal"; + +export class Light extends AnnotationBody { + constructor(jsonld?: any, options?: IManifestoOptions) { + super(jsonld, options); + } + + getColor(): Color { + var hexColor = this.getProperty("color"); + if (hexColor) return Color.fromCSS(hexColor); + else return new Color([255, 255, 255]); // white light + } + + /** + * The implementation of the intensity is based on + * {@link https://github.com/IIIF/3d/blob/main/temp-draft-4.md | temp-draft-4.md } + * and the example 3D manifests + * {@link https://github.com/IIIF/3d/tree/main/manifests/3_lights | lights } + * on 24 Mar 2024. The intensity property in the manifest is an object + * with declared type 'Value', a numeric property named 'value' and a + * property named unit . This implementation will only work with a unit == 'relative' + * and it will be assumed that a relative unit value of 1.0 corresponds to the + * brightest light source a rendering engine supports. + * + * This code will implement a default intensity of 1.0 + **/ + getIntensity(): number { + var intObject = this.getProperty("intensity"); + if (intObject) { + try { + if (!(intObject.type === "Value" && intObject.unit === "relative")) + throw new Error(); + return intObject.value as number; + } catch (err) { + throw new Error( + "unable to interpret raw intensity object " + + JSON.stringify(intObject) + ); + } + } else return 1.0; + } + + /** + * As defined in the temp-draft-4.md ( + * https://github.com/IIIF/3d/blob/main/temp-draft-4.md#lights ; 12 May 2024) + * this quantity is the half-angle of the cone of the spotlight. + * + * The inconsistency between this definition of the angle and the definition of + * fieldOfView for PerspectiveCamera (where the property value defines the full angle) has + * already been noted: https://github.com/IIIF/api/issues/2284 + * + * provisional decision is to return undefined in case that this property + * is accessed in a light that is not a spotlight + * + * + * @returns number + + **/ + getAngle(): number | undefined { + if (this.isSpotLight()) { + return Number(this.getProperty("angle")); + } else { + return undefined; + } + } + + /** + * @return : if not null, is either a PointSelector, or an object + * with an id matching the id of an Annotation instance. + **/ + getLookAt(): object | PointSelector | null { + const rawObj = this.getPropertyAsObject("lookAt") ?? null; + if (rawObj == null) return null; + + const rawType = (rawObj["type"] || rawObj["@type"]) ?? null; + if (rawType == null) return null; + + if (rawType == "Annotation") { + return rawObj; + } + if (rawType == "PointSelector") { + return new PointSelector(rawObj); + } + throw new Error(`unidentified value of lookAt ${rawType}`); + } + + isAmbientLight(): boolean { + return Utils.normaliseType(this.getType() || "") === "ambientlight"; + } + + isDirectionalLight(): boolean { + return Utils.normaliseType(this.getType() || "") === "directionallight"; + } + + isPointLight(): boolean { + return Utils.normaliseType(this.getType() || "") === "pointlight"; + } + + isSpotLight(): boolean { + return Utils.normaliseType(this.getType() || "") === "spotlight"; + } +} diff --git a/src/Manifest.ts b/src/Manifest.ts index be6eec5b..0869068b 100644 --- a/src/Manifest.ts +++ b/src/Manifest.ts @@ -17,6 +17,19 @@ import { Utils, } from "./internal"; +/** + * @remarks Scenes are conveniently retrieved from a Manifest by iterating through + * Sequence in the Manifest, inner loop the Scenes in each sequence + * @see {@link Sequence } + * + * @example + * var manifest: Manifest; + * function doSomethingWithScene(scene:Scene)... + * ... + * foreach(var seq:Sequence of manifest.getSequences() + * foreach(var scene : Scene of seq.getScenes() + * doSomethingWithScene(scene); + **/ export class Manifest extends IIIFResource { public index: number = 0; private _allRanges: Range[] | null = null; @@ -34,6 +47,11 @@ export class Manifest extends IIIFResource { this._parseRanges(range, String(i)); } } + + // initialization the cached _annotationIdMap to null + // it will be populated if and only if client calls make a request + // to the getter annotationIdMap + this._annotationIdMap = null; } /** @deprecated Use getAccompanyingCanvas instead */ @@ -248,6 +266,9 @@ export class Manifest extends IIIFResource { return null; } + /** + * @returns Array of Sequence instances + **/ getSequences(): Sequence[] { if (this.items.length) { return this.items; @@ -326,4 +347,33 @@ export class Manifest extends IIIFResource { return null; } + + _annotationIdMap: any; + + /** + * Developer Note: The concept of the "id map" appear in the + * JSON-LD specification https://www.w3.org/TR/json-ld11/#dfn-id-map + * This functionality may be available as well in the 'nodeMap' code of the + * digitalbazaar/jsonld library + * + * this very simplified version just returns a mao of id -> Annotation nodes + * in manifest + * + * THe annotationIdMap is a Javascript object whose property names are + * IRI (id values) and property values are instances of the Annotation class + **/ + get annotationIdMap(): Object { + if (this._annotationIdMap == null) { + this._annotationIdMap = {}; + for (const seq of this.getSequences()) { + for (const scene of seq.getScenes()) + for (const anno of scene.getContent()) + this._annotationIdMap[anno.id] = anno; + for (const canvas of seq.getCanvases()) + for (const anno of canvas.getContent()) + this._annotationIdMap[anno.id] = anno; + } + } + return this._annotationIdMap; + } } diff --git a/src/ManifestResource.ts b/src/ManifestResource.ts index a480b69b..ce4f00ab 100644 --- a/src/ManifestResource.ts +++ b/src/ManifestResource.ts @@ -28,6 +28,16 @@ export class ManifestResource extends JSONLDResource { return Utils.normaliseType(this.getProperty("type")); } + /** + * returns the PropertyValue which in turn allows a language-specific string + * encoded in the json as the "label" property + * @example + * var label = manifest.getLabel().getValue(); // returns the string for default locale + * + * @example + * var label = manifest.getLabel().getValue(locale); // locale a string , examples + * // would be "fr", "en-US", + **/ getLabel(): PropertyValue { const label: any = this.getProperty("label"); @@ -38,6 +48,16 @@ export class ManifestResource extends JSONLDResource { return new PropertyValue([], this.options.locale); } + getSummary(): PropertyValue { + const summary: any = this.getProperty("summary"); + + if (summary) { + return PropertyValue.parse(summary, this.options.locale); + } + + return new PropertyValue([], this.options.locale); + } + getDefaultLabel(): string | null { return this.getLabel().getValue(this.options.locale); } @@ -157,6 +177,15 @@ export class ManifestResource extends JSONLDResource { return this.getIIIFResourceType() === IIIFResourceType.RANGE; } + // this different implementation is necessary until such time as the + // SCENE is added to the @iiif/vocabulary package. + isScene(): boolean { + return ( + this.getIIIFResourceType() === + Utils.normaliseType("Scene") + ); + } + isSequence(): boolean { return this.getIIIFResourceType() === IIIFResourceType.SEQUENCE; } diff --git a/src/PointSelector.ts b/src/PointSelector.ts new file mode 100644 index 00000000..ee9312bc --- /dev/null +++ b/src/PointSelector.ts @@ -0,0 +1,18 @@ +import { JSONLDResource } from "./internal"; + +import { Vector3 } from "threejs-math"; + +export class PointSelector extends JSONLDResource { + isPointSelector: boolean = true; + + constructor(jsonld: any) { + super(jsonld); + } + + /** + @returns the 3D coordinates of the point as a Vector3 instance. + **/ + getLocation(): Vector3 { + return new Vector3(this.__jsonld.x, this.__jsonld.y, this.__jsonld.z); + } +} diff --git a/src/PropertyValue.ts b/src/PropertyValue.ts index 7a7dee0f..dab2f00c 100644 --- a/src/PropertyValue.ts +++ b/src/PropertyValue.ts @@ -153,6 +153,10 @@ export class PropertyValue extends Array { // If any of the values have a language associated with them, the client // must display all of the values associated with the language that best // matches the language preference. + + if (locales.length == 0 && this._defaultLocale) + locales.push(this._defaultLocale as string); + const allLocales = Array.from(this.values()) .map((lv) => lv._locale) .filter((l) => l !== undefined) as string[]; @@ -253,6 +257,7 @@ export class PropertyValue extends Array { // Try to determine the available locale that best fits the user's preferences const matchingLocale = this.getSuitableLocale(locales); + if (matchingLocale) { const val = this.find((lv) => lv._locale === matchingLocale)!._value; return Array.isArray(val) ? val : [val]; diff --git a/src/RotateTransform.ts b/src/RotateTransform.ts new file mode 100644 index 00000000..b3bf9663 --- /dev/null +++ b/src/RotateTransform.ts @@ -0,0 +1,24 @@ +import { Transform } from "./internal"; + +export class RotateTransform extends Transform { + constructor(jsonld?: any) { + super(jsonld); + this.isRotateTransform = true; + } + + /** + * Returns an object with x,y,z attributes whose values are + * a counter-clockwise rotation in degrees about the fixed coordinate + * system axes. + * + * @returns object + **/ + getRotation(): object { + var retVal = {}; + for (const attrib of ["x", "y", "z"]) { + var raw = this.__jsonld[attrib]; + retVal[attrib] = raw !== undefined ? Number(raw) : 0.0; + } + return retVal; + } +} diff --git a/src/ScaleTransform.ts b/src/ScaleTransform.ts new file mode 100644 index 00000000..b0db338e --- /dev/null +++ b/src/ScaleTransform.ts @@ -0,0 +1,19 @@ +import { Transform } from "./internal"; + +export class ScaleTransform extends Transform { + constructor(jsonld?: any) { + super(jsonld); + this.isScaleTransform = true; + } + + getScale(): object { + var retVal = {}; + for (const attrib of ["x", "y", "z"]) { + var raw = this.__jsonld[attrib]; + + // note that default scaling is 1.0 + retVal[attrib] = raw !== undefined ? Number(raw) : 1.0; + } + return retVal; + } +} diff --git a/src/Scene.ts b/src/Scene.ts new file mode 100644 index 00000000..69901c7c --- /dev/null +++ b/src/Scene.ts @@ -0,0 +1,87 @@ +import { + Annotation, + AnnotationPage, + IManifestoOptions, + ManifestResource, + Color, +} from "./internal"; +// @ts-ignore +import flattenDeep from "lodash/flattenDeep"; + +export class Scene extends ManifestResource { + constructor(jsonld: any, options: IManifestoOptions) { + super(jsonld, options); + } + + // Presentation API 3.0 + getContent(): Annotation[] { + const content: Annotation[] = []; + + const items = this.__jsonld.items || this.__jsonld.content; + + if (!items) return content; + + // should be contained in an AnnotationPage + let annotationPage: AnnotationPage | null = null; + + if (items.length) { + annotationPage = new AnnotationPage(items[0], this.options); + } + + if (!annotationPage) { + return content; + } + + const annotations: Annotation[] = annotationPage.getItems(); + + for (let i = 0; i < annotations.length; i++) { + const a = annotations[i]; + const annotation = new Annotation(a, this.options); + content.push(annotation); + } + + return content; + } + + getAnnotationById(searchId: string): Annotation | null { + for (var anno of this.getContent()) if (anno.id === searchId) return anno; + return null; + } + + getBackgroundColor(): Color | null { + // regular expression intended to match strings like + // "#FF00FF" -- interpreted as three hexadecimal values + // in range 0-255 . Not that the \w escape matches digits, + // upper and lower case latin characters, and underscore + // currently only supports the form for CSS + // https://www.w3.org/wiki/CSS/Properties/color/RGB + // with 6 hexadecimal digits + + var bgc: string | undefined = this.getProperty("backgroundColor"); + if (bgc) return Color.fromCSS(bgc as string); + else return null; + } + + // Annotations not rendered as part of the Canvas + // Have non-painting motivations and are listed in Canvas annotations property, not items property + getNonContentAnnotations(): Annotation[] { + const annotationPages = (this.__jsonld.annotations || []) + .filter( + (annotationPage) => + annotationPage && annotationPage.type === "AnnotationPage" + ) + .map( + (annotationPage) => new AnnotationPage(annotationPage, this.options) + ) as AnnotationPage[]; + if (!annotationPages.length) return []; + + const annotationsNested = annotationPages.map((page) => + page.getItems() + ) as Annotation[][]; + const annotationsFlat = flattenDeep(annotationsNested) as Annotation[]; + + return annotationsFlat.map( + (annotation) => new Annotation(annotation, this.options) + ); + } +} diff --git a/src/Sequence.ts b/src/Sequence.ts index c5b6a4ec..a437660b 100644 --- a/src/Sequence.ts +++ b/src/Sequence.ts @@ -4,6 +4,7 @@ import { IManifestoOptions, Manifest, ManifestResource, + Scene, Thumb, Thumbnail, Utils, @@ -221,6 +222,26 @@ export class Sequence extends ManifestResource { return index; } + /** + * @returns Array of Scene instances in the Sequence + **/ + getScenes(): Scene[] { + const returnVal: Scene[] = []; + const low_items = this.__jsonld.elements || this.__jsonld; + + if (low_items) { + for (let i = 0; i < low_items.length; ++i) { + const c = low_items[i]; + if (c.type === "Scene") { + const scene: Scene = new Scene(c, this.options); + //scene.index = i; + returnVal.push(scene); + } + } + } + return returnVal; + } + getStartCanvasIndex(): number { const startCanvas: string = this.getStartCanvas(); diff --git a/src/SpecificResource.ts b/src/SpecificResource.ts new file mode 100644 index 00000000..6dd61859 --- /dev/null +++ b/src/SpecificResource.ts @@ -0,0 +1,104 @@ +import { + IManifestoOptions, + ManifestResource, + Annotation, + AnnotationBody, + AnnotationBodyParser, + Transform, + TransformParser, + PointSelector, +} from "./internal"; + +/** + Developer note: This implementation does not strictly adhere + to the description of SpecificResource in the Web Annotation Model + document https://www.w3.org/TR/annotation-model/ + section 4 : https://www.w3.org/TR/annotation-model/#specific-resources + + The getTransform() method returning an Array of 3D Transfom resources, is + an extension of SpecificResource beyond the web annotation model. +*/ +export class SpecificResource extends ManifestResource { + /* + property distinguishing instances of SpecificResource from instances of AnnotionBody. + The return type of the Annotation.getBody() method is an array of instances of the + union type ( AnnotationBody | SpecificResource ) + */ + isAnnotationBody: boolean = false; + + /* + property distinguishing instances of SpecificResource from instances of AnnotionBody. + The return type of the Annotation.getBody() method is an array of instances of the + union type ( AnnotationBody | SpecificResource ) + */ + isSpecificResource: boolean = true; + + constructor(jsonld: any, options?: IManifestoOptions) { + super(jsonld, options); + this.isSpecificResource = true; + } + + getScope(): object | Annotation | null { + var raw = this.getPropertyAsObject("scope"); + if (raw?.isIRI) return raw; + + if (raw) { + const scope = [].concat(raw)[0]; + if (scope && scope["type"] === "Annotation") + return new Annotation(scope, this.options); + } + + return null; + } + + getSource(): object | AnnotationBody { + var raw = this.getPropertyAsObject("source"); + if (raw.isIRI) return raw; + + /* + this logic gets a little convoluted, because we have to preserve + the cases where the raw json is an array for the sources of a + SpecificResource applied to an annotation body, while for a target + of an Annotation we just want a single object + */ + // case of a source of a SpecificResource which is an Annotation target + if (raw) { + var containerTypes = ["Scene", "Canvas"]; + const singleItem = [].concat(raw)[0]; + if (containerTypes.includes(singleItem["type"])) return singleItem; + } + if (raw) { + var item = [].concat(raw)[0]; + if (item) { + return AnnotationBodyParser.BuildFromJson(item, this.options); + } + } + throw new Error("cannot resolve Source " + JSON.stringify(raw)); + } + + getSelector(): PointSelector | null { + const raw = this.getProperty("selector"); + if (raw) { + var item = [].concat(raw)[0]; + + if (item) { + if (item["type"] === "PointSelector") return new PointSelector(item); + } + throw new Error( + "unable to resolve SpecificResource selector " + + JSON.stringify(this.__jsonld) + ); + } + return null; + } + + getTransform(): Transform[] { + var retVal: Transform[] = []; + var transformItems = this.getProperty("transform"); + for (var i = 0; i < transformItems.length; ++i) { + var transformItem = transformItems[i]; + retVal.push(TransformParser.BuildFromJson(transformItem)); + } + return retVal; + } +} diff --git a/src/TextualBody.ts b/src/TextualBody.ts new file mode 100644 index 00000000..51dfc78e --- /dev/null +++ b/src/TextualBody.ts @@ -0,0 +1,42 @@ +import { + IManifestoOptions, + AnnotationBody, + SpecificResource, +} from "./internal"; + +/** +An implementation of the TextualBody class (class in JSON-LD sense) +as it is described in Web Annotation Data Model Section 3.2.4 +https://www.w3.org/TR/annotation-model/#embedded-textual-body +**/ +export class TextualBody extends AnnotationBody { + constructor(jsonld?: any, options?: IManifestoOptions) { + super(jsonld, options); + } + + /** +The simple string that is the data content of this resource +will return empty string as a default value +**/ + getValue(): string { + return this.getProperty("value") || ""; + } + + /** +Returns a specific resource representing the TextualBody position if +present, otherwise null. +**/ + getPosition(): SpecificResource | null { + const rawPosition = this.getPropertyAsObject("position") ?? null; + if (rawPosition == null) return null; + + if (rawPosition.type && rawPosition.type == "SpecificResource") { + return new SpecificResource(rawPosition, this.options); + } else { + throw new Error("unknown position type specified"); + } + } + get Position(): SpecificResource | null { + return this.getPosition(); + } +} diff --git a/src/Transform.ts b/src/Transform.ts new file mode 100644 index 00000000..c5023e69 --- /dev/null +++ b/src/Transform.ts @@ -0,0 +1,13 @@ +import { JSONLDResource } from "./internal"; + +export abstract class Transform extends JSONLDResource { + constructor(jsonld?: any) { + super(jsonld); + this.isTransform = true; + } + + isTransform: boolean = true; + isRotateTransform: boolean | undefined; + isScaleTransform: boolean | undefined; + isTranslateTransform: boolean | undefined; +} diff --git a/src/TransformParser.ts b/src/TransformParser.ts new file mode 100644 index 00000000..b828c8e7 --- /dev/null +++ b/src/TransformParser.ts @@ -0,0 +1,18 @@ +import { + Transform, + TranslateTransform, + RotateTransform, + ScaleTransform, +} from "./internal"; + +export class TransformParser { + static BuildFromJson(jsonld: any): Transform { + if (jsonld.type === "TranslateTransform") + return new TranslateTransform(jsonld); + else if (jsonld.type === "RotateTransform") + return new RotateTransform(jsonld); + else if (jsonld.type === "ScaleTransform") + return new ScaleTransform(jsonld); + else throw new Error("Unknown transform type " + jsonld.type); + } +} diff --git a/src/TranslateTransform.ts b/src/TranslateTransform.ts new file mode 100644 index 00000000..08ce1c57 --- /dev/null +++ b/src/TranslateTransform.ts @@ -0,0 +1,17 @@ +import { Transform } from "./internal"; + +export class TranslateTransform extends Transform { + constructor(jsonld?: any) { + super(jsonld); + this.isTranslateTransform = true; + } + + getTranslation(): object { + var retVal = {}; + for (const attrib of ["x", "y", "z"]) { + var raw = this.__jsonld[attrib]; + retVal[attrib] = raw !== undefined ? Number(raw) : 0.0; + } + return retVal; + } +} diff --git a/src/index.ts b/src/index.ts index 5939414e..2f0018b3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,10 +4,24 @@ import { IIIFResource } from "./IIIFResource"; import { IManifestoOptions } from "./IManifestoOptions"; import { Utils } from "./Utils"; -export const loadManifest: (url: string) => Promise = (url: string) => { +/** +Initiates downloading an IIIF manifest json file from URL. Returns a Promise +to allow subsequent processing on a successful fetch. + +@param url string containing the URL to Fetch +@returns Promise The object returned through the Promise is the javascript object obtained by deserializing the json text. +**/ +export const loadManifest: (url: string) => Promise = (url: string) => { return Utils.loadManifest(url); }; +/** +Parses IIIF manifest file to return a manifesto Manifest instance + +@param manifest Either a string containing text of a manifest file or an javascript object obtained by deserializing by the JSON.parse function a manifest file. +@param options? TODO Not yet documented +@returns instance of Manifest class. +**/ export const parseManifest: ( manifest: any, options?: IManifestoOptions | undefined diff --git a/src/internal.ts b/src/internal.ts index d6f48c06..0b33b5b6 100644 --- a/src/internal.ts +++ b/src/internal.ts @@ -1,9 +1,19 @@ export * from "./JSONLDResource"; +export * from "./Transform"; export * from "./ManifestResource"; export * from "./Resource"; export * from "./IIIFResource"; -export * from "./Annotation"; +export * from "./SpecificResource"; +//export * from "./SpecificResourceForTarget"; +//export * from "./SpecificResourceForBody"; + export * from "./AnnotationBody"; +export * from "./Light"; +export * from "./Camera"; +export * from "./TextualBody"; +export * from "./AnnotationBodyParser"; +export * from "./Annotation"; + export * from "./AnnotationList"; export * from "./AnnotationPage"; export * from "./Canvas"; @@ -21,15 +31,28 @@ export * from "./LanguageMap"; export * from "./PropertyValue"; export * from "./Manifest"; export * from "./ManifestType"; +export * from "./PointSelector"; export * from "./Range"; export * from "./Rendering"; +export * from "./Scene"; export * from "./Sequence"; export * from "./Serialisation"; export * from "./Service"; export * from "./Size"; + export * from "./StatusCode"; export * from "./Thumb"; export * from "./Thumbnail"; +export * from "./Transform"; + +export * from "./TranslateTransform"; +export * from "./TransformParser"; export * from "./TreeNode"; export * from "./TreeNodeType"; export * from "./Utils"; +export * from "./TranslateTransform"; +export * from "./RotateTransform"; +export * from "./ScaleTransform"; +export * from "./Color"; + +export * from "./Geometry3d"; diff --git a/test/fixtures/manifests_3d.js b/test/fixtures/manifests_3d.js new file mode 100644 index 00000000..67790eb4 --- /dev/null +++ b/test/fixtures/manifests_3d.js @@ -0,0 +1,7 @@ +module.exports = { + "model_origin" : { + local: "http://localhost:3001/model_origin.json", + remote : "https://raw.githubusercontent.com/IIIF/3d/eds/manifests/1_basic_model_in_scene/model_origin.json" + } +}; + diff --git a/test/index.js b/test/index.js index 92446cf6..81c7fbec 100644 --- a/test/index.js +++ b/test/index.js @@ -69,7 +69,6 @@ importTest('no-nav-ranges', './tests/no-nav-ranges'); importTest('plato', './tests/plato'); importTest('poster-canvas', './tests/poster-canvas'); importTest('potterselectric', './tests/potterselectric'); -importTest('pres3-3d', './tests/pres3-3d'); importTest('pres3-av-basic', './tests/pres3-av-basic'); importTest('pres3-collection', './tests/pres3-collection'); importTest('pres3-collection2', './tests/pres3-collection2'); diff --git a/test/tests/static-thumbs.js b/test/tests/static-thumbs.js index eb21378d..735405e8 100644 --- a/test/tests/static-thumbs.js +++ b/test/tests/static-thumbs.js @@ -19,10 +19,11 @@ describe('static thumbs', function() { expect(sequence).to.exist; }); - it('has thumbnails', function() { + // for deprecation: see src/Thumbs.js ; src/Sequence.js getThumbs method + it('has thumbnails: uses deprecated method Sequence.getThumbs', function() { thumbnails = sequence.getThumbs(); var thumbnail = thumbnails[0]; expect(thumbnail.uri).to.equal('https://edsilv.github.io/biiif-workshop/collection/_abyssinian/thumb.jpeg'); }); -}); \ No newline at end of file +}); diff --git a/test/tests_3d/10_content_state/astronaut_comment_scope.js b/test/tests_3d/10_content_state/astronaut_comment_scope.js new file mode 100644 index 00000000..5224cfca --- /dev/null +++ b/test/tests_3d/10_content_state/astronaut_comment_scope.js @@ -0,0 +1,116 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); +//var manifests_3d = require('../fixtures/manifests_3d'); + + +var ExternalResourceType = require('@iiif/vocabulary/dist-commonjs/').ExternalResourceType; +var MediaType = require('@iiif/vocabulary/dist-commonjs/').MediaType; + + +let manifest, sequence, scene , annotation, body, comments; + +let manifest_url = { + local: "", + remote : "https://raw.githubusercontent.com/IIIF/3d/astronaut_comment_scope/manifests/10_content_state/astronaut_comment_scope.json" + }.remote; + +describe('astronaut_comment_scope', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + it('has a scene', function() { + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()); + }); + + + it('with one annotation', function(){ + var annotations = scene.getContent(); + expect(annotations.length).to.equal(1); + annotation = annotations[0]; + }); + + it('that target the scene', function(){ + var target = annotation.getTarget(); + target.id.should.exist; + target.id.should.equal( scene.id ); + + if (target.isSpecificResource) + target.getSource().should.exist; + }); + + it('has two commenting annotations', function(){ + comments = scene.getNonContentAnnotations(); + expect(comments.length).to.equal(2); + }); + + it('that target the Scene with PointSelector', function(){ + const comment = comments[0]; + + const target = comment.getTarget(); + expect( target.isSpecificResource ); + expect( target.getSource()).to.exist; + + const selector = target.getSelector(); + expect( selector.isPointSelector ); + + const location = selector.getLocation(); + expect(location.x).to.exist; + expect(location.y).to.exist; + expect(location.z).to.exist; + }); + + it('and that have scope content state', function(){ + const comment = comments[0]; + + const target = comment.getTarget(); + expect( target.isSpecificResource ); + + const scopeAnnotation = target.getScope(); + expect(scopeAnnotation.isAnnotation()).to.be.true; + expect(scopeAnnotation.getMotivation()[0]).to.equal('contentState'); + }); + + it('with camera annotation', function(){ + const comment = comments[0]; + + const scopeContentItems = comment.getScopeContent(); + expect(scopeContentItems.length).to.equal(1); + + const annotation = scopeContentItems[0]; + expect(annotation.isAnnotation()).to.be.true; + expect(annotation.getMotivation()[0]).to.equal('painting'); + + const body = annotation.getBody()[0]; + expect(body.isSpecificResource()).to.equal(false); + expect(body instanceof manifesto.Camera).to.equal(true); + expect(body.isPerspectiveCamera()).to.equal(true); + + const target = annotation.getTarget(); + expect(target.isSpecificResource); + expect(target.getSource()).to.exist; + const selector = target.getSelector(); + expect(selector.isPointSelector); + const location = selector.getLocation(); + location.x.should.equal(0); + location.y.should.equal(2.010847091674805); + location.z.should.equal(9.11616179783789); + + const lookAtLocation = body.getLookAt()?.getLocation(); + expect(lookAtLocation.x).to.eq(0); + expect(lookAtLocation.y).to.eq(2.0108470916748047); + expect(lookAtLocation.z).to.eq(-0.012333005666732798); + }); +}); diff --git a/test/tests_3d/1_basic_model_in_scene/model_origin.js b/test/tests_3d/1_basic_model_in_scene/model_origin.js new file mode 100644 index 00000000..48131417 --- /dev/null +++ b/test/tests_3d/1_basic_model_in_scene/model_origin.js @@ -0,0 +1,91 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); +//var manifests_3d = require('../fixtures/manifests_3d'); + + +var ExternalResourceType = require('@iiif/vocabulary/dist-commonjs/').ExternalResourceType; +var MediaType = require('@iiif/vocabulary/dist-commonjs/').MediaType; + + +let manifest, sequence, scene , annotation, body; + +let manifest_url = { + local: "http://localhost:3001/model_origin.json", + remote : "https://raw.githubusercontent.com/IIIF/3d/eds/manifests/1_basic_model_in_scene/model_origin.json" + }.remote; + +describe('model_origin', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + it('has a scene', function() { + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()).to.be.ok; + }); + + + it('with one annotation', function(){ + var annotations = scene.getContent(); + expect(annotations.length).to.equal(1); + annotation = annotations[0]; + }); + + it('that target the scene', function(){ + var target = annotation.getTarget(); + target.id.should.exist; + target.id.should.equal( scene.id ); + + if (target.isSpecificResource) + target.getSource().should.exist; + + }); + + it('and body is an AnnotationBody', function(){ + body = annotation.getBody()[0]; + expect( body.isModel() ).to.equal(true); + expect(Array.isArray(body)).to.equal(false); + expect(body.isSpecificResource()).to.equal(false); + body.getType().should.equal(ExternalResourceType.MODEL); + }); + + it('and body has IIIFResourceType', function(){ + body = annotation.getBody()[0]; + expect(body.getIIIFResourceType()).to.exist; + + let test = ( body.getIIIFResourceType() == ExternalResourceType.MODEL ); + expect(test).to.equal(true); + + }); + + it('and body has no transforms', function(){ + body = annotation.getBody()[0]; + expect(body.getTransform()).to.not.exist; + }); + + it('body id looks like a model url', function(){ + body.id.should.include('astronaut.glb'); + }); + + it('body resource URI id looks like a model url', function(){ + body.getResourceID().should.include('astronaut.glb'); + }); + + it('body Format (if defined) is glb or glTF', function(){ + var mediaType = body.getFormat(); + if (mediaType) + ['MediaType.GLB, MediaType.GLTF'].should.include(mediaType); + }); + +}); diff --git a/test/tests_3d/1_basic_model_in_scene/model_origin_bgcolor.js b/test/tests_3d/1_basic_model_in_scene/model_origin_bgcolor.js new file mode 100644 index 00000000..a1d90ec5 --- /dev/null +++ b/test/tests_3d/1_basic_model_in_scene/model_origin_bgcolor.js @@ -0,0 +1,45 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); +//var manifests_3d = require('../fixtures/manifests_3d'); + + +var ExternalResourceType = require('@iiif/vocabulary/dist-commonjs/').ExternalResourceType; +var MediaType = require('@iiif/vocabulary/dist-commonjs/').MediaType; + + +let manifest, sequence, scene; + +let manifest_url = { + local: "http://localhost:3001/model_origin_bgcolor.json", + remote : "https://raw.githubusercontent.com/IIIF/3d/main/manifests/1_basic_model_in_scene/model_origin_bgcolor.json" + }.remote; + +describe('model_origin', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + it('has a scene', function() { + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()); + }); + + it('with a defined background color', function(){ + var backgroundColor = scene.getBackgroundColor(); + expect(backgroundColor).to.exist; + backgroundColor.red.should.equal(255); + backgroundColor.green.should.equal(0); + backgroundColor.blue.should.equal(254); + }); +}); diff --git a/test/tests_3d/2_cameras/orthographic_camera_lookat_point.js b/test/tests_3d/2_cameras/orthographic_camera_lookat_point.js new file mode 100644 index 00000000..0333ca2b --- /dev/null +++ b/test/tests_3d/2_cameras/orthographic_camera_lookat_point.js @@ -0,0 +1,104 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); + +var threejs_math = require('threejs-math'); + +let manifest, annotations, scene; + +let manifest_url = { + local: "", + remote : "https://raw.githubusercontent.com/vincentmarchetti/iiif3dtsg/kshell-dev/manifests/2_cameras/orthographic_camera_lookat_point.json" + }.remote; + +describe('orthographic_camera_lookat_point', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + + it('has a scene with two annotation', function(){ + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()).to.be.ok; + annotations = scene.getContent(); + expect(annotations.length).to.equal(2); + + + }); + + it('has 1st annotation a Camera', function(){ + var camera_anno = annotations[1]; + let camera = camera_anno.getBody()[0]; + + expect(camera.isSpecificResource()).to.equal(false); + expect(camera instanceof manifesto.Camera).to.equal(true); + expect(camera.isPerspectiveCamera()).to.not.be.ok; + expect(camera.isOrthographicCamera()).to.be.ok; + expect(camera.isModel()).to.equal(false,"checking isModel()=false"); + expect(camera.ViewHeight).to.equal(3.5); + + let lookedAt = camera.LookAt; + expect( lookedAt , "find the lookAt annotation.id?").to.exist; + + let lookedAtLocation = null; + if ( lookedAt.isPointSelector ){ + lookedAtLocation = lookedAt.getLocation(); + } + else{ + let lookedAtAnnotation = scene.getAnnotationById( lookedAt.id ); + expect( lookedAtAnnotation, "find the lookAt annotation in scene?").to.exist; + lookedAtLocation = lookedAtAnnotation.LookAtLocation; + } + expect( lookedAtLocation ).to.exist; + + let lookedFromLocation = camera_anno.LookAtLocation ; + let direction = lookedAtLocation.clone().sub( lookedFromLocation ); + let exact_unit_direction = direction.clone().divideScalar( direction.length() ); + + + expect( [direction.x, direction.y,direction.z]).to.deep.equal([2.0,-2.0,10.0]); + + let exact_coords = [exact_unit_direction.x, exact_unit_direction.y,exact_unit_direction.z].join(", "); + //console.log(`exact direction ( ${exact_coords} )`) + let euler = manifesto.cameraRelativeRotation( direction ); + + // next want to evaluate the result: + // 1. create a quaternion representation from the euler + // 2. show that athis rotation does 3 things to the unit vectors + // attached to the camera + // 2.1 the camera z axis transforms to be parallel to exact_unit_direction + // 2.2 the rotated camera x axis is perpendicular to global z axis + // 2.3 rotated camera y axis z component is positive + let quat = new threejs_math.Quaternion().setFromEuler( euler ); + + let camera_direction = new threejs_math.Vector3( 0.0, 0.0, -1.0 ).applyQuaternion( quat ); + + let camera_direction_coords = [camera_direction.x, camera_direction.y, camera_direction.z ]; + //console.log(`camera direction ( ${camera_direction_coords} )`) + + let direction_error = camera_direction.clone().sub(exact_unit_direction); + let direction_error_coords = [ direction_error.x, direction_error.y, direction_error.z ]; + //console.log(`direction error ( ${direction_error_coords} )`) + + expect( direction_error.length() ).to.be.below( 1.0e-8 ); + + let camera_x_axis = new threejs_math.Vector3( 1.0, 0.0, 0.0 ).applyQuaternion( quat ); + expect( Math.abs( camera_x_axis.y )).to.be.below(1.0e-8); + + let camera_y_axis = new threejs_math.Vector3( 0.0, 1.0, 0.0 ).applyQuaternion( quat ); + expect( camera_y_axis.z ).to.be.above(0.0); + + }); +}); diff --git a/test/tests_3d/2_cameras/positioned_camera_lookat_anno.js b/test/tests_3d/2_cameras/positioned_camera_lookat_anno.js new file mode 100644 index 00000000..11249d5f --- /dev/null +++ b/test/tests_3d/2_cameras/positioned_camera_lookat_anno.js @@ -0,0 +1,89 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); + +var threejs_math = require('threejs-math'); + +let manifest, annotations, scene; + +let manifest_url = { + local: "", + remote : "https://raw.githubusercontent.com/IIIF/3d/main/manifests/2_cameras/positioned_camera_lookat_anno.json" + }.remote; + +describe('positioned_camera_lookat_anno', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + + it('has a scene with two annotation', function(){ + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()).to.be.ok; + annotations = scene.getContent(); + expect(annotations.length).to.equal(2); + }); + + it('has 1st annotation a Camera', function(){ + var camera_anno = annotations[1]; + let camera = camera_anno.getBody()[0]; + + expect(camera.isSpecificResource()).to.equal(false); + expect(camera instanceof manifesto.Camera).to.equal(true); + expect(camera.isPerspectiveCamera()).to.equal(true); + expect(camera.isModel()).to.equal(false,"checking isModel()=false"); + + + let lookedAt = camera.LookAt; + expect( lookedAt , "find the lookAt annotation.id?").to.exist; + + let lookedAtAnnotation = scene.getAnnotationById( lookedAt.id ); + expect( lookedAtAnnotation, "find the lookAt annotation in scene?").to.exist; + + let lookedAtLocation = lookedAtAnnotation.LookAtLocation; + expect( lookedAtLocation ).to.exist; + + let testLocation = [lookedAtLocation.x,lookedAtLocation.y,lookedAtLocation.z]; + expect(testLocation).to.deep.equal( [0.0,0.0,0.0]); + + let lookedFromLocation = camera_anno.LookAtLocation ; + let direction = lookedAtLocation.clone().sub( lookedFromLocation ); + let exact_unit_direction = direction.clone().divideScalar( direction.length() ); + + expect( [direction.x, direction.y,direction.z]).to.deep.equal([0.0,-3.0,10.0]); + + let euler = manifesto.cameraRelativeRotation( direction ); + + // next want to evaluate the result: + // 1. create a quaternion representation from the euler + // 2. show that athis rotation does 3 things to the unit vectors + // attached to the camera + // 2.1 the camera z axis transforms to be parallel to exact_unit_direction + // 2.2 the rotated camera x axis is perpendicular to global z axis + // 2.3 rotated camera y axis z component is positive + let quat = new threejs_math.Quaternion().setFromEuler( euler ); + + let camera_direction = new threejs_math.Vector3( 0.0, 0.0, -1.0 ).applyQuaternion( quat ); + let direction_error = camera_direction.clone().sub(exact_unit_direction).length(); + expect( direction_error ).to.be.below( 1.0e-8 ); + + let camera_x_axis = new threejs_math.Vector3( 1.0, 0.0, 0.0 ).applyQuaternion( quat ); + expect( Math.abs( camera_x_axis.y )).to.be.below(1.0e-8); + + let camera_y_axis = new threejs_math.Vector3( 0.0, 1.0, 0.0 ).applyQuaternion( quat ); + expect( camera_y_axis.z ).to.be.above(0.0); + + }); +}); diff --git a/test/tests_3d/2_cameras/positioned_camera_lookat_point.js b/test/tests_3d/2_cameras/positioned_camera_lookat_point.js new file mode 100644 index 00000000..3c2946c1 --- /dev/null +++ b/test/tests_3d/2_cameras/positioned_camera_lookat_point.js @@ -0,0 +1,103 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); + +var threejs_math = require('threejs-math'); + +let manifest, annotations, scene; + +let manifest_url = { + local: "", + remote : "https://raw.githubusercontent.com/IIIF/3d/main/manifests/2_cameras/positioned_camera_lookat_point.json" + }.remote; + +describe('positioned_camera_lookat_point', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + + it('has a scene with two annotation', function(){ + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()).to.be.ok; + annotations = scene.getContent(); + expect(annotations.length).to.equal(2); + + + }); + + it('has 1st annotation a Camera', function(){ + var camera_anno = annotations[1]; + let camera = camera_anno.getBody()[0]; + + expect(camera.isSpecificResource()).to.equal(false); + expect(camera instanceof manifesto.Camera).to.equal(true); + expect(camera.isPerspectiveCamera()).to.equal(true); + expect(camera.isModel()).to.equal(false,"checking isModel()=false"); + + + let lookedAt = camera.LookAt; + expect( lookedAt , "find the lookAt annotation.id?").to.exist; + + let lookedAtLocation = null; + if ( lookedAt.isPointSelector ){ + lookedAtLocation = lookedAt.getLocation(); + } + else{ + let lookedAtAnnotation = scene.getAnnotationById( lookedAt.id ); + expect( lookedAtAnnotation, "find the lookAt annotation in scene?").to.exist; + lookedAtLocation = lookedAtAnnotation.LookAtLocation; + } + expect( lookedAtLocation ).to.exist; + + let lookedFromLocation = camera_anno.LookAtLocation ; + let direction = lookedAtLocation.clone().sub( lookedFromLocation ); + let exact_unit_direction = direction.clone().divideScalar( direction.length() ); + + + expect( [direction.x, direction.y,direction.z]).to.deep.equal([2.0,-2.0,10.0]); + + let exact_coords = [exact_unit_direction.x, exact_unit_direction.y,exact_unit_direction.z].join(", "); + //console.log(`exact direction ( ${exact_coords} )`) + let euler = manifesto.cameraRelativeRotation( direction ); + + // next want to evaluate the result: + // 1. create a quaternion representation from the euler + // 2. show that athis rotation does 3 things to the unit vectors + // attached to the camera + // 2.1 the camera z axis transforms to be parallel to exact_unit_direction + // 2.2 the rotated camera x axis is perpendicular to global z axis + // 2.3 rotated camera y axis z component is positive + let quat = new threejs_math.Quaternion().setFromEuler( euler ); + + let camera_direction = new threejs_math.Vector3( 0.0, 0.0, -1.0 ).applyQuaternion( quat ); + + let camera_direction_coords = [camera_direction.x, camera_direction.y, camera_direction.z ]; + //console.log(`camera direction ( ${camera_direction_coords} )`) + + let direction_error = camera_direction.clone().sub(exact_unit_direction); + let direction_error_coords = [ direction_error.x, direction_error.y, direction_error.z ]; + //console.log(`direction error ( ${direction_error_coords} )`) + + expect( direction_error.length() ).to.be.below( 1.0e-8 ); + + let camera_x_axis = new threejs_math.Vector3( 1.0, 0.0, 0.0 ).applyQuaternion( quat ); + expect( Math.abs( camera_x_axis.y )).to.be.below(1.0e-8); + + let camera_y_axis = new threejs_math.Vector3( 0.0, 1.0, 0.0 ).applyQuaternion( quat ); + expect( camera_y_axis.z ).to.be.above(0.0); + + }); +}); diff --git a/test/tests_3d/2_cameras/positioned_camera_lookat_specific_resource.js b/test/tests_3d/2_cameras/positioned_camera_lookat_specific_resource.js new file mode 100644 index 00000000..77b081f0 --- /dev/null +++ b/test/tests_3d/2_cameras/positioned_camera_lookat_specific_resource.js @@ -0,0 +1,105 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); + +var threejs_math = require('threejs-math'); + +let manifest, annotations, scene; + +let manifest_url = { + local: "", + remote : "https://raw.githubusercontent.com/IIIF/3d/refs/heads/camera_look_at_specific_resource/manifests/2_cameras/positioned_camera_lookat_specific_resource.json" + }.remote; + +describe('positioned_camera_lookat_specific_resource', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + + it('has a scene with two annotation', function(){ + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()).to.be.ok; + annotations = scene.getContent(); + expect(annotations.length).to.equal(2); + + + }); + + it('has 1st annotation a Camera', function(){ + var camera_anno = annotations[1]; + let camera = camera_anno.getBody()[0]; + + expect(camera.isSpecificResource()).to.equal(false); + expect(camera instanceof manifesto.Camera).to.equal(true); + expect(camera.isPerspectiveCamera()).to.equal(true); + expect(camera.isModel()).to.equal(false,"checking isModel()=false"); + + + let lookedAt = camera.LookAt; + expect( lookedAt , "find the lookAt annotation.id?").to.exist; + + let lookedAtLocation = null; + if ( lookedAt.isPointSelector ){ + lookedAtLocation = lookedAt.getLocation(); + } else if ( lookedAt instanceof manifesto.SpecificResource ) { + expect(lookedAt.getSelector()?.isPointSelector).to.equal(true); + lookedAtLocation = lookedAt.getSelector().getLocation(); + } else { + let lookedAtAnnotation = scene.getAnnotationById( lookedAt.id ); + expect( lookedAtAnnotation, "find the lookAt annotation in scene?").to.exist; + lookedAtLocation = lookedAtAnnotation.LookAtLocation; + } + expect( lookedAtLocation ).to.exist; + + let lookedFromLocation = camera_anno.LookAtLocation ; + let direction = lookedAtLocation.clone().sub( lookedFromLocation ); + let exact_unit_direction = direction.clone().divideScalar( direction.length() ); + + + expect( [direction.x, direction.y,direction.z]).to.deep.equal([2.0,-2.0,10.0]); + + let exact_coords = [exact_unit_direction.x, exact_unit_direction.y,exact_unit_direction.z].join(", "); + //console.log(`exact direction ( ${exact_coords} )`) + let euler = manifesto.cameraRelativeRotation( direction ); + + // next want to evaluate the result: + // 1. create a quaternion representation from the euler + // 2. show that athis rotation does 3 things to the unit vectors + // attached to the camera + // 2.1 the camera z axis transforms to be parallel to exact_unit_direction + // 2.2 the rotated camera x axis is perpendicular to global z axis + // 2.3 rotated camera y axis z component is positive + let quat = new threejs_math.Quaternion().setFromEuler( euler ); + + let camera_direction = new threejs_math.Vector3( 0.0, 0.0, -1.0 ).applyQuaternion( quat ); + + let camera_direction_coords = [camera_direction.x, camera_direction.y, camera_direction.z ]; + //console.log(`camera direction ( ${camera_direction_coords} )`) + + let direction_error = camera_direction.clone().sub(exact_unit_direction); + let direction_error_coords = [ direction_error.x, direction_error.y, direction_error.z ]; + //console.log(`direction error ( ${direction_error_coords} )`) + + expect( direction_error.length() ).to.be.below( 1.0e-8 ); + + let camera_x_axis = new threejs_math.Vector3( 1.0, 0.0, 0.0 ).applyQuaternion( quat ); + expect( Math.abs( camera_x_axis.y )).to.be.below(1.0e-8); + + let camera_y_axis = new threejs_math.Vector3( 0.0, 1.0, 0.0 ).applyQuaternion( quat ); + expect( camera_y_axis.z ).to.be.above(0.0); + + }); +}); diff --git a/test/tests_3d/3_lights/ambient_green_light.js b/test/tests_3d/3_lights/ambient_green_light.js new file mode 100644 index 00000000..aa6ac9f8 --- /dev/null +++ b/test/tests_3d/3_lights/ambient_green_light.js @@ -0,0 +1,57 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); +//var manifests_3d = require('../fixtures/manifests_3d'); + + +var ExternalResourceType = require('@iiif/vocabulary/dist-commonjs/').ExternalResourceType; +var MediaType = require('@iiif/vocabulary/dist-commonjs/').MediaType; + + +let manifest, sequence, scene , model, body, ambient_light; + +let manifest_url = { + local: "http://localhost:3001/model_origin.json", + remote : "https://raw.githubusercontent.com/IIIF/3d/main/manifests/3_lights/ambient_green_light.json" + }.remote; + +describe('model_origin', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + + it('has a scene with two annotation', function(){ + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()).to.be.ok; + var annotations = scene.getContent(); + expect(annotations.length).to.equal(2); + ambient_light = annotations[1].getBody()[0]; + + }); + + it('with an ambient light', function(){ + expect(ambient_light.isModel()).to.not.be.ok; + expect(ambient_light instanceof manifesto.Light).to.equal(true); + expect(ambient_light.isAmbientLight()).to.equal(true); + + var color = ambient_light.getColor(); + expect(color.red).to.equal(0); + expect(color.green).to.equal(255); + expect(color.blue).to.equal(0); + + expect(ambient_light.getIntensity()).to.equal(0.5); + }); +}); diff --git a/test/tests_3d/3_lights/direction_light_transform_rotate.js b/test/tests_3d/3_lights/direction_light_transform_rotate.js new file mode 100644 index 00000000..c2918e9e --- /dev/null +++ b/test/tests_3d/3_lights/direction_light_transform_rotate.js @@ -0,0 +1,80 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); +//var manifests_3d = require('../fixtures/manifests_3d'); + + +var ExternalResourceType = require('@iiif/vocabulary/dist-commonjs/').ExternalResourceType; +var MediaType = require('@iiif/vocabulary/dist-commonjs/').MediaType; + + +let manifest, sequence, scene , model, body, annotations; + +let manifest_url = { + local: "http://localhost:3001/model_origin.json", + remote : "https://raw.githubusercontent.com/IIIF/3d/main/manifests/3_lights/direction_light_transform_rotate.json" + }.remote; + +describe('model_origin', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + + it('has a scene with two annotation', function(){ + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()).to.be.ok; + annotations = scene.getContent(); + expect(annotations.length).to.equal(2); + }); + + + it('with a directional light', function(){ + var directional_light_target = annotations[1].getTarget(); + expect(directional_light_target).to.exist; + + + var directional_light_body = annotations[1].getBody()[0]; + //console.log("directional_light_body.isSpecificResource() " + directional_light_body.isSpecificResource()); + + expect(directional_light_body.isSpecificResource()).to.equal(true); + directional_light_transform = directional_light_body; + directional_light = directional_light_body.getSource(); + + expect(directional_light.isModel()).to.not.be.ok; + expect(directional_light instanceof manifesto.Light).to.equal(true); + expect(directional_light.isAmbientLight()).to.not.be.ok; + expect(directional_light.isDirectionalLight()).to.equal(true); + + var color = directional_light.getColor(); + // test for default color + expect(color.red).to.equal(255); + expect(color.green).to.equal(255); + expect(color.blue).to.equal(255); + + // test for default intensity + expect(directional_light.getIntensity()).to.equal(1.0); + + + var transforms = directional_light_transform.getTransform(); + expect( transforms ).to.exist; + + + }); + + + + +}); diff --git a/test/tests_3d/3_lights/spotlight_lookat_point.js b/test/tests_3d/3_lights/spotlight_lookat_point.js new file mode 100644 index 00000000..f2951f92 --- /dev/null +++ b/test/tests_3d/3_lights/spotlight_lookat_point.js @@ -0,0 +1,62 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); +//var manifests_3d = require('../fixtures/manifests_3d'); + + +var ExternalResourceType = require('@iiif/vocabulary/dist-commonjs/').ExternalResourceType; +var MediaType = require('@iiif/vocabulary/dist-commonjs/').MediaType; + + +let manifest, sequence, scene , model, body, annotations; + +let manifest_url = { + local: "http://localhost:3001/model_origin.json", + remote : "https://raw.githubusercontent.com/vincentmarchetti/iiif3dtsg/spotlight-manifest/manifests/3_lights/spotlight_lookat_positioned.json" + }.remote; + +describe('spotlight', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a scene with two annotation', function(){ + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()).to.be.ok; + annotations = scene.getContent(); + expect(annotations.length).to.equal(2); + + + }); + + + it('with a spot light', function(){ + // not following find idiom doesn't work if spotlight is inside + // a SpecificResource + let lightAnno = scene.Content.find( (anno) => anno.Body[0] instanceof manifesto.Light ); + + expect(lightAnno).to.exist; + let body = lightAnno.Body[0]; + let light = (body.isSpecificResource())? body.Source : body; + expect (light.isSpotLight()).to.equal(true); + + expect( light.Intensity).to.equal( 0.6 ); + expect( light.Color ).to.exist; + expect( light.Angle ).to.equal(3.5); + + let lookAt = light.LookAt; + expect(lookAt).to.exist; + expect(lookAt.isPointSelector).to.equal(true); + }); + + + + +}); diff --git a/test/tests_3d/4_transform_and_position/model_position.js b/test/tests_3d/4_transform_and_position/model_position.js new file mode 100644 index 00000000..d1951ab6 --- /dev/null +++ b/test/tests_3d/4_transform_and_position/model_position.js @@ -0,0 +1,61 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); +//var manifests_3d = require('../fixtures/manifests_3d'); + + +var ExternalResourceType = require('@iiif/vocabulary/dist-commonjs/').ExternalResourceType; +var MediaType = require('@iiif/vocabulary/dist-commonjs/').MediaType; + + +let manifest, sequence, scene , annotation, body; + +let manifest_url = { + local: "http://localhost:3001/model_origin.json", + remote : "https://raw.githubusercontent.com/IIIF/3d/eds/manifests/4_transform_and_position/model_position.json" + }.remote; + +describe('model_position', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + it('has a scene', function() { + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()); + }); + + + it('with one annotation', function(){ + var annotations = scene.getContent(); + expect(annotations.length).to.equal(1); + annotation = annotations[0]; + }); + + it('targeting a SpecificResource with PointSelector', function(){ + var target = annotation.getTarget(); + + expect( target.isSpecificResource ); + expect( target.getSource()).to.exist; + + var selector = target.getSelector(); + expect( selector.isPointSelector ); + var location = selector.getLocation(); + location.x.should.equal(-1.0); + location.y.should.equal( 0.0); + location.z.should.equal( 1.0); + }); + + + +}); diff --git a/test/tests_3d/4_transform_and_position/model_transform_scale_position.js b/test/tests_3d/4_transform_and_position/model_transform_scale_position.js new file mode 100644 index 00000000..af19f699 --- /dev/null +++ b/test/tests_3d/4_transform_and_position/model_transform_scale_position.js @@ -0,0 +1,93 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); +//var manifests_3d = require('../fixtures/manifests_3d'); + + +var ExternalResourceType = require('@iiif/vocabulary/dist-commonjs/').ExternalResourceType; +var MediaType = require('@iiif/vocabulary/dist-commonjs/').MediaType; + + +let manifest, sequence, scene , annotation, body; + +let manifest_url = { + local: "http://localhost:3001/model_origin.json", + remote : "https://raw.githubusercontent.com/IIIF/3d/main/manifests/4_transform_and_position/model_transform_scale_position.json" +}.remote; + +describe('model_transform_scale_position', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + it('has a scene', function() { + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()).to.be.ok; + }); + + + it('with two annotations', function(){ + var annotations = scene.getContent(); + expect(annotations.length).to.equal(2); + annotation = annotations[1]; + }); + + it('annotations[1] with 1 SpecificResource body', function(){ + body = annotation.getBody()[0] + expect( body.isSpecificResource() ).to.be.ok ; + expect( body.isModel() ).to.be.ok; + var transform = body.getTransform(); + expect(Array.isArray(transform)).to.be.ok; + expect(transform.length).to.equal(2); + + var tt = transform[0]; + expect(tt.isTranslateTransform ).to.equal(true); + expect(tt.isRotateTransform ).to.not.be.ok; + + var tdata = tt.getTranslation(); + expect(tdata.x).to.equal(2.0); + expect(tdata.y).to.equal(2.0); + expect(tdata.z).to.equal(2.0); + + var st = transform[1]; + expect(st.isTranslateTransform ).to.not.be.ok; + expect(st.isScaleTransform ).to.equal(true); + + var sdata = st.getScale(); + expect(sdata.x).to.equal(2.0); + expect(sdata.y).to.equal(2.0); + expect(sdata.z).to.equal(2.0); + }); + + it('with source pointing to manifest', function(){ + var source = body.getSource(); + expect( source.isModel() ).to.equal(true); + source.id.should.include('astronaut.glb'); + }) + + it('targeting a SpecificResource with PointSelector', function(){ + var target = annotation.getTarget(); + + if (target.isSpecificResource) + target.getSource().should.exist; + + expect( target.isSpecificResource ).to.be.ok; + + var selector = target.getSelector(); + expect( selector.isPointSelector ).to.be.ok; + var location = selector.getLocation(); + location.x.should.equal( 1.0); + location.y.should.equal( 0.0); + location.z.should.equal( 0.0); + }); +}); diff --git a/test/tests_3d/4_transform_and_position/model_transform_translate_rotate_position.js b/test/tests_3d/4_transform_and_position/model_transform_translate_rotate_position.js new file mode 100644 index 00000000..085ea7d4 --- /dev/null +++ b/test/tests_3d/4_transform_and_position/model_transform_translate_rotate_position.js @@ -0,0 +1,104 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); +//var manifests_3d = require('../fixtures/manifests_3d'); + + +var ExternalResourceType = require('@iiif/vocabulary/dist-commonjs/').ExternalResourceType; +var MediaType = require('@iiif/vocabulary/dist-commonjs/').MediaType; + + +let manifest, sequence, scene , annotation, body; + +let manifest_url = { + local: "http://localhost:3001/model_origin.json", + remote : "https://raw.githubusercontent.com/IIIF/3d/main/manifests/4_transform_and_position/model_transform_translate_rotate_position.json" + }.remote; + +describe('model_transform_translate_rotate_position', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + it('has a scene', function() { + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()).to.be.ok; + }); + + + it('with one annotation', function(){ + var annotations = scene.getContent(); + expect(annotations.length).to.equal(1); + annotation = annotations[0]; + }); + + it('with 1 SpecificResource body', function(){ + body = annotation.getBody()[0]; + expect( body.isSpecificResource() ).to.be.ok ; + body.getResourceID().should.include('astronaut.glb'); + body.getFormat().should.equal("model/gltf-binary"); + }); + + it('with transforms applied to the body', function(){ + var transform = body.getTransform(); + expect(Array.isArray(transform)).to.be.ok; + expect(transform.length).to.equal(2); + + var tt = transform[0]; + expect(tt.isTranslateTransform ).to.equal(true); + expect(tt.isRotateTransform).to.not.be.ok; + var tdata = tt.getTranslation(); + expect(tdata.x).to.equal(1.0); + expect(tdata.y).to.equal(0.0); + expect(tdata.z).to.equal(0.0); + + var rt = transform[1]; + expect(rt.isTranslateTransform).to.not.be.ok; + expect(rt.isRotateTransform).to.equal(true); + var rdata = rt.getRotation(); + expect(rdata.x).to.equal(0.0); + expect(rdata.y).to.equal(180.0); + expect(rdata.z).to.equal(0.0); + + const matrix = body.getTransformMatrix(); + expect(matrix).to.exist; + + const decomposed = manifesto.decomposeMatrix(matrix); + expect(decomposed).to.exist; + }); + + it('with source pointing to manifest', function(){ + expect( body.isSpecificResource() ).to.be.ok ; + var source = body.getSource(); + source.id.should.include('astronaut.glb'); + }); + + it('targeting a SpecificResource with PointSelector', function(){ + var target = annotation.getTarget(); + + if (target.isSpecificResource) + target.getSource().should.exist; + + expect( target.isSpecificResource ).to.be.ok; + + var selector = target.getSelector(); + expect( selector.isPointSelector ).to.be.ok; + var location = selector.getLocation(); + location.x.should.equal( 0.0); + location.y.should.equal( 0.0); + location.z.should.equal( 0.0); + }); + + + +}); diff --git a/test/tests_3d/9_commenting_annotations/astronaut_comment.js b/test/tests_3d/9_commenting_annotations/astronaut_comment.js new file mode 100644 index 00000000..e9d9bc9d --- /dev/null +++ b/test/tests_3d/9_commenting_annotations/astronaut_comment.js @@ -0,0 +1,75 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); +//var manifests_3d = require('../fixtures/manifests_3d'); + + +var ExternalResourceType = require('@iiif/vocabulary/dist-commonjs/').ExternalResourceType; +var MediaType = require('@iiif/vocabulary/dist-commonjs/').MediaType; + + +let manifest, sequence, scene , annotation, body; + +let manifest_url = { + local: "", + remote : "https://raw.githubusercontent.com/IIIF/3d/main/manifests/9_commenting_annotations/astronaut_comment.json" + }.remote; + +describe('astronaut_comment', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('has a sequence', function() { + sequence = manifest.getSequenceByIndex(0); + expect(sequence).to.exist; + }); + + it('has a scene', function() { + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()); + }); + + + it('with one annotation', function(){ + var annotations = scene.getContent(); + expect(annotations.length).to.equal(1); + annotation = annotations[0]; + }); + + it('that target the scene', function(){ + var target = annotation.getTarget(); + target.id.should.exist; + target.id.should.equal( scene.id ); + + if (target.isSpecificResource) + target.getSource().should.exist; + }); + + it('has two commenting annotations', function(){ + const annotations = scene.getNonContentAnnotations(); + expect(annotations.length).to.equal(2); + }); + + it('targeting the Scene with PointSelector', function(){ + const annotations = scene.getNonContentAnnotations(); + const annotation = annotations[0]; + + const target = annotation.getTarget(); + expect( target.isSpecificResource ); + expect( target.getSource()).to.exist; + + const selector = target.getSelector(); + expect( selector.isPointSelector ); + + const location = selector.getLocation(); + expect(location.x).to.exist; + expect(location.y).to.exist; + expect(location.z).to.exist; + }); +}); diff --git a/test/tests_3d/9_commenting_annotations/whale_comment_camera.js b/test/tests_3d/9_commenting_annotations/whale_comment_camera.js new file mode 100644 index 00000000..257dec54 --- /dev/null +++ b/test/tests_3d/9_commenting_annotations/whale_comment_camera.js @@ -0,0 +1,75 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs'); +//var manifests_3d = require('../fixtures/manifests_3d'); + + +var ExternalResourceType = require('@iiif/vocabulary/dist-commonjs/').ExternalResourceType; +var MediaType = require('@iiif/vocabulary/dist-commonjs/').MediaType; + + +let manifest, scene , annotations, body; + +let manifest_url = { + local: "", + remote : "https://raw.githubusercontent.com/IIIF/3d/whale_anno/manifests/9_commenting_annotations/whale_comment_camera.json" + }.remote; + +describe('c_comment_annotation_camera', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + + + it('has a scene', function() { + sequence = manifest.getSequenceByIndex(0); + scene = sequence.getScenes()[0]; + expect(scene).to.exist; + expect(scene.isScene()).to.be.ok; + }); + + + it('with 4 annotation', function(){ + var annotations = scene.getContent(); + expect(annotations.length).to.equal(4); + }); + + it('annotation 3 is TextualBody', function(){ + var annotations = scene.getContent(); + expect(annotations.length).to.equal(4); + var textBody = annotations[2].getBody()[0]; + expect(textBody instanceof manifesto.TextualBody).to.equal(true); + expect(textBody.Value).to.exist; + }); + + it('annotation 4 is a camera', function(){ + var annotations = scene.getContent(); + expect(annotations.length).to.equal(4); + var camera = annotations[3].getBody()[0]; + expect(camera).to.exist; + + expect(camera instanceof manifesto.Camera).to.equal(true); + expect(camera.isPerspectiveCamera()).to.equal(true); + }); + + it('camera has null LookAt property', function(){ + var annotations = scene.getContent(); + var camera = annotations[3].getBody()[0]; + + expect(camera.LookAt).to.equal(null); + }); + + it('all annotation have a body', function(){ + var annotations = scene.getContent(); + for (var i = 0; i < annotations.length; ++i){ + var custom_message = "annotation " + i + " body fails exist"; + var body = annotations[i].getBody()[0]; + expect(body, custom_message).to.exist; + } + }); +}); diff --git a/test/tests_3d/core_tests/Geometry3d.js b/test/tests_3d/core_tests/Geometry3d.js new file mode 100644 index 00000000..7a115748 --- /dev/null +++ b/test/tests_3d/core_tests/Geometry3d.js @@ -0,0 +1,633 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); + +var threejs_math = require('threejs-math'); + +describe('Geometry3d: cameraRelativeRotation', function() { + + it('relativeRotation (2.0,-1.0,4.0)', function (){ + var direction = new threejs_math.Vector3(2.0, -1.0, 4.0); + var unit_direction = direction.divideScalar(direction.length()) + var euler = manifesto.cameraRelativeRotation(direction); + expect(euler.isEuler).to.equal(true); + + var x_axis = new threejs_math.Vector3(1.0,0.0,0.0); + var y_axis = new threejs_math.Vector3(0.0,1.0,0.0); + var nz_axis = new threejs_math.Vector3(0.0,0.0,-1.0); + + // and the camera axis + var camera_direction = nz_axis.applyEuler(euler); + expect(camera_direction.isVector3).to.equal(true); + + var camera_right = x_axis.applyEuler(euler); + var camera_up = y_axis.applyEuler(euler); + + // directions nearly equal + expect( new threejs_math.Vector3().subVectors(camera_direction , unit_direction ).length() ).to.be.lessThan(1.0e-4, "camera direction not correct"); + expect( Math.abs( camera_right.y)).to.be.lessThan(1.0e-4, "camera horizontal axis is horizontal"); + expect( camera_up.x).to.be.greaterThan(0.0, "camera vertical axis is up"); + }); + + it('looking straight down from above', function (){ + var direction = new threejs_math.Vector3(0.0, -1.0, 0.0); + var unit_direction = direction.clone().divideScalar(direction.length()) + var euler = manifesto.cameraRelativeRotation(direction); + expect(euler.isEuler).to.equal(true); + + var x_axis = new threejs_math.Vector3(1.0,0.0,0.0); + var y_axis = new threejs_math.Vector3(0.0,1.0,0.0); + var nz_axis = new threejs_math.Vector3(0.0,0.0,-1.0); + var z_axis = new threejs_math.Vector3(0.0,0.0,+1.0) + + // and the camera axis + var camera_direction = nz_axis.clone().applyEuler(euler); + expect(camera_direction.isVector3).to.equal(true); + + + var camera_up = y_axis.clone().applyEuler(euler); + + // directions nearly equal + expect( new threejs_math.Vector3().subVectors(camera_direction , unit_direction ).length() ).to.be.lessThan(1.0e-4, "camera direction not correct"); + expect( new threejs_math.Vector3().subVectors(camera_up , z_axis ).length()).to.be.lessThan(1.0e-4, "camera vertical axis is forward"); + }); + + it('looking straight up from below', function (){ + var direction = new threejs_math.Vector3(0.0, 1.0, 0.0); + var unit_direction = direction.clone().divideScalar(direction.length()) + var euler = manifesto.cameraRelativeRotation(direction); + expect(euler.isEuler).to.equal(true); + + var x_axis = new threejs_math.Vector3(1.0,0.0,0.0); + var y_axis = new threejs_math.Vector3(0.0,1.0,0.0); + var nz_axis = new threejs_math.Vector3(0.0,0.0,-1.0); + var z_axis = new threejs_math.Vector3(0.0,0.0,+1.0); + + // and the camera axis + var camera_direction = nz_axis.clone().applyEuler(euler); + expect(camera_direction.isVector3).to.equal(true); + + + var camera_up = y_axis.clone().applyEuler(euler); + // directions nearly equal + expect( new threejs_math.Vector3().subVectors(camera_direction , unit_direction ).length() ).to.be.lessThan(1.0e-4, "camera direction not correct"); + expect( new threejs_math.Vector3().subVectors(camera_up , nz_axis ).length()).to.be.lessThan(1.0e-4, "camera vertical axis is backward"); + }); + + + + +}); + +describe('Geometry3d: lightRelativeRotation', function() { + + it('relativeRotation (2.0,-1.0,4.0)', function (){ + var direction = new threejs_math.Vector3(2.0, -1.0, 4.0); + var unit_direction = direction.divideScalar(direction.length()) + var euler = manifesto.lightRelativeRotation(direction); + expect(euler.isEuler).to.equal(true); + + var ny_axis = new threejs_math.Vector3(0.0,-1.0,0.0); + + var light_direction = ny_axis.clone().applyEuler(euler); + // directions nearly equal + expect( new threejs_math.Vector3().subVectors(light_direction , unit_direction ).length() ).to.be.lessThan(1.0e-4, "light direction not correct"); + }); +}); + +describe('Geometry3d: eulerFromRotateTransform', function() { + + // based on the https://raw.githubusercontent.com/IIIF/3d/whale_anno/manifests/xx_whale_comments/c_comment_annotation_camera.json + // manifesto at commit f35a1ad (27 July 2024) + it('c_comment_annotation_camera', function (){ + + var transform = new manifesto.RotateTransform( + { + "type": "RotateTransform", + "x": -15.0, + "y": 215.0, + "z": 0.0 + } + ); + + var euler = manifesto.eulerFromRotateTransform( transform ); + + expect(euler).to.exist; + + var neg_z_axis = new threejs_math.Vector3(0.0,0.0,-1.0); + + var rotated_z_axis = neg_z_axis.clone().applyEuler(euler); + + // evaluate the desired direction based on defined camera + // position (lookFrom) and target position (lookAt) + var lookFrom = new threejs_math.Vector3( -0.25, 0.0, -0.5); + var lookAt = new threejs_math.Vector3(0.040, 0.063, -0.066); + + var desired_direction = lookAt.clone().sub(lookFrom).normalize(); + var direction_error = desired_direction.clone().sub(rotated_z_axis); + + // apply very lax test, since the camera orientation may have been eyeballed + // only in a threeJS editor, particularly there may be a depth imprecision. + expect( direction_error.length()).to.be.lessThan(1.5e-1, "rotated z direction not correct"); + + }); +}); + +describe('Geometry3d: combineTransformsToMatrix', function() { + it('combines transform scale -> translate', function (){ + const translateT = new manifesto.TranslateTransform({ + type: 'TranslateTransform', + x: 2, + y: 2, + z: 2 + }) + + const scaleT = new manifesto.ScaleTransform({ + type: 'ScaleTransform', + x: 2, + y: 2, + z: 2 + }) + + const matrix = manifesto.combineTransformsToMatrix([translateT, scaleT]); + const { translation, rotation, scale } = manifesto.decomposeMatrix(matrix); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.equal(4); + expect(translation.y).to.equal(4); + expect(translation.z).to.equal(4); + + expect(scale.x).to.equal(2); + expect(scale.y).to.equal(2); + expect(scale.z).to.equal(2); + + expect(rotation.x).to.equal(0); + expect(rotation.y).to.equal(0); + expect(rotation.z).to.equal(0); + }); + + it('combines transform translate -> scale', function (){ + const translateT = new manifesto.TranslateTransform({ + type: 'TranslateTransform', + x: 2, + y: 2, + z: 2 + }) + + const scaleT = new manifesto.ScaleTransform({ + type: 'ScaleTransform', + x: 2, + y: 2, + z: 2 + }) + + const matrix = manifesto.combineTransformsToMatrix([scaleT, translateT]); + const { translation, rotation, scale } = manifesto.decomposeMatrix(matrix); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.equal(2); + expect(translation.y).to.equal(2); + expect(translation.z).to.equal(2); + + expect(scale.x).to.equal(2); + expect(scale.y).to.equal(2); + expect(scale.z).to.equal(2); + + expect(rotation.x).to.equal(0); + expect(rotation.y).to.equal(0); + expect(rotation.z).to.equal(0); + }); + + it('combines transform translate -> rotate', function (){ + const translateT = new manifesto.TranslateTransform({ + type: 'TranslateTransform', + x: 2, + y: 0, + z: 0 + }) + + const rotateT = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 0, + y: 90, + z: 0 + }) + + const matrix = manifesto.combineTransformsToMatrix([translateT, rotateT]); + const { translation, rotation, scale } = manifesto.decomposeMatrix(matrix); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.be.closeTo(0, 0.000001); + expect(translation.y).to.be.closeTo(0, 0.000001); + expect(translation.z).to.be.closeTo(-2, 0.000001); + + expect(scale.x).to.equal(1); + expect(scale.y).to.equal(1); + expect(scale.z).to.equal(1); + + expect(rotation.x).to.equal(0); + expect(rotation.y).to.equal(Math.PI / 2); + expect(rotation.z).to.equal(0); + }); + + it('combines transform rotate -> translate', function (){ + const translateT = new manifesto.TranslateTransform({ + type: 'TranslateTransform', + x: 2, + y: 0, + z: 0 + }) + + const rotateT = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 0, + y: 90, + z: 0 + }) + + const matrix = manifesto.combineTransformsToMatrix([rotateT, translateT]); + const { translation, rotation, scale } = manifesto.decomposeMatrix(matrix); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.be.closeTo(2, 0.000001); + expect(translation.y).to.be.closeTo(0, 0.000001); + expect(translation.z).to.be.closeTo(0, 0.000001); + + expect(scale.x).to.equal(1); + expect(scale.y).to.equal(1); + expect(scale.z).to.equal(1); + + expect(rotation.x).to.equal(0); + expect(rotation.y).to.equal(Math.PI / 2); + expect(rotation.z).to.equal(0); + }); + + it('combines transform rotate -> rotate', function (){ + const rotateTFirst = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 30, + y: 0, + z: 0 + }) + + const rotateTSecond = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 15, + y: 0, + z: 0 + }) + + const matrix = manifesto.combineTransformsToMatrix([rotateTFirst, rotateTSecond]); + const { translation, rotation, scale } = manifesto.decomposeMatrix(matrix); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.be.closeTo(0, 0.000001); + expect(translation.y).to.be.closeTo(0, 0.000001); + expect(translation.z).to.be.closeTo(0, 0.000001); + + expect(scale.x).to.equal(1); + expect(scale.y).to.equal(1); + expect(scale.z).to.equal(1); + + expect(rotation.x).to.be.closeTo(Math.PI / 4, 0.000001); + expect(rotation.y).to.be.closeTo(0, 0.000001); + expect(rotation.z).to.be.closeTo(0, 0.000001); + }); + + it('combines transform rotate -> rotate (2)', function (){ + const rotateTFirst = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 0, + y: 45, + z: 0 + }) + + const rotateTSecond = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 60, + y: 0, + z: 0 + }) + + const matrix = manifesto.combineTransformsToMatrix([rotateTFirst, rotateTSecond]); + const { translation, rotation, scale } = manifesto.decomposeMatrix(matrix); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.be.closeTo(0, 0.000001); + expect(translation.y).to.be.closeTo(0, 0.000001); + expect(translation.z).to.be.closeTo(0, 0.000001); + + expect(scale.x).to.equal(1); + expect(scale.y).to.equal(1); + expect(scale.z).to.equal(1); + + expect(rotation.x).to.be.closeTo(Math.PI / 3, 0.000001); + expect(rotation.y).to.be.closeTo(Math.PI / 4, 0.000001); + expect(rotation.z).to.be.closeTo(0, 0.000001); + }); + it('combines transform translate -> rotate -> scale', function (){ + const translateT = new manifesto.TranslateTransform({ + type: 'TranslateTransform', + x: 2, + y: 0, + z: 0 + }) + + const rotateT = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 0, + y: 90, + z: 0 + }) + + const scaleT = new manifesto.ScaleTransform({ + type: 'ScaleTransform', + x: 2, + y: 2, + z: 2 + }) + + const matrix = manifesto.combineTransformsToMatrix([translateT, rotateT, scaleT]); + const { translation, rotation, scale } = manifesto.decomposeMatrix(matrix); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.be.closeTo(0, 0.000001); + expect(translation.y).to.be.closeTo(0, 0.000001); + expect(translation.z).to.be.closeTo(-4, 0.000001); + + expect(scale.x).to.equal(2); + expect(scale.y).to.equal(2); + expect(scale.z).to.equal(2); + + expect(rotation.x).to.equal(0); + expect(rotation.y).to.equal(Math.PI / 2); + expect(rotation.z).to.equal(0); + }); +}); + +describe('Geometry3d: combineTransformsToTRS', function() { + it('combines transform scale -> translate', function (){ + const translateT = new manifesto.TranslateTransform({ + type: 'TranslateTransform', + x: 2, + y: 2, + z: 2 + }) + + const scaleT = new manifesto.ScaleTransform({ + type: 'ScaleTransform', + x: 2, + y: 2, + z: 2 + }) + + const { translation, rotation, scale } = manifesto.combineTransformsToTRS([translateT, scaleT]); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.equal(4); + expect(translation.y).to.equal(4); + expect(translation.z).to.equal(4); + + expect(scale.x).to.equal(2); + expect(scale.y).to.equal(2); + expect(scale.z).to.equal(2); + + expect(rotation.x).to.equal(0); + expect(rotation.y).to.equal(0); + expect(rotation.z).to.equal(0); + }); + + it('combines transform translate -> scale', function (){ + const translateT = new manifesto.TranslateTransform({ + type: 'TranslateTransform', + x: 2, + y: 2, + z: 2 + }) + + const scaleT = new manifesto.ScaleTransform({ + type: 'ScaleTransform', + x: 2, + y: 2, + z: 2 + }) + + const { translation, rotation, scale } = manifesto.combineTransformsToTRS([scaleT, translateT]); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.equal(2); + expect(translation.y).to.equal(2); + expect(translation.z).to.equal(2); + + expect(scale.x).to.equal(2); + expect(scale.y).to.equal(2); + expect(scale.z).to.equal(2); + + expect(rotation.x).to.equal(0); + expect(rotation.y).to.equal(0); + expect(rotation.z).to.equal(0); + }); + + it('combines transform translate -> rotate', function (){ + const translateT = new manifesto.TranslateTransform({ + type: 'TranslateTransform', + x: 2, + y: 0, + z: 0 + }) + + const rotateT = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 0, + y: 90, + z: 0 + }) + + const { translation, rotation, scale } = manifesto.combineTransformsToTRS([translateT, rotateT]); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.be.closeTo(0, 0.000001); + expect(translation.y).to.be.closeTo(0, 0.000001); + expect(translation.z).to.be.closeTo(-2, 0.000001); + + expect(scale.x).to.equal(1); + expect(scale.y).to.equal(1); + expect(scale.z).to.equal(1); + + expect(rotation.x).to.equal(0); + expect(rotation.y).to.equal(Math.PI / 2); + expect(rotation.z).to.equal(0); + }); + + it('combines transform rotate -> translate', function (){ + const translateT = new manifesto.TranslateTransform({ + type: 'TranslateTransform', + x: 2, + y: 0, + z: 0 + }) + + const rotateT = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 0, + y: 90, + z: 0 + }) + + const { translation, rotation, scale } = manifesto.combineTransformsToTRS([rotateT, translateT]); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.be.closeTo(2, 0.000001); + expect(translation.y).to.be.closeTo(0, 0.000001); + expect(translation.z).to.be.closeTo(0, 0.000001); + + expect(scale.x).to.equal(1); + expect(scale.y).to.equal(1); + expect(scale.z).to.equal(1); + + expect(rotation.x).to.equal(0); + expect(rotation.y).to.equal(Math.PI / 2); + expect(rotation.z).to.equal(0); + }); + + it('combines transform rotate -> rotate', function (){ + const rotateTFirst = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 30, + y: 0, + z: 0 + }) + + const rotateTSecond = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 15, + y: 0, + z: 0 + }) + + const { translation, rotation, scale } = manifesto.combineTransformsToTRS([rotateTFirst, rotateTSecond]); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.be.closeTo(0, 0.000001); + expect(translation.y).to.be.closeTo(0, 0.000001); + expect(translation.z).to.be.closeTo(0, 0.000001); + + expect(scale.x).to.equal(1); + expect(scale.y).to.equal(1); + expect(scale.z).to.equal(1); + + expect(rotation.x).to.be.closeTo(Math.PI / 4, 0.000001); + expect(rotation.y).to.be.closeTo(0, 0.000001); + expect(rotation.z).to.be.closeTo(0, 0.000001); + }); + + it('combines transform rotate -> rotate (2)', function (){ + const rotateTFirst = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 0, + y: 45, + z: 0 + }) + + const rotateTSecond = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 60, + y: 0, + z: 0 + }) + + const { translation, rotation, scale } = manifesto.combineTransformsToTRS([rotateTFirst, rotateTSecond]); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.be.closeTo(0, 0.000001); + expect(translation.y).to.be.closeTo(0, 0.000001); + expect(translation.z).to.be.closeTo(0, 0.000001); + + expect(scale.x).to.equal(1); + expect(scale.y).to.equal(1); + expect(scale.z).to.equal(1); + + expect(rotation.x).to.be.closeTo(Math.PI / 3, 0.000001); + expect(rotation.y).to.be.closeTo(Math.PI / 4, 0.000001); + expect(rotation.z).to.be.closeTo(0, 0.000001); + }); + it('combines transform translate -> rotate -> scale', function (){ + const translateT = new manifesto.TranslateTransform({ + type: 'TranslateTransform', + x: 2, + y: 0, + z: 0 + }) + + const rotateT = new manifesto.RotateTransform({ + type: 'RotateTransform', + x: 0, + y: 90, + z: 0 + }) + + const scaleT = new manifesto.ScaleTransform({ + type: 'ScaleTransform', + x: 2, + y: 2, + z: 2 + }) + + const { translation, rotation, scale } = manifesto.combineTransformsToTRS([translateT, rotateT, scaleT]); + + expect(translation).to.exist; + expect(rotation).to.exist; + expect(scale).to.exist; + + expect(translation.x).to.be.closeTo(0, 0.000001); + expect(translation.y).to.be.closeTo(0, 0.000001); + expect(translation.z).to.be.closeTo(-4, 0.000001); + + expect(scale.x).to.equal(2); + expect(scale.y).to.equal(2); + expect(scale.z).to.equal(2); + + expect(rotation.x).to.equal(0); + expect(rotation.y).to.equal(Math.PI / 2); + expect(rotation.z).to.equal(0); + }); +}); diff --git a/test/tests_3d/core_tests/annotationIdMap.js b/test/tests_3d/core_tests/annotationIdMap.js new file mode 100644 index 00000000..468fb1f8 --- /dev/null +++ b/test/tests_3d/core_tests/annotationIdMap.js @@ -0,0 +1,37 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); + + +let manifest_url = { + local: "http://localhost:3001/model_origin.json", + remote : "https://raw.githubusercontent.com/IIIF/3d/main/manifests/3_lights/ambient_green_light.json" + }.remote; + +let anno1_id = "https://example.org/iiif/3d/anno1"; +let anno2_id = "https://example.org/iiif/3d/anno2"; + +var manifest; + +describe('Manifest.annotationIdMap', function() { + + it('loads successfully', function(done) { + manifesto.loadManifest(manifest_url).then(function(data) { + manifest = manifesto.parseManifest(data); + done(); + }); + }); + + it('query annotationIdMap', function() { + + var anno1 = manifest.annotationIdMap[anno1_id]; + expect(anno1).to.exist; + + var anno2 = manifest.annotationIdMap[anno2_id]; + expect(anno2).to.exist; + + + var anno3 = manifest.annotationIdMap["http://huckleberry"]; + expect(anno3).to.not.exist; + }); +}); diff --git a/test/tests_3d/core_tests/class_color.js b/test/tests_3d/core_tests/class_color.js new file mode 100644 index 00000000..f259154f --- /dev/null +++ b/test/tests_3d/core_tests/class_color.js @@ -0,0 +1,28 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); + + +describe('class-color', function() { + + it('fromCSS demo', function (done){ + var sampleCSS = "#0FE0A3"; + var color = manifesto.Color.fromCSS( sampleCSS ); + expect(color.red).to.equal(15); + done(); + }); + + it('constructing Color', function (done){ + var color = new manifesto.Color([255,192,64]); + expect(color.blue).to.equal(64); + done(); + }); + + it('getting a CSS term', function (done){ + var color = new manifesto.Color([80,168,254]); + expect(color.CSS).to.equal("#50A8FE"); + done(); + }); + +}) + diff --git a/test/tests_3d/core_tests/iiif_label.js b/test/tests_3d/core_tests/iiif_label.js new file mode 100644 index 00000000..7f9eaf28 --- /dev/null +++ b/test/tests_3d/core_tests/iiif_label.js @@ -0,0 +1,78 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); + + + +let manifestObj = { + "@context": "http://iiif.io/api/presentation/4/context.json", + "id": "https://example.org/iiif/3d/model_origin.json", + "type": "Manifest", + "label": { "en": ["english manifest"], + "fr": ["french manifest"], + "de": ["german manifest"] + }, + "summary": { "en": ["Viewer should render the model at the scene origin, and then viewer should add default lighting and camera"] }, + "items": [ + { + "id": "https://example.org/iiif/scene1/page/p1/1", + "type": "Scene", + "label": { "en": ["A Scene"] }, + "items": [ + { + "id": "https://example.org/iiif/scene1/page/p1/1", + "type": "AnnotationPage", + "items": [ + { + "id": "https://example.org/iiif/3d/anno1", + "type": "Annotation", + "motivation": ["painting"], + "body": { + "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/astronaut/astronaut.glb", + "type": "Model" + }, + "target": "https://example.org/iiif/scene1/page/p1/1" + } + ] + } + ] + } + ] +} + +let manifest ; + +describe('label test', function() { + + it('parse text', function() { + + options = { + "locale" : "fr" + } + + manifest = manifesto.parseManifest(manifestObj, options); + expect(manifest.getIIIFResourceType()).to.equal('manifest'); + + }); + + + it('ask for english', function() { + + var label_text = manifest.getLabel().getValue("en"); + expect( label_text ).to.equal("english manifest"); + }); + + it('ask for french', function() { + + var label_text = manifest.getLabel().getValue("fr"); + expect( label_text ).to.equal("french manifest"); + }); + + it('ask for default', function() { + + var label_text = manifest.getLabel().getValue(); + expect( label_text ).to.equal("french manifest"); + }); + +}); + diff --git a/test/tests_3d/core_tests/parse_manifest.js b/test/tests_3d/core_tests/parse_manifest.js new file mode 100644 index 00000000..7c46dc79 --- /dev/null +++ b/test/tests_3d/core_tests/parse_manifest.js @@ -0,0 +1,35 @@ +var expect = require('chai').expect; +var should = require('chai').should(); +var manifesto = require('../../../dist-commonjs/'); + + +var manifest_text='{ "@context": "http://iiif.io/api/presentation/4/context.json", "id": "https://example.org/iiif/3d/model_origin.json", "type": "Manifest", "label": { "en": [ "Astronaut" ], "ru": [ "космонавт" ], "zh-CN": [ "宇航员" ] }, "summary": { "en": ["Viewer should render the model at the scene origin, and then viewer should add default lighting and camera"] }, "items": [ { "id": "https://example.org/iiif/scene1/page/p1/1", "type": "Scene", "label": { "en": ["A Scene"] }, "items": [ { "id": "https://example.org/iiif/scene1/page/p1/1", "type": "AnnotationPage", "items": [ { "id": "https://example.org/iiif/3d/anno1", "type": "Annotation", "motivation": ["painting"], "body": { "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/astronaut/astronaut.glb", "type": "Model" }, "target": "https://example.org/iiif/scene1/page/p1/1" } ] } ] } ] }' + +describe('parse-manifest', function() { + + it('parse text', function(done) { + + manifest = manifesto.parseManifest(manifest_text); + expect(manifest.getIIIFResourceType()).to.equal('manifest'); + done(); + }); + + + it('parse obj', function(done) { + + var manifest_obj = JSON.parse(manifest_text); + + var manifest=manifesto.parseManifest(manifest_obj); + expect(manifest.getIIIFResourceType()).to.equal('manifest'); + done(); + }); + + it('invalid json text', function(done) { + + var invalid_text = "[not valid json" + var badCall = function(){manifesto.parseManifest(invalid_text);}; + expect(badCall).to.throw(SyntaxError); + done(); + }); +}); + diff --git a/test/tests_3d/core_tests/threejs_math.js b/test/tests_3d/core_tests/threejs_math.js new file mode 100644 index 00000000..1ee03707 --- /dev/null +++ b/test/tests_3d/core_tests/threejs_math.js @@ -0,0 +1,34 @@ +var expect = require('chai').expect; +var should = require('chai').should(); + +var threejs_math = require('threejs-math'); + +describe('threejs_basics', function() { + + it('construct Vector3', function(done) { + var location = new threejs_math.Vector3(0.5,0.6,0.624499799); + var dist = location.length(); + expect( dist ).to.be.closeTo(1.0,1.0e-6); + done(); + }); + + it('test 30 degree rotation', function(done) { + var negativeY = new threejs_math.Vector3(0.0, -1.0, 0.0); + var axisX = new threejs_math.Vector3(1.0, 0.0, 0.0); + var angleRadians = threejs_math.MathUtils.degToRad(30.0); + + var quat = new threejs_math.Quaternion().setFromAxisAngle( axisX, angleRadians); + var actual = negativeY.clone().applyQuaternion( quat ); + + //console.log("actual rotated " + actual.toArray()); + var expected = new threejs_math.Vector3(0.0, -0.866025, -0.5); + var error = actual.sub(expected); + + + expect( error.length() ).to.be.at.most(1.0e-6); + done(); + }); + + + +}); \ No newline at end of file