From 9c11fcb501a585d1f1f4af9e3238e2aa506bb92f Mon Sep 17 00:00:00 2001 From: Vishwajeet Date: Tue, 10 Nov 2026 14:18:38 +0100 Subject: [PATCH] Rewrite the documentation for 3.0 The docs folder described the 2.0 API. This replaces it with pages for 3.0, adds the changelog, an index check for the public API, and a docs workflow. --- .github/workflows/docs.yml | 43 + .github/workflows/verify.yml | 2 + CHANGELOG.md | 79 + MIGRATION.md | 20 +- README.md | 10 +- developer.md | 12 +- docs/.atlas-analysis.json | 112 - docs/.mintignore | 12 +- docs/.prettierignore | 4 + docs/.prettierrc.json | 9 + docs/CONTRIBUTING.md | 34 - docs/LICENSE | 21 - docs/README.md | 71 +- docs/api-coverage.json | 357 + docs/api/core/opengeometry.mdx | 49 - docs/api/export/ifc.mdx | 84 - docs/api/export/pdf.mdx | 122 - docs/api/export/projection.mdx | 148 - docs/api/export/step.mdx | 75 - docs/api/export/stl.mdx | 77 - docs/api/operations/boolean-operations.mdx | 163 - docs/api/operations/extrude.mdx | 157 - docs/api/operations/loft.mdx | 60 - docs/api/operations/offset.mdx | 272 - docs/api/operations/sweep.mdx | 298 - docs/api/operations/triangulate.mdx | 281 - docs/api/primitives/arc.mdx | 74 - docs/api/primitives/curve.mdx | 185 - docs/api/primitives/elliptical-arc.mdx | 33 - docs/api/primitives/line.mdx | 207 - docs/api/primitives/polyline.mdx | 197 - docs/api/primitives/rectangle.mdx | 209 - docs/api/scene/scene-management.mdx | 139 - docs/api/shapes/analytic-solid.mdx | 206 - docs/api/shapes/cuboid.mdx | 104 - docs/api/shapes/cylinder.mdx | 100 - docs/api/shapes/opening.mdx | 60 - docs/api/shapes/polygon.mdx | 280 - docs/api/shapes/solid.mdx | 212 - docs/api/shapes/sphere.mdx | 73 - docs/api/shapes/sweep.mdx | 215 - docs/api/shapes/wedge.mdx | 188 - docs/concepts/architecture.mdx | 201 - docs/concepts/booleans.mdx | 77 - docs/concepts/brep.mdx | 291 - docs/concepts/exports.mdx | 59 - docs/concepts/operations.mdx | 90 - docs/concepts/primitives-and-shapes.mdx | 84 - docs/concepts/scene-graph.mdx | 59 - docs/docs.json | 326 +- docs/favicon.svg | 5 + docs/installation.mdx | 139 - docs/integration/examples.mdx | 173 - docs/integration/threejs.mdx | 229 - docs/llms.txt | 96 + docs/logo/logoDark.png | Bin 0 -> 7980 bytes docs/logo/logoLight.png | Bin 0 -> 7101 bytes docs/opengeometry/agents.mdx | 41 + docs/opengeometry/api/body.mdx | 126 + docs/opengeometry/api/constants.mdx | 108 + docs/opengeometry/api/display.mdx | 75 + docs/opengeometry/api/export.mdx | 79 + docs/opengeometry/api/offsets.mdx | 75 + docs/opengeometry/api/og-error.mdx | 58 + docs/opengeometry/api/og-mark.mdx | 45 + docs/opengeometry/api/opengeometry.mdx | 65 + docs/opengeometry/api/overview.mdx | 46 + docs/opengeometry/api/picking.mdx | 36 + docs/opengeometry/api/regions.mdx | 70 + docs/opengeometry/api/sheet.mdx | 46 + docs/opengeometry/api/solid.mdx | 73 + docs/opengeometry/api/system-assembly.mdx | 55 + docs/opengeometry/api/wire.mdx | 45 + docs/opengeometry/changelog.mdx | 43 + docs/opengeometry/concepts/architecture.mdx | 38 + docs/opengeometry/concepts/bodies.mdx | 65 + .../concepts/coordinates-and-planes.mdx | 66 + docs/opengeometry/concepts/display.mdx | 82 + docs/opengeometry/concepts/errors.mdx | 86 + docs/opengeometry/concepts/history.mdx | 70 + docs/opengeometry/examples.mdx | 37 + docs/opengeometry/guides/booleans.mdx | 146 + docs/opengeometry/guides/export-step.mdx | 75 + docs/opengeometry/guides/extrude.mdx | 77 + .../opengeometry/guides/ifc-exchange-body.mdx | 44 + .../guides/measure-and-validate.mdx | 88 + docs/opengeometry/guides/picking.mdx | 42 + docs/opengeometry/guides/primitives.mdx | 128 + .../guides/rebuild-and-mirror.mdx | 71 + .../guides/regions-and-offsets.mdx | 146 + docs/opengeometry/guides/revolve.mdx | 65 + docs/opengeometry/guides/run-in-node.mdx | 57 + docs/opengeometry/guides/shell.mdx | 59 + docs/opengeometry/guides/sweep.mdx | 94 + .../guides/transforms-and-assemblies.mdx | 106 + .../guides/use-your-threejs-scene.mdx | 106 + docs/opengeometry/installation.mdx | 77 + docs/opengeometry/migrate-from-2-0.mdx | 35 + docs/opengeometry/quickstart.mdx | 117 + docs/opengeometry/troubleshooting.mdx | 64 + docs/opengeometry/what-is-opengeometry.mdx | 50 + docs/package-lock.json | 14075 ++++++++++++++++ docs/package.json | 31 + docs/quickstart.mdx | 340 - docs/scripts/build-index.mjs | 130 + docs/style.css | 58 + docs/what-is-opengeometry.mdx | 132 - .../examples-vite/boolean.html | 1 - .../examples-vite/index.html | 46 +- .../examples-vite/opening.html | 2 +- .../examples-vite/showcase/main.ts | 2 +- .../examples-vite/theme.css | 53 +- main/scripts/build/readme-code.test.mjs | 41 +- 113 files changed, 18459 insertions(+), 6512 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 CHANGELOG.md delete mode 100644 docs/.atlas-analysis.json create mode 100644 docs/.prettierignore create mode 100644 docs/.prettierrc.json delete mode 100644 docs/CONTRIBUTING.md delete mode 100644 docs/LICENSE create mode 100644 docs/api-coverage.json delete mode 100644 docs/api/core/opengeometry.mdx delete mode 100644 docs/api/export/ifc.mdx delete mode 100644 docs/api/export/pdf.mdx delete mode 100644 docs/api/export/projection.mdx delete mode 100644 docs/api/export/step.mdx delete mode 100644 docs/api/export/stl.mdx delete mode 100644 docs/api/operations/boolean-operations.mdx delete mode 100644 docs/api/operations/extrude.mdx delete mode 100644 docs/api/operations/loft.mdx delete mode 100644 docs/api/operations/offset.mdx delete mode 100644 docs/api/operations/sweep.mdx delete mode 100644 docs/api/operations/triangulate.mdx delete mode 100644 docs/api/primitives/arc.mdx delete mode 100644 docs/api/primitives/curve.mdx delete mode 100644 docs/api/primitives/elliptical-arc.mdx delete mode 100644 docs/api/primitives/line.mdx delete mode 100644 docs/api/primitives/polyline.mdx delete mode 100644 docs/api/primitives/rectangle.mdx delete mode 100644 docs/api/scene/scene-management.mdx delete mode 100644 docs/api/shapes/analytic-solid.mdx delete mode 100644 docs/api/shapes/cuboid.mdx delete mode 100644 docs/api/shapes/cylinder.mdx delete mode 100644 docs/api/shapes/opening.mdx delete mode 100644 docs/api/shapes/polygon.mdx delete mode 100644 docs/api/shapes/solid.mdx delete mode 100644 docs/api/shapes/sphere.mdx delete mode 100644 docs/api/shapes/sweep.mdx delete mode 100644 docs/api/shapes/wedge.mdx delete mode 100644 docs/concepts/architecture.mdx delete mode 100644 docs/concepts/booleans.mdx delete mode 100644 docs/concepts/brep.mdx delete mode 100644 docs/concepts/exports.mdx delete mode 100644 docs/concepts/operations.mdx delete mode 100644 docs/concepts/primitives-and-shapes.mdx delete mode 100644 docs/concepts/scene-graph.mdx create mode 100644 docs/favicon.svg delete mode 100644 docs/installation.mdx delete mode 100644 docs/integration/examples.mdx delete mode 100644 docs/integration/threejs.mdx create mode 100644 docs/llms.txt create mode 100644 docs/logo/logoDark.png create mode 100644 docs/logo/logoLight.png create mode 100644 docs/opengeometry/agents.mdx create mode 100644 docs/opengeometry/api/body.mdx create mode 100644 docs/opengeometry/api/constants.mdx create mode 100644 docs/opengeometry/api/display.mdx create mode 100644 docs/opengeometry/api/export.mdx create mode 100644 docs/opengeometry/api/offsets.mdx create mode 100644 docs/opengeometry/api/og-error.mdx create mode 100644 docs/opengeometry/api/og-mark.mdx create mode 100644 docs/opengeometry/api/opengeometry.mdx create mode 100644 docs/opengeometry/api/overview.mdx create mode 100644 docs/opengeometry/api/picking.mdx create mode 100644 docs/opengeometry/api/regions.mdx create mode 100644 docs/opengeometry/api/sheet.mdx create mode 100644 docs/opengeometry/api/solid.mdx create mode 100644 docs/opengeometry/api/system-assembly.mdx create mode 100644 docs/opengeometry/api/wire.mdx create mode 100644 docs/opengeometry/changelog.mdx create mode 100644 docs/opengeometry/concepts/architecture.mdx create mode 100644 docs/opengeometry/concepts/bodies.mdx create mode 100644 docs/opengeometry/concepts/coordinates-and-planes.mdx create mode 100644 docs/opengeometry/concepts/display.mdx create mode 100644 docs/opengeometry/concepts/errors.mdx create mode 100644 docs/opengeometry/concepts/history.mdx create mode 100644 docs/opengeometry/examples.mdx create mode 100644 docs/opengeometry/guides/booleans.mdx create mode 100644 docs/opengeometry/guides/export-step.mdx create mode 100644 docs/opengeometry/guides/extrude.mdx create mode 100644 docs/opengeometry/guides/ifc-exchange-body.mdx create mode 100644 docs/opengeometry/guides/measure-and-validate.mdx create mode 100644 docs/opengeometry/guides/picking.mdx create mode 100644 docs/opengeometry/guides/primitives.mdx create mode 100644 docs/opengeometry/guides/rebuild-and-mirror.mdx create mode 100644 docs/opengeometry/guides/regions-and-offsets.mdx create mode 100644 docs/opengeometry/guides/revolve.mdx create mode 100644 docs/opengeometry/guides/run-in-node.mdx create mode 100644 docs/opengeometry/guides/shell.mdx create mode 100644 docs/opengeometry/guides/sweep.mdx create mode 100644 docs/opengeometry/guides/transforms-and-assemblies.mdx create mode 100644 docs/opengeometry/guides/use-your-threejs-scene.mdx create mode 100644 docs/opengeometry/installation.mdx create mode 100644 docs/opengeometry/migrate-from-2-0.mdx create mode 100644 docs/opengeometry/quickstart.mdx create mode 100644 docs/opengeometry/troubleshooting.mdx create mode 100644 docs/opengeometry/what-is-opengeometry.mdx create mode 100644 docs/package-lock.json create mode 100644 docs/package.json delete mode 100644 docs/quickstart.mdx create mode 100644 docs/scripts/build-index.mjs create mode 100644 docs/style.css delete mode 100644 docs/what-is-opengeometry.mdx diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..7470f6e4 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,43 @@ +name: Documentation + +on: + pull_request: + paths: + - "docs/**" + - "main/opengeometry-three/index.ts" + - "main/opengeometry-three/src/constants/**" + - ".github/workflows/docs.yml" + push: + branches: + - main + paths: + - "docs/**" + - "main/opengeometry-three/index.ts" + - "main/opengeometry-three/src/constants/**" + - ".github/workflows/docs.yml" + +permissions: + contents: read + +concurrency: + group: docs-${{ github.ref }} + cancel-in-progress: true + +jobs: + docs: + name: Format, coverage, build and links + runs-on: ubuntu-latest + defaults: + run: + working-directory: docs + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "22" + cache: npm + cache-dependency-path: docs/package-lock.json + - name: Install documentation tools + run: npm ci + - name: Check documentation + run: npm run check diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 819fff88..30f28939 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -6,6 +6,7 @@ on: - 'main/**' - 'README.md' - 'MIGRATION.md' + - 'docs/opengeometry/**' - 'LICENSE.md' - '.github/workflows/verify.yml' pull_request: @@ -13,6 +14,7 @@ on: - 'main/**' - 'README.md' - 'MIGRATION.md' + - 'docs/opengeometry/**' - 'LICENSE.md' - '.github/workflows/verify.yml' workflow_dispatch: diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..17f2bac7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,79 @@ +# Changelog + +All notable changes to the `opengeometry` package are in this file. The format follows +[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the package follows +[Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [3.0.0] - 2026-11-09 + +3.0 is a new API. Code written for 2.0 does not run without changes. Version 2.5 was not +published. Follow [MIGRATION.md](./MIGRATION.md): it gives every change with code before and after. + +### Changed + +- **Breaking:** bodies are made with three classes and a kind constant: `new Wire(kind, params)`, + `new Solid(kind, params)` and `new Sheet(OG_OPERATION_SWEEP, params)`. The 2.0 classes + (`Cuboid`, `Cylinder`, `Polygon`, `Opening`, `Sweep`, `AnalyticSolid` and the others) are gone. + See "Replace this with that" in MIGRATION.md. +- **Breaking:** points and vectors are `[x, y, z]` arrays. `Vector3` is gone. +- **Breaking:** bodies move with `body.transform(kind, params)` and `OG_TRANSFORM_*`. Setting + `position`, `rotation` or `scale` is reverted with a `PlacementOverwritten` warning. +- **Breaking:** start the kernel with `await OpenGeometry.create(input, options)` before the first + body. `workerURL` goes in the second argument. +- **Breaking:** the 2D region and offset functions are statics of `OpenGeometry`, such as + `OpenGeometry.booleanRegions2D` and `OpenGeometry.offsetRingVariable`. The offset calls return + `CurvedRegion2D` line and arc edges, not `{ x, y, z }` points. +- **Breaking:** `solid.prepareIfcExchange()` is `OpenGeometry.exportIfcBody(solid)`. +- **Breaking:** failures throw `OGError` with a `code`, a `call`, a `message` and `details`. +- **Breaking:** `classifyPoint` takes a point in the body's own coordinates and returns + `'Inside'`, `'Outside'`, `'Boundary'` or `'Unknown'`. +- **Breaking:** the shell hollows a solid in place: + `solid.operate(OG_OPERATION_SHELL, { thickness })`. To keep the first solid, shell + `solid.duplicate()`. +- **Breaking:** a body is displayed when it is drawn or walked by `updateMatrixWorld`. Its new + mesh is installed after the render that draws it, so the next frame shows it. +- **Breaking:** a body's `surface` and `outline` meshes have `matrixAutoUpdate` set to `false`. + Code that writes their `position`, `rotation`, `quaternion` or `scale` must call + `updateMatrix()` on that mesh. +- The outline leaves out smooth edges, and planar faces average their normals across them, so a + polygon that approximates a curve shades as a curve. The smooth angle is 20° by default; set + `appearance.smoothAngle` to `0` for the 2.0 look. + +### Added + +- Solid primitives: cuboid, cylinder, cylinder sector, sphere, cone or frustum, ring torus and + planar polyhedron. Wire primitives: rectangle, circle, polyline, line-and-arc profile and arc. + Each goes on any plane through the `plane` option. +- Extrude with holes, from any closed wire, including a line-and-arc profile. +- Sweep along lines and arcs, with one exact bend per arc, into a capped `Solid`, an open-ended + `Sheet` (`caps: false`), or a closed ring. +- Revolve a closed line-and-arc profile a full turn about an axis in its plane. +- Union, subtract and intersect with one to a hundred tool solids in one `operate` call, and a + report of the result with `solid.getReport()`. +- `body.rebuild(kind, params)` gives a body new parameters in place. `body.mirror(plane)` rebuilds + it as its reflection. +- `SystemAssembly` with parent and child placement; `duplicate()` for an independent copy and + `instance()` for a shared shape. +- Marks with `rollback` and `release`, and `OpenGeometry.transaction(fn, { dryRun })`. +- Queries: `getBounds`, `getBrep`, `getWorldBrep`, `faceNormalAt`, `classifyPoint`, `measure` + (volume and area within a stated error bound) and `validity`. +- Display for Three.js: every body is a `THREE.Group`, with level of detail that follows the + camera, tessellation in a web worker or inline, picking to a face or an edge with + `OpenGeometry.resolveHit`, `OpenGeometry.settled` and `OpenGeometry.flush`. +- Drawing through your own layers: `OpenGeometry.setHostDrawn`, `OpenGeometry.markDisplayed` and + `OpenGeometry.hostGroup`. `OpenGeometry.releaseIdleGeometry()` frees cached display meshes. +- `OpenGeometry.exportStep` writes STEP in millimetres or metres with Y or Z up, with an export + report. +- `OpenGeometry.insetCurvedRegion2D` and `OpenGeometry.offsetCurvedRingVariable` inset a + line-and-arc region exactly, with one distance, or one distance per edge. + +### Removed + +- **Breaking:** IFC file text, STL and PDF export, projection, loft, triangulation as a public + call, curves other than lines, circles and arcs, and wedges. They have no replacement in 3.0. + +### Fixed + +- A circular hole away from the profile centre extrudes. 2.0 refused some of these. +- Offset corners are exact arcs. 2.0 drew an inside corner as short segments outside the circle. +- A point inside one of two touching solids of a body is `Inside`. 2.0 could read it as outside. diff --git a/MIGRATION.md b/MIGRATION.md index ea758fa1..1af10d5f 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -12,20 +12,6 @@ It is written for people and for coding assistants alike: each section says what 4. For a name the table does not list, look in "Partly replaced". Anything listed under "Removed" has no replacement: take that code out, or stay on the older version. 5. Finish with its "Check your result" steps. -## Unreleased - -### Added - -- `OpenGeometry.offsetCurvedRingVariable(region, distances, holeDistances = [])` insets one `CurvedRegion2D` of lines and arcs by one distance (finite, >= 0) per edge, with one list per hole ring, and returns `CurvedRegion2D[]`. An arc edge stays on its centre: a convex arc moves to `r - d`, a concave arc or a hole's arc to `r + d`. A distance of 0 keeps its edge. A distance larger than an arc's radius, a wrong count, or a negative or non-finite distance is `InvalidParameter`. A collapsed result is an empty list. `offsetRingVariable` is unchanged. - -### Different behaviour - -- A body counts as displayed when it is drawn, not only when `updateMatrixWorld` walks it: its surface or outline `onBeforeRender`, or `OpenGeometry.markDisplayed(bodies)`, stamps it for the current render pass, and its new display geometry is installed after that render, so the next frame shows it. A body that is neither drawn nor walked for a full pass is no longer displayed and gets no level-of-detail target or record swap. A walk still stamps and installs at once, so code that walks, then calls `OpenGeometry.flush({ geometry: 'sync' })`, gets the same meshes as before. -- Display buffers leave smooth edges out of `outline` and `edgeIds`. An edge is smooth when its two faces are tangent-continuous, or when two planes fold by less than the smooth angle, 20° by default. The outline of a polygon that approximates a curve therefore loses its fold lines, and planar faces average their vertex normals across smooth edges, so the shading no longer shows the facets. A new `smoothEdges` `Uint8Array` gives one byte per topology edge, 1 for smooth. -- `appearance.smoothAngle` sets the angle per body, in degrees from 0 up to but not including 90; `0` restores the previous outline and normals. `OGWorldGraph.buffers` and `OGTessellator.buffers` take it as an optional fourth argument. -- Rust: `SnapshotStore::buffers()`, `WorldGraph::buffers()` and `display_buffers()` now default to 20°, not 0°. `tessellate_with_smooth_angle`, `display_buffers_with_smooth_angle` and `buffers_with_smooth_angle` take an explicit angle, and `SMOOTH_ANGLE` is the default. `tessellate()` stays at 0°. -- A body's `surface` and `outline` meshes are static: their `matrixAutoUpdate` is `false`, so a world matrix update no longer recomputes their local matrix. Code that writes their `position`, `rotation`, `quaternion` or `scale` must call `updateMatrix()` on that mesh after the write. - ## 2.5 to 3.0 2.5 was not published. From 2.0, follow 2.0 to 2.5, then 2.5 to 3.0. @@ -50,6 +36,7 @@ It is written for people and for coding assistants alike: each section says what - An arched opening is one cutter: extrude a closed `OG_PRIMITIVE_PROFILE` (jambs, sill and an arch) across a curved or straight wall and subtract it with `wall.operate(OG_OPERATION_SUBTRACT, { tools: [arch] })`. 2.0 needed a box and a half-cylinder for it, and a curved wall then failed. - An arched door from the floor is one cutter too: when its sill is at or below the wall's bottom face, the subtraction cuts a notch out of the wall instead of a hole. A cutter through both the floor and the top of the wall still throws `CoverageGap`. - The 2D offsets are back as statics. `OpenGeometry.offsetRingVariable(ring, distances, holes?)` insets a closed ring by one distance per edge, each hole grown by its own distances. `OpenGeometry.offsetPolylineRegions(path, width, closed, miterLimit?)` strokes a path, with mitres up to `miterLimit` (default 4) and bevels past it. Both take 2.0's flat `[x, y, z, ...]` lists or a `Float64Array` and return `CurvedRegion2D[]`, exact line and arc edges in XZ. `OpenGeometry.offsetPolyline(path, distance, options?)` replaces 2.0's `polyline.getOffset(distance, acuteThresholdDegrees, bevel)`. It returns `OffsetPath2D`, `{ edges, bevelled, closed }`, and its options are `{ acuteThresholdDegrees?, bevel?, closed? }`, with defaults 35 and `true`. When `closed` is left out, a path whose ends meet is closed. The entry exports the types `OffsetHole`, `OffsetPath2D` and `OffsetPolylineOptions`. +- `OpenGeometry.offsetCurvedRingVariable(region, distances, holeDistances = [])` insets one `CurvedRegion2D` of lines and arcs by one distance (finite, >= 0) per edge, with one list per hole ring, and returns `CurvedRegion2D[]`. An arc edge stays on its centre: a convex arc moves to `r - d`, a concave arc or a hole's arc to `r + d`. A distance of 0 keeps its edge. A distance larger than an arc's radius, a wrong count, or a negative or non-finite distance is `InvalidParameter`. A collapsed result is an empty list. `offsetRingVariable` is unchanged. - `OG_PRIMITIVE_SPHERE` makes a solid sphere: `{ radius }`, centred on the `plane` origin. - `OG_PRIMITIVE_CONE` makes a solid cone or frustum standing on the `plane`, its axis along the normal: `{ radiusBottom, radiusTop, height }`. One radius may be `0` for a pointed cone; radii within four times the geometric tolerance of each other make a cylinder. - `OG_PRIMITIVE_TORUS` makes a solid ring torus lying on the `plane`, its axis along the normal: `{ majorRadius, minorRadius }`, with the minor radius below the major one. @@ -605,6 +592,11 @@ console.log(pan.getReport()?.handlers, cistern.getReport()?.handlers, bowl.ogId) - An `operate` call (subtract, union or intersect) whose intersection reaches the apex of a cone throws `CoverageGap`. `details.families` names the pair, for example `['cone or frustum', 'cuboid']` or `['cylinder', 'noncoaxial cone or frustum']`. The `message` names `'singular surface point'`. - When that failure is `CoverageGap`, `details` also has `families`. It names the specialised gap the kernel met, such as `['cylinder', 'oblique cuboid intersection']`; for two planar bodies, that of the last box handler tried. With no specialised gap, it is the error's own pair. For most gaps the `message` names only the generic pair, `generic analytic solid` and `intersecting analytic solid`, so read `details.families` for the specialised one. The `code` is `CoverageGap`. - `flush({ geometry: 'sync', bodies })` checks its input before it meshes anything. A body that was disposed, or that comes from a reset runtime, throws `Disposed`. `bodies` without `geometry: 'sync'`, a `bodies` that is not an array, and an item that is not a Wire, a Sheet or a Solid throw `InvalidParameter`. Hidden bodies, bodies with no shape and bodies disposed while a mark is live are skipped. +- A body counts as displayed when it is drawn, not only when `updateMatrixWorld` walks it: its surface or outline `onBeforeRender`, or `OpenGeometry.markDisplayed(bodies)`, stamps it for the current render pass, and its new display geometry is installed after that render, so the next frame shows it. A body that is neither drawn nor walked for a full pass is no longer displayed and gets no level-of-detail target or record swap. A walk still stamps and installs at once, so code that walks, then calls `OpenGeometry.flush({ geometry: 'sync' })`, gets the same meshes as before. +- Display buffers leave smooth edges out of `outline` and `edgeIds`. An edge is smooth when its two faces are tangent-continuous, or when two planes fold by less than the smooth angle, 20° by default. The outline of a polygon that approximates a curve therefore loses its fold lines, and planar faces average their vertex normals across smooth edges, so the shading no longer shows the facets. A new `smoothEdges` `Uint8Array` gives one byte per topology edge, 1 for smooth. +- `appearance.smoothAngle` sets the angle per body, in degrees from 0 up to but not including 90; `0` restores the previous outline and normals. `OGWorldGraph.buffers` and `OGTessellator.buffers` take it as an optional fourth argument. +- Rust: `SnapshotStore::buffers()`, `WorldGraph::buffers()` and `display_buffers()` now default to 20°, not 0°. `tessellate_with_smooth_angle`, `display_buffers_with_smooth_angle` and `buffers_with_smooth_angle` take an explicit angle, and `SMOOTH_ANGLE` is the default. `tessellate()` stays at 0°. +- A body's `surface` and `outline` meshes are static: their `matrixAutoUpdate` is `false`, so a world matrix update no longer recomputes their local matrix. Code that writes their `position`, `rotation`, `quaternion` or `scale` must call `updateMatrix()` on that mesh after the write. - `OGError.details` is typed as `ErrorDetails`, which the package exports with `OperateErrorDetails`. A `details` value that is not an object becomes `{}`. - Point classification counts each solid of a body on its own, outer shell and cavities. A body is Inside if any solid holds the point. Before, the faces of all solids were counted together, so a point inside one of two touching solids could read Outside, and a Boolean that tested such a point could go wrong. - `classifyPoint` returns `'Boundary'` for a point within the geometric tolerance (`1e-8`) of the body's surface: on faces at any rotation, on seams, rims, edges, corners, sphere poles and a cone apex. Limit: the face test follows a circle, an ellipse or a full-turn line trim as 64 straight pieces, and an intersection curve as 128. So near such a trim the answer can be wrong. A point a little off a cylinder or cone cap near its rim (within about 1.2e-3 times the radius) can get the wrong side. A point on the surface just past a cut edge can read `'Boundary'`, up to about 7e-5 from the body on a cylinder minus a cuboid tilted 45 degrees. A point 1e-7 off a sphere pole or a cone apex can read `'Unknown'`. diff --git a/README.md b/README.md index c0165ace..68fc2992 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ > **Actively maintained and growing.** We're building OpenGeometry in the open. APIs, examples, and package structure are evolving, and we are actively improving and expanding the project. Star the repo to follow along. If you have questions or want to get involved, join the [Discord](https://discord.com/invite/9wJpbfgGGA) or check out the [issues](https://github.com/OpenGeometry-io/OpenGeometry/issues). -> **Version note.** This README describes OpenGeometry 3.0.0. Check which line you have installed with `npm ls opengeometry`: the 2.0 line has a different API. The hosted documentation still describes 2.0. +> **Version note.** This README describes OpenGeometry 3.0.0. Check which line you have installed with `npm ls opengeometry`: the 2.0 line has a different API. The documentation at [docs.opengeometry.io](https://docs.opengeometry.io?utm_source=github) describes 3.0. --- @@ -97,7 +97,7 @@ This loads the kernel, makes a 6 m by 0.2 m rectangle wire on the ground plane, The two URLs assume both files were copied to the site root, as described under Installation. The block uses top-level `await`, so it must run as a module. If your build rejects top-level `await`, raise its target (the examples set Vite's `build.target` to `'esnext'`) or move the code after the imports into an `async` function and call it. -Runnable examples live in [`main/opengeometry-three/examples-vite/`](./main/opengeometry-three/examples-vite/): a showcase, a sweep, booleans, an opening, a cuboid, a cylinder and STEP export. From a clone, run `npm --prefix main ci`, `npm run build` and then `npm run dev-example`. +Runnable examples live in [`main/opengeometry-three/examples-vite/`](./main/opengeometry-three/examples-vite/): a showcase, a sweep, booleans, an opening, a cuboid, a cylinder, a rounded section, a sweep along an arc path, a curved profile united with a straight one, and STEP export. From a clone, run `npm --prefix main ci`, `npm run build` and then `npm run dev-example`. ## Demos @@ -178,7 +178,7 @@ This section is a compact reference for writing OpenGeometry 3.0 code, by hand o | Copies | `body.duplicate({ ogId?, parent? })` makes an independent copy; `body.instance({ ogId?, parent? })` shares the shape. `getInstanceCount()`, `makeUnique()`. | | `SystemAssembly` | `new SystemAssembly({ ogId?, parent? })`. `addChild(children, { keepWorld? })`, `removeChild(child, { keepWorld? })`, `getChildren()`, `getParent()`, `getBounds()`, `transform`, `dispose()`. Bodies have the same tree methods. | | Queries | `getBounds()` (`[minX, minY, minZ, maxX, maxY, maxZ]`, or `null`), `getBrep()`, `getWorldBrep()` (the BRep placed in the world), `faceNormalAt(faceId, [x, y, z])` (the face's unit normal in the body's own coordinates), `classifyPoint([x, y, z])` (`'Inside'`, `'Outside'`, `'Boundary'` or `'Unknown'`, in the body's own coordinates), `measure({ deflection? })` (`{ volume, area, errorBound, areaErrorBound, deflection }`; the volume is within `errorBound` of the exact one, the area within `areaErrorBound`), `validity()` (`{ valid, closed, bodyType, error? }`), `solid.getReport()` (the last boolean's report, or `null`). | -| Appearance | `appearance` in the options, or `body.setAppearance({ color?, opacity?, outline?, pickOutline?, deflection? })`. | +| Appearance | `appearance` in the options, or `body.setAppearance({ color?, opacity?, outline?, pickOutline?, deflection?, smoothAngle? })`. `smoothAngle` is in degrees, 20 by default: edges whose faces fold by less are left out of the outline and shaded smooth; `0` keeps every edge. | | Display | `OpenGeometry.settled({ deflection? })` resolves to `{ failed }`; `OpenGeometry.flush({ geometry?: 'sync', bodies? })` (with `bodies`, meshes and places only those bodies now; hidden bodies, bodies with no shape and bodies in limbo (disposed while a mark is live) are skipped; a fully disposed body or one from a reset runtime throws `Disposed` before anything is meshed; `bodies` without `geometry: 'sync'`, a non-array `bodies` or an item that is not a Wire, Sheet or Solid throws `InvalidParameter`); `OpenGeometry.setDisplayDeflection(world?)`; `OpenGeometry.setCameraMotion(moving)`; `OpenGeometry.observeCamera(renderer, camera)` observes the first camera seen per renderer frame (`renderer.info.render.frame`) for level of detail; a `render()` nested inside an `onBeforeRender` (Reflector style) starts a new frame, and an `ArrayCamera` is observed through its first sub-camera (a host whose drawables are not kernel bodies, such as instanced or batched layers, calls it from their `onBeforeRender`); `OpenGeometry.releaseIdleGeometry()` disposes the display geometry cached for bodies not showing it and returns `{ records, bytes }`; `OpenGeometry.markDisplayed(bodies)` counts those bodies as displayed for the current render pass (a host that draws bodies through its own instanced or batched layers calls it from that layer's `onBeforeRender`; it works for a body hidden by layer, skips a body with `visible = false`, and validates `bodies` as `flush({ bodies })` does); `OpenGeometry.setHostDrawn(bodies, hostDrawn)` hands the drawing of those bodies to the host (`true`) or gives it back (`false`): while host-drawn, a body's `visible` is `false`, so three.js skips it and everything under it, and the kernel keeps the body's own visibility apart, so `markDisplayed`, a walk, `flush({ geometry: 'sync', bodies })`, level of detail and record swaps treat it as shown, and a dispose, a rollback or a reset changes that visibility instead of `visible`; giving it back sets `visible` to that visibility (a host calls it when a body joins or leaves its instanced or batched layers; do not set `visible` on a host-drawn body; it validates `bodies` as `flush({ bodies })` does, except that giving bodies back ignores a disposed or finalized body, and a `hostDrawn` that is not a boolean throws `InvalidParameter`); `OpenGeometry.hostGroup(bodies)` returns a `HostGroup` that stamps all its bodies at once: `group.drawn()` counts every member as displayed for the current render pass exactly as `markDisplayed` does, at a cost that does not grow with the number of members (a host calls it from each instanced or batched layer's `onBeforeRender` in place of `markDisplayed`), `group.set(bodies)` replaces the members and `group.dispose()` ends the group, after which `drawn()` does nothing and its members no longer count through it; a body may be in several groups, a hidden or host-drawn member keeps its own visibility and gets its geometry when it is shown again through `setHostDrawn` or a rollback, a member that is not host-drawn and has `visible` set to `true` later gets it when it is drawn or walked, a member disposed later leaves its groups, a group that is dropped without `dispose()` is ended when it is garbage collected, `hostGroup` and `set` validate `bodies` once as `markDisplayed` does, and `set` on a disposed group or one from a reset runtime throws `Disposed`. A body is displayed when it is drawn (its own `onBeforeRender` or `markDisplayed`) or walked by `updateMatrixWorld`; a draw installs new display geometry after the render, a walk at once. Each body dispatches `geometrychanged` after it installs new display geometry and `placementchanged` when a flush moves it (`BodyEventMap`); their listeners run synchronously, after the whole flush is applied or at the end of the render pass, and a listener that throws is reported through `OpenGeometry.on('error', …)` with the thrown value while the flush and the pass complete. | | Picking | `OpenGeometry.resolveHit(intersection)` takes a Three.js raycast hit and returns `{ ogId, shapeRevision, faceId?, edgeId? }` or `undefined`. | | `OGMark` | `const mark = OpenGeometry.mark()`, then `mark.rollback()` and `mark.release()`. `OpenGeometry.markStats()` returns `{ liveMarks, retainedRevisions }`. `OpenGeometry.transaction(fn, { dryRun? })` runs a synchronous `fn` and rolls back if it throws. | @@ -224,7 +224,7 @@ This section is a compact reference for writing OpenGeometry 3.0 code, by hand o ## Documentation -The hosted documentation at **[docs.opengeometry.io](https://docs.opengeometry.io?utm_source=github)** still describes the 2.0 API. For 3.0, use this README, the types in the package and the examples. To move code written for 2.0 to 3.0, follow [MIGRATION.md](./MIGRATION.md). +The documentation at **[docs.opengeometry.io](https://docs.opengeometry.io?utm_source=github)** describes 3.0: a quickstart, concepts, guides and the API reference. What changed in each release is in [CHANGELOG.md](./CHANGELOG.md). To move code written for 2.0 to 3.0, follow [MIGRATION.md](./MIGRATION.md). ## Repository structure @@ -233,7 +233,7 @@ The hosted documentation at **[docs.opengeometry.io](https://docs.opengeometry.i | [`main/opengeometry/`](./main/opengeometry/) | The Rust kernel, built to WebAssembly | | [`main/opengeometry-three/`](./main/opengeometry-three/) | The Three.js SDK, published as `opengeometry` | | [`main/scripts/`](./main/scripts/) | Build, check, benchmark and snapshot scripts | -| [`docs/`](./docs/) | The 2.0 documentation source, not yet rewritten for 3.0 | +| [`docs/`](./docs/) | The source of the documentation site | ## Building from source diff --git a/developer.md b/developer.md index c4a29643..97283f1e 100644 --- a/developer.md +++ b/developer.md @@ -1,7 +1,7 @@ # Developer Documentation -Contributor-facing notes. For end-user docs see [README.md](./README.md); -[docs.opengeometry.io](https://docs.opengeometry.io) still describes the 2.0 API. +Contributor-facing notes. For end-user docs see [README.md](./README.md) and +[docs.opengeometry.io](https://docs.opengeometry.io), whose source is in [`docs/`](./docs/README.md). ## Prerequisites @@ -123,18 +123,20 @@ commit and says why. The golden file is the only fixture with a record command. 2. If the release changes how existing code must be written, check that `MIGRATION.md` has its entry (its "Adding an entry" section asks for it in the change that broke the code) and rename an "Unreleased" section after the two versions, such as "2.5 to 2.6". -3. Run both gates with `CI` unset on a machine that has a golden file for its target and +3. Rename the `## [Unreleased]` heading of `CHANGELOG.md` to the version and the release + date, and add the same entry to `docs/opengeometry/changelog.mdx`. +4. Run both gates with `CI` unset on a machine that has a golden file for its target and a `timings` block, where the golden comparison, the comparisons with stored results and the timing budgets run: ```bash npm run check npm run check:full ``` -4. Merge to the `main` branch, then start the GitHub Action at +5. Merge to the `main` branch, then start the GitHub Action at `.github/workflows/release.yml` by hand on the `main` branch; a push does not publish. It rebuilds, runs `npm run check` (required to pass), and publishes `main/dist/` to npm if the version is not already on the registry. -5. The action also creates a GitHub release tagged `v`. +6. The action also creates a GitHub release tagged `v`. If the publish step fails for an environmental reason but the version was already bumped, re-running the workflow will re-attempt publish (the action checks npm and only diff --git a/docs/.atlas-analysis.json b/docs/.atlas-analysis.json deleted file mode 100644 index 641a9c29..00000000 --- a/docs/.atlas-analysis.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "projectType": "sdk-library", - "projectName": "OpenGeometry", - "projectDescription": "A high-performance CAD kernel for the web, providing 2D/3D geometric primitives and CAD operations via WebAssembly.", - "theme": "almond", - "primaryColor": "#4460FF", - "lightColor": null, - "darkColor": null, - "navigation": { - "tabs": [ - { - "tab": "Documentation", - "groups": [ - { - "group": "Get Started", - "pages": [ - "introduction", - "installation", - "quickstart" - ] - }, - { - "group": "Core Concepts", - "pages": [ - "concepts/architecture", - "concepts/brep", - "concepts/scene-graph" - ] - }, - { - "group": "Integration", - "pages": [ - "integration/threejs", - "integration/examples" - ] - } - ] - }, - { - "tab": "API Reference", - "groups": [ - { - "group": "2D Primitives", - "pages": [ - "api/primitives/line", - "api/primitives/arc", - "api/primitives/rectangle", - "api/primitives/polyline", - "api/primitives/curve" - ] - }, - { - "group": "3D Shapes", - "pages": [ - "api/shapes/polygon", - "api/shapes/cylinder", - "api/shapes/cuboid", - "api/shapes/sphere", - "api/shapes/wedge", - "api/shapes/sweep" - ] - }, - { - "group": "Operations", - "pages": [ - "api/operations/extrude", - "api/operations/offset", - "api/operations/sweep", - "api/operations/triangulate" - ] - }, - { - "group": "Scene & Export", - "pages": [ - "api/scene/scene-management", - "api/export/projection", - "api/export/pdf" - ] - } - ] - } - ] - }, - "keyFeatures": [ - "WebAssembly-powered geometric kernel written in Rust", - "2D primitives: lines, arcs, rectangles, polylines, curves", - "3D shapes: polygons, cylinders, cuboids, spheres, wedges", - "CAD operations: extrusion, offset, sweep, triangulation", - "BREP (Boundary Representation) data structure", - "Scene graph management for complex models", - "Export to PDF with projection support", - "Three.js integration layer" - ], - "publicApiSurface": [ - "OGLine", - "OGArc", - "OGRectangle", - "OGPolyline", - "OGCurve", - "OGPolygon", - "OGCylinder", - "OGCuboid", - "OGSphere", - "OGWedge", - "OGScene", - "Brep", - "extrude_polygon_by_buffer_geometry", - "offset_polygon", - "sweep_operation", - "triangulate_polygon" - ] -} diff --git a/docs/.mintignore b/docs/.mintignore index 9922f06d..9d54c769 100644 --- a/docs/.mintignore +++ b/docs/.mintignore @@ -1,7 +1,5 @@ -# Mintlify automatically ignores these files and directories: -# .git, .github, .claude, .agents, .idea, node_modules, -# README.md, LICENSE.md, CHANGELOG.md, CONTRIBUTING.md - -# Draft content -drafts/ -*.draft.mdx +package.json +package-lock.json +api-coverage.json +scripts/ +README.md diff --git a/docs/.prettierignore b/docs/.prettierignore new file mode 100644 index 00000000..7d069d17 --- /dev/null +++ b/docs/.prettierignore @@ -0,0 +1,4 @@ +package-lock.json +node_modules +.mintlify +docs/ diff --git a/docs/.prettierrc.json b/docs/.prettierrc.json new file mode 100644 index 00000000..bbb4aa79 --- /dev/null +++ b/docs/.prettierrc.json @@ -0,0 +1,9 @@ +{ + "printWidth": 100, + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md deleted file mode 100644 index 8863ee48..00000000 --- a/docs/CONTRIBUTING.md +++ /dev/null @@ -1,34 +0,0 @@ -> **Customize this file**: Tailor this template to your project by noting specific contribution types you're looking for, adding a Code of Conduct, or adjusting the writing guidelines to match your style. - -# Contribute to the documentation - -Thank you for your interest in contributing to our documentation! This guide will help you get started. - -## How to contribute - -### Option 1: Edit directly on GitHub - -1. Navigate to the page you want to edit -2. Click the "Edit this file" button (the pencil icon) -3. Make your changes and submit a pull request - -### Option 2: Local development - -1. Fork and clone this repository -2. Install the Mintlify CLI: `npm i -g mint` -3. Create a branch for your changes -4. Make changes -5. Navigate to the docs directory and run `mint dev` -6. Preview your changes at `http://localhost:3000` -7. Commit your changes and submit a pull request - -For more details on local development, see our [development guide](development.mdx). - -## Writing guidelines - -- **Use active voice**: "Run the command" not "The command should be run" -- **Address the reader directly**: Use "you" instead of "the user" -- **Keep sentences concise**: Aim for one idea per sentence -- **Lead with the goal**: Start instructions with what the user wants to accomplish -- **Use consistent terminology**: Don't alternate between synonyms for the same concept -- **Include examples**: Show, don't just tell diff --git a/docs/LICENSE b/docs/LICENSE deleted file mode 100644 index 54113742..00000000 --- a/docs/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Mintlify - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 055c983a..aa814ea1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,43 +1,60 @@ -# Mintlify Starter Kit +# OpenGeometry documentation -Use the starter kit to get your docs deployed and ready to customize. +This directory is the Mintlify site for [docs.opengeometry.io](https://docs.opengeometry.io). Keep +`docs.json` at this directory's root. -Click the green **Use this template** button at the top of this repo to copy the Mintlify starter kit. The starter kit contains examples with +Every page lives in `opengeometry/`, because Mintlify builds a page's address from its file path: +`opengeometry/quickstart.mdx` is `/opengeometry/quickstart`. `docs.json`, `style.css`, the logo, +the favicon, `api-coverage.json` and `llms.txt` stay at the top. The redirects in `docs.json` send +the addresses of the 2.0 site to their new pages. -- Guide pages -- Navigation -- Customizations -- API reference pages -- Use of popular components +## Local development -**[Follow the full quickstart guide](https://starter.mintlify.com/quickstart)** +Use Node.js 22 or later. -## Development - -Install the [Mintlify CLI](https://www.npmjs.com/package/mint) to preview your documentation changes locally. To install, use the following command: - -``` -npm i -g mint +```sh +cd docs +npm ci +npm run dev ``` -Run the following command at the root of your documentation, where your `docs.json` is located: +Mintlify prints the local preview address. Preview and strict validation download Mintlify's client +on the first run, so an internet connection is required. -``` -mint dev +Before you submit a change: + +```sh +npm run format +npm run index +npm run check ``` -View your local preview at `http://localhost:3000`. +`npm run check` checks formatting, that `api-coverage.json` and `llms.txt` are current, strict +Mintlify validation, and internal links with heading anchors. Run +`npm run links -- --check-external` when you change external links. -## Publishing changes +## Code in the pages -Install our GitHub app from your [dashboard](https://dashboard.mintlify.com/settings/organization/github-app) to propagate changes from your repo to your deployment. Changes are deployed to production automatically after pushing to the default branch. +Every `ts` block in a page is type-checked against the built package by +`main/scripts/build/readme-code.test.mjs`, together with the README and MIGRATION.md. It runs in the +repository gate (`npm run check` at the root), because it needs `main/dist`. Write each block as a +complete module: its imports, `await OpenGeometry.create(...)`, then the code. Use `bash`, `js`, +`json` or `text` for blocks that must not be compiled. -## Need help? +## API coverage -### Troubleshooting +`scripts/build-index.mjs` reads the exports of `main/opengeometry-three/index.ts` and checks that +each one is named on its API page. It writes `api-coverage.json` and `llms.txt`. When you add an +export, name it on an API page and add it to `PAGES` in the script if the default does not fit: +`OG_*` constants and parameter types go to the Constants page. -- If your dev environment isn't running: Run `mint update` to ensure you have the most recent version of the CLI. -- If a page loads as a 404: Make sure you are running in a folder with a valid `docs.json`. +## Editing -### Resources -- [Mintlify documentation](https://mintlify.com/docs) +- Add MDX pages under `opengeometry/` with `title` and `description` frontmatter and kebab-case + paths. Link between pages with the full address, such as `/opengeometry/quickstart`. +- Add each page to its navigation group in `docs.json`, then run `npm run index`. +- `style.css` draws the tree lines of the Documentation tab. Its selector uses the Changelog route; + update it if that route changes. +- Write in short sentences, one idea each, in the active voice. Define a term before you use it. + Say what the reader sees and what to do. +- Describe only what the package does. Do not document 2.0 calls except on the migration page. diff --git a/docs/api-coverage.json b/docs/api-coverage.json new file mode 100644 index 00000000..0f545529 --- /dev/null +++ b/docs/api-coverage.json @@ -0,0 +1,357 @@ +[ + { + "export": "OpenGeometry", + "kind": "value", + "page": "opengeometry/api/opengeometry" + }, + { + "export": "OGMark", + "kind": "value", + "page": "opengeometry/api/og-mark" + }, + { + "export": "HostGroup", + "kind": "type", + "page": "opengeometry/api/display" + }, + { + "export": "SystemAssembly", + "kind": "value", + "page": "opengeometry/api/system-assembly" + }, + { + "export": "Wire", + "kind": "value", + "page": "opengeometry/api/wire" + }, + { + "export": "Solid", + "kind": "value", + "page": "opengeometry/api/solid" + }, + { + "export": "Sheet", + "kind": "value", + "page": "opengeometry/api/sheet" + }, + { + "export": "BodyEventMap", + "kind": "type", + "page": "opengeometry/api/body" + }, + { + "export": "PointClassification", + "kind": "type", + "page": "opengeometry/api/body" + }, + { + "export": "Measure", + "kind": "type", + "page": "opengeometry/api/body" + }, + { + "export": "Validity", + "kind": "type", + "page": "opengeometry/api/body" + }, + { + "export": "MirrorPlane", + "kind": "type", + "page": "opengeometry/api/body" + }, + { + "export": "OGError", + "kind": "value", + "page": "opengeometry/api/og-error" + }, + { + "export": "ErrorDetails", + "kind": "type", + "page": "opengeometry/api/og-error" + }, + { + "export": "OperateErrorDetails", + "kind": "type", + "page": "opengeometry/api/og-error" + }, + { + "export": "AnalyticExchangeBodyV2", + "kind": "type", + "page": "opengeometry/api/export" + }, + { + "export": "IfcPreparedValue", + "kind": "type", + "page": "opengeometry/api/export" + }, + { + "export": "ArcParams", + "kind": "type", + "page": "opengeometry/api/constants" + }, + { + "export": "ConeParams", + "kind": "type", + "page": "opengeometry/api/constants" + }, + { + "export": "CylinderSectorParams", + "kind": "type", + "page": "opengeometry/api/constants" + }, + { + "export": "PolyhedronParams", + "kind": "type", + "page": "opengeometry/api/constants" + }, + { + "export": "ProfileArc", + "kind": "type", + "page": "opengeometry/api/constants" + }, + { + "export": "ProfileParams", + "kind": "type", + "page": "opengeometry/api/constants" + }, + { + "export": "ProfileSegment", + "kind": "type", + "page": "opengeometry/api/constants" + }, + { + "export": "SphereParams", + "kind": "type", + "page": "opengeometry/api/constants" + }, + { + "export": "TorusParams", + "kind": "type", + "page": "opengeometry/api/constants" + }, + { + "export": "CurvedRegion2D", + "kind": "type", + "page": "opengeometry/api/regions" + }, + { + "export": "CurvedRegionEdge", + "kind": "type", + "page": "opengeometry/api/regions" + }, + { + "export": "OffsetHole", + "kind": "type", + "page": "opengeometry/api/offsets" + }, + { + "export": "OffsetPath2D", + "kind": "type", + "page": "opengeometry/api/offsets" + }, + { + "export": "OffsetPolylineOptions", + "kind": "type", + "page": "opengeometry/api/offsets" + }, + { + "export": "OffsetRegion", + "kind": "type", + "page": "opengeometry/api/regions" + }, + { + "export": "OG_PRIMITIVE_RECTANGLE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_CIRCLE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_POLYLINE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_CUBOID", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_CYLINDER", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_CYLINDER_SECTOR", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_POLYHEDRON", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_SPHERE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_CONE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_TORUS", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PROFILE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_ARC", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_RECTANGLE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_CIRCLE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_POLYLINE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_CUBOID", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_CYLINDER", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_PROFILE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_ARC", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_CYLINDER_SECTOR", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_POLYHEDRON", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_SPHERE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_CONE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_PRIMITIVE_PARAMS_TORUS", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_OPERATION_EXTRUDE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_OPERATION_SWEEP", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_OPERATION_REVOLVE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_OPERATION_UNION", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_OPERATION_SUBTRACT", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_OPERATION_INTERSECT", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_OPERATION_SHELL", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_OPERATION_PARAMS_EXTRUDE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_OPERATION_PARAMS_SWEEP", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_OPERATION_PARAMS_REVOLVE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_TRANSFORM_TRANSLATE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_TRANSFORM_ROTATE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_TRANSFORM_SCALE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_TRANSFORM_PLACE", + "kind": "value", + "page": "opengeometry/api/constants" + }, + { + "export": "OG_REGION_TOLERANCE", + "kind": "value", + "page": "opengeometry/api/constants" + } +] diff --git a/docs/api/core/opengeometry.mdx b/docs/api/core/opengeometry.mdx deleted file mode 100644 index aca9507a..00000000 --- a/docs/api/core/opengeometry.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: OpenGeometry runtime -description: Initialize the OpenGeometry WASM module and control runtime behavior ---- - -## Overview - -Before you construct `Vector3`, kernel-backed primitives, or shapes, initialize OpenGeometry once: - -```ts -import { OpenGeometry } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); -``` - -`OpenGeometry.create(...)` is idempotent. It caches a singleton instance and returns it on -subsequent calls. - - - `Vector3` is wasm-backed in this SDK, so calling `OpenGeometry.create(...)` first is part of the - normal runtime contract. - - -## create - -```ts -await OpenGeometry.create(options); -``` - -### Options - -`OpenGeometryOptions`: - - - URL to `opengeometry_bg.wasm`. This must be reachable from the browser or runtime. - - -## Debug mode - -You can toggle debug mode after initialization: - -```ts -const og = await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); -og.enableDebug = true; -``` - -## Live demo - -Start from the hosted demo index (all demos initialize OpenGeometry): [OpenGeometry demos](https://demo.opengeometry.io/). diff --git a/docs/api/export/ifc.mdx b/docs/api/export/ifc.mdx deleted file mode 100644 index b46c8819..00000000 --- a/docs/api/export/ifc.mdx +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: IFC export (experimental) -description: Export strict analytic BRep v2 geometry directly or prepare it for semantic IFC assembly ---- - -## Overview - -Analytic IFC export has two v2 workflows: - -- `solid.exportIfc()` writes one IFC4 product directly from the authoritative BRep. -- `solid.prepareIfcExchange()` returns the strict Rust-prepared `AnalyticExchangeBodyV2` used by a - semantic BIM assembler such as Floorkit and `openplans-ifc-py`. - -Both workflows retain analytic surfaces and curves, actual face/bound orientations, cavities, -general bounded intersection curves, and face provenance. They do not inspect a viewport mesh. - -```ts -import { OpenGeometry } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); -``` - -## Direct IFC text - -```ts -import { Cuboid } from "opengeometry"; - -const wall = new Cuboid({ width: 6, height: 3, depth: 0.3 }); -const result = wall.exportIfc(); - -console.log(result.report.schema_version); // 2 -console.log(result.text); -``` - -`result.report` is the same prepared body used to assemble the IFC text. It reports world-metre, -Z-up geometry, revision, quality, exchange error, entities, solid roots, and per-face provenance. -World placement is applied once. - -## Semantic exchange - -```ts -const geometry = wall.prepareIfcExchange(); - -const payload = { - schemaVersion: "2.0", - elements: [{ - type: "FREEFORM_ANALYTIC", - id: "wall-1", - name: "Exterior wall", - ifcClass: "IfcWall", - geometries: [geometry], - }], -}; -``` - -`geometries` is a required nonempty array. This keeps a composite authored element as one semantic -IFC product while retaining every exact body. Semantic openings remain explicit relationships; the -host geometry and opening cutter are both prepared by Rust, while the downstream service creates -the IFC products and relations. - -The semantic schema version is exactly `"2.0"`. Schema-v1 payloads, a singular legacy `geometry` -field, compatibility defaults, and faceted fallback are rejected. - -## Download direct IFC in the browser - -```ts -const blob = new Blob([result.text], { type: "application/x-step" }); -const url = URL.createObjectURL(blob); -const link = document.createElement("a"); -link.href = url; -link.download = "model.ifc"; -link.click(); -URL.revokeObjectURL(url); -``` - -## Related - -- [Analytic solid](/api/shapes/analytic-solid) -- [Exports](/concepts/exports) -- [STEP export](/api/export/step) - -## Live demo - -[Analytic STEP and IFC demo](https://demo.opengeometry.io/operations/analytic-step-export.html) diff --git a/docs/api/export/pdf.mdx b/docs/api/export/pdf.mdx deleted file mode 100644 index 0cae5730..00000000 --- a/docs/api/export/pdf.mdx +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: PDF export (experimental) -description: Export projected 2D scenes to vector PDF documents in native builds ---- - -## Overview - -OpenGeometry can export projected 2D scenes to vector PDF documents. The current public story is: - -- use projection APIs to derive 2D output from B-Rep geometry -- use native Rust PDF export helpers when you need configurable output -- optionally use `WorldGraph::project_to_pdf(...)` as a native convenience path - - -PDF export is experimental. Output and APIs may change. If you hit an exporter limitation or -confusing output, reach out on [Discord](https://discord.gg/9wJpbfgGGA). - - - -PDF export is only available in native (non-WASM) builds. Browser/WASM builds do not include the -PDF writer. - - -## Native WorldGraph convenience API - -In native Rust builds, `WorldGraph` projects a set of nodes and writes the PDF in one call: - -```rust -use opengeometry::export::pdf::PdfExportConfig; -use opengeometry::export::projection::{CameraParameters, HlrOptions}; -use opengeometry::world::WorldGraph; - -graph.project_to_pdf( - &["room".to_string()], - &CameraParameters::default(), - &HlrOptions::default(), - 0.01, - "technical-drawing.pdf", - &PdfExportConfig::default(), -)?; -``` - -This method: - -1. projects the bodies under the given nodes to 2D with their world transforms -2. applies hidden line removal if requested -3. writes the PDF with the given `PdfExportConfig` - -## Rust PDF API - -When you need configurable export, the native Rust API is the current source of truth. - -### PdfExportConfig - -```rust -pub struct PdfExportConfig { - pub page_width_mm: f64, - pub page_height_mm: f64, - pub margin_mm: f64, - pub line_width_mm: f64, - pub auto_fit: bool, - pub title: Option, -} -``` - -Default configuration: - -```rust -PdfExportConfig { - page_width_mm: 297.0, - page_height_mm: 210.0, - margin_mm: 10.0, - line_width_mm: 0.25, - auto_fit: true, - title: None, -} -``` - -### Core Rust helpers - -```rust -pub fn export_scene_to_pdf(scene: &Scene2D, file_path: &str) -> PdfExportResult<()> -pub fn export_scene_to_pdf_with_config( - scene: &Scene2D, - file_path: &str, - config: &PdfExportConfig, -) -> PdfExportResult<()> -pub fn export_scene_to_pdf_bytes( - scene: &Scene2D, - config: &PdfExportConfig, -) -> PdfExportResult> -``` - -### Example (Rust) - -```rust -use opengeometry::export::pdf::{export_scene_to_pdf_with_config, PdfExportConfig}; -use opengeometry::export::projection::{project_brep_to_scene, CameraParameters, HlrOptions}; - -let scene = project_brep_to_scene(&brep, &CameraParameters::default(), &HlrOptions::default()); - -let config = PdfExportConfig { - margin_mm: 15.0, - line_width_mm: 0.35, - title: Some("OpenGeometry Drawing".to_string()), - ..PdfExportConfig::default() -}; - -export_scene_to_pdf_with_config(&scene, "drawing.pdf", &config)?; -``` - -## Notes - -- Input projection units are meters. PDF output is in millimeters. -- `auto_fit: true` scales and centers the drawing on the page. -- If you need custom paper sizes or in-memory bytes output, use the Rust PDF helpers directly. - -## Related - -- [Projection & hidden line removal](/api/export/projection) -- [WorldGraph](/api/scene/scene-management) -- [Exports](/concepts/exports) diff --git a/docs/api/export/projection.mdx b/docs/api/export/projection.mdx deleted file mode 100644 index bd6225e1..00000000 --- a/docs/api/export/projection.mdx +++ /dev/null @@ -1,148 +0,0 @@ ---- -title: Projection & hidden line removal (experimental) -description: Project 3D B-Rep geometry to 2D JSON with optional hidden line removal ---- - -## Overview - -OpenGeometry projects geometry placed in a [`WorldGraph`](/api/scene/scene-management) to 2D vector -data with optional hidden line removal. You usually: - -1. Create wrapper geometry such as `Cuboid`, `Polygon`, `Solid`, or boolean results. -2. Add it to a `WorldGraph` — `define(...)` for analytic solids, `defineLegacy(...)` for schema-v1 - BReps — and place it with nodes. -3. Call `projectLines(...)` or `projectViews(...)` with the nodes you want drawn. - - -Projection and hidden line removal are experimental. Output and option shapes may change. If you -hit a limitation or confusing output, reach out on -[Discord](https://discord.gg/9wJpbfgGGA). - - -## Initialization - -```ts -import { OpenGeometry } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); -``` - -## Projection APIs - -### projectLines() - -Projects the bodies under `items` to a flat `Scene2DLines` payload. - -```ts -const { lines } = graph.projectLines(items, camera, hlr, deflection); -``` - -- `items` — node ids; each node's whole subtree is projected once -- `camera` — `CameraParameters` object (see below) -- `hlr` — optional hidden line removal options -- `deflection` — tessellation tolerance for curved analytic surfaces, in world units (default `0.01`) - -### projectViews() - -Projects the same items once per view and returns `{ [viewId]: Scene2D }`. Every segment carries -`source_entity_id` (the node id) and `layer`, an AIA code derived from the nearest node `kind`. - -```ts -const views = graph.projectViews(items, [ - { id: "iso", camera }, - { id: "front", camera: frontCamera, hlr: { hide_hidden_edges: false } }, -], 0.01); -``` - -## Camera JSON - -Cameras follow the kernel `CameraParameters` shape: - -```ts -const camera = { - position: { x: 8, y: 6, z: 8 }, - target: { x: 0, y: 0, z: 0 }, - up: { x: 0, y: 1, z: 0 }, - near: 0.1, - projection_mode: "Orthographic" as const, -}; -``` - -Supported `projection_mode` values: - -- `"Orthographic"` -- `"Perspective"` - -## Hidden line removal JSON - -Hidden line removal options: - -```ts -const hlr = { hide_hidden_edges: true }; -``` - -When `hide_hidden_edges` is `false`, projection behaves more like a wireframe export. - -## Example - -### Project wrapper geometry to 2D - -```ts -import { Cuboid, OpenGeometry, Vector3, WorldGraph } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); - -const graph = new WorldGraph(); -graph.define("box", new Cuboid({ center: new Vector3(0, 1.5, 0), width: 5, height: 3, depth: 2 })); -graph.addNode({ id: "box-1", definition: "box" }); - -const { lines } = graph.projectLines( - ["box-1"], - { - position: { x: 8, y: 6, z: 8 }, - target: { x: 0, y: 0, z: 0 }, - up: { x: 0, y: 1, z: 0 }, - near: 0.1, - projection_mode: "Orthographic", - }, - { hide_hidden_edges: true }, -); -console.log(lines.length); -``` - -## Output shapes - -### Scene2D - -`projectViews(...)` returns one `Scene2D` per view: - -- `name?: string` — the view id -- `segments: ClassifiedSegment[]` — each with `geometry`, edge `class`, `layer`, and - `source_entity_id` - -### Scene2DLines - -`projectLines(...)` returns a flat line list: - -- `name?: string` -- `lines: Line2D[]` - -This form is often easier to post-process for custom exporters. - -## Projection behavior - -- Orthographic views are the best fit for technical drawings. -- Perspective views are useful when you want a presentation-style outline projection. -- Hidden line removal works from the stored B-Rep topology, not from rendered triangle meshes. -- Hidden edges are resolved per body; bodies do not yet occlude each other. - -## Related - -- [WorldGraph](/api/scene/scene-management) -- [PDF export](/api/export/pdf) -- [Exports](/concepts/exports) - -## Live demo - -There is no dedicated projection demo page yet. Start from the demo index: -[OpenGeometry demos](https://demo.opengeometry.io/). diff --git a/docs/api/export/step.mdx b/docs/api/export/step.mdx deleted file mode 100644 index a7286c8d..00000000 --- a/docs/api/export/step.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: STEP export (experimental) -description: Export strict analytic BRep v2 solids to STEP Part 21 text ---- - -## Overview - -`AnalyticSolid.exportStep()` exports the authoritative BRep directly. Plane, sphere, cylinder, -cone, and ring-torus surfaces remain analytic; shared curves, trims, orientations, cavities, and -boolean face topology are retained. Viewport triangles are not read or regrouped. - -Initialize the WASM runtime before constructing geometry: - -```ts -import { OpenGeometry } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); -``` - -## Export a solid - -```ts -import { Cuboid } from "opengeometry"; - -const cuboid = new Cuboid({ - width: 2, - height: 1, - depth: 1.2, - color: 0x0ea5e9, -}); - -const result = cuboid.exportStep("metre"); -console.log(result.report); -``` - -The length unit is required to be `"metre"` or `"millimetre"`. Authored coordinates are metres; -the exporter applies the selected conversion once. Positive uniform Three.js placement is applied -once before export. Nonuniform placement is rejected because it would change the analytic surface -families. - -## Result - -`exportStep()` returns: - -- `text`: STEP Part 21 text -- `report.schema_version`: always `2` -- `report.revision`: the exported model revision -- `report.length_unit`: the selected unit -- face, edge, solid, cavity, singular-use, tolerance, quality, and validation statistics - -The call fails with a structured analytic geometry error if the model is invalid or its exchange -budget cannot be met. It never replaces unsupported analytic geometry with facets. - -## Download in the browser - -```ts -const blob = new Blob([result.text], { type: "model/step" }); -const url = URL.createObjectURL(blob); -const link = document.createElement("a"); -link.href = url; -link.download = "model.step"; -link.click(); -URL.revokeObjectURL(url); -``` - -## Related - -- [Analytic solid](/api/shapes/analytic-solid) -- [Exports](/concepts/exports) -- [IFC export](/api/export/ifc) -- [STL export](/api/export/stl) - -## Live demo - -[STEP export demo](https://demo.opengeometry.io/operations/step-export.html) diff --git a/docs/api/export/stl.mdx b/docs/api/export/stl.mdx deleted file mode 100644 index a2f6ae3f..00000000 --- a/docs/api/export/stl.mdx +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: STL export (experimental) -description: Tessellate strict analytic BRep v2 solids to binary STL at an explicit error bound ---- - -## Overview - -STL stores triangles, so `AnalyticSolid.exportStl(deflection)` tessellates the authoritative BRep -for export. The generated triangles are transient and do not replace surfaces, curves, trims, or -topology in the model. - -Initialize the WASM runtime before constructing geometry: - -```ts -import { OpenGeometry } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); -``` - -## Export a solid - -```ts -import { Cuboid } from "opengeometry"; - -const cuboid = new Cuboid({ width: 2, height: 1, depth: 1 }); -const result = cuboid.exportStl(0.005); -``` - -`deflection` is a positive distance in authored metres. Shared edges are sampled once, adjoining -faces reuse those positions, and curved normals come from the analytic supports. World placement, -including positive uniform scale, is applied before tessellation. - -## Result - -`exportStl()` returns: - -- `bytes`: binary STL as a `Uint8Array` -- `report.schema_version`: always `2` -- `report.revision`: the tessellated model revision -- `report.triangle_count` -- `report.requested_deflection` -- `report.achieved_deflection` -- `report.float32_encoding_error` -- `report.quality`: `"tessellated_from_analytic_brep"` - -Binary STL stores coordinates as Float32. If tessellation plus Float32 encoding cannot meet the -requested bound, the call fails instead of claiming that tolerance. - -## Download in the browser - -```ts -const blob = new Blob([result.bytes], { type: "model/stl" }); -const url = URL.createObjectURL(blob); -const link = document.createElement("a"); -link.href = url; -link.download = "model.stl"; -link.click(); -URL.revokeObjectURL(url); -``` - -## Write in Node.js - -```ts -import { writeFileSync } from "node:fs"; - -writeFileSync("model.stl", Buffer.from(result.bytes)); -``` - -## Related - -- [Analytic solid](/api/shapes/analytic-solid) -- [Exports](/concepts/exports) -- [STEP export](/api/export/step) - -## Live demo - -[STL export demo](https://demo.opengeometry.io/operations/stl-export.html) diff --git a/docs/api/operations/boolean-operations.mdx b/docs/api/operations/boolean-operations.mdx deleted file mode 100644 index 325dd49c..00000000 --- a/docs/api/operations/boolean-operations.mdx +++ /dev/null @@ -1,163 +0,0 @@ ---- -title: Boolean operations -description: Combine strict analytic BRep v2 solids with the in-house boolean engine -icon: "shapes" ---- - -## Overview - -OpenGeometry booleans operate on authoritative analytic BRep v2 solids. They preserve retained -surfaces and curves, rebuild trims, record face provenance, and tessellate only for rendering. -Faceted and schema-v1 operands are rejected. - -Initialize the WASM runtime before constructing operands: - -```ts -import { OpenGeometry } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); -``` - -## API - -The standalone helpers are binary: - -```ts -import { - booleanUnion, - booleanIntersection, - booleanSubtraction, -} from "opengeometry"; - -const union = booleanUnion(a, b, options); -const common = booleanIntersection(a, b, options); -const cut = booleanSubtraction(a, b, options); -``` - -Every operand must be an `AnalyticSolid`, including the public analytic `Cylinder` and `Sphere` -wrappers. Raw JSON and schema-v1 shape wrappers are not accepted. - -`AnalyticSolid` also exposes `union(other)`, `intersection(other)`, and array-only -`subtract(cutters)`. Multiple subtraction cutters are applied in order: - -```ts -const cut = wall.subtract([door, window], { - deflection: 0.005, - color: 0x10b981, -}); -``` - -## Options - - - Chord-error bound used to tessellate the returned solid. It does not alter the boolean model. - - - - Surface material color for the returned solid. - - - - Material opacity for standalone helper results. - - - - Enables or disables material transparency for standalone helper results. - - - - Three.js material side for standalone helper results. - - - - Shows analytic feature edges. Standalone helpers default this to `true`. - - -## Result - -The helpers return an `AnalyticSolid`. Use: - -- `result.getBrepSerialized()` for strict schema-v2 model JSON -- `result.report` for operation, contacts, coincident ownership, and input-to-result face mappings -- `result.faceIdForTriangle(...)` and `result.edgeIdForOutlineSegment(...)` for picking -- `result.retessellate(deflection)` to change render density without changing topology -- `result.exportStep(...)`, `result.prepareIfcExchange()`, or `result.exportIfc()` for analytic exchange -- `result.dispose()` when removing the result permanently - -## Structured errors - -Kernel failures throw `AnalyticGeometryError`. Its `code` identifies failures such as -`coverage_gap`, `unresolved_intersection`, `invalid_topology`, or `limit_exceeded`. -`coverage_gap` also exposes the unsupported surface-family pair through `families`. - -```ts -import { AnalyticGeometryError } from "opengeometry"; - -try { - const cut = booleanSubtraction(host, cutter); - scene.add(cut); -} catch (error) { - if (error instanceof AnalyticGeometryError) { - console.error(error.code, error.families, error.message); - } -} -``` - -An unresolved or unsupported analytic case is an error. The API does not fall back to a mesh -boolean or turn an unknown classification into outside. - -The cuboid fast paths include aligned planar arrangements, perpendicular cylindrical through-holes -and blind pockets for union, intersection, and subtraction, the complementary cylinder-minus-cuboid remnants, and sphere/cuboid intersections -that cross exactly one cuboid face. The spherical -path returns an exact circle trim and spherical cap for union, intersection, and either subtraction -order. Cases crossing -multiple cuboid faces continue through later intersection coverage and currently return -`coverage_gap`. - -## Example - -```ts -import * as THREE from "three"; -import { - AnalyticSolid, - OpenGeometry, - Sphere, - Vector3, - booleanSubtraction, -} from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); - -const scene = new THREE.Scene(); -const host = new AnalyticSolid({ - kind: "cuboid", - width: 4, - depth: 2, - height: 3, - deflection: 0.01, - color: 0x9ca3af, -}); -const cutter = new Sphere({ - center: new Vector3(0, 1.5, 0), - radius: 0.8, - deflection: 0.01, -}); - -const result = booleanSubtraction(host, cutter, { - deflection: 0.005, - color: 0x10b981, - outline: true, -}); -scene.add(result); -``` - -## Related - -- [Booleans](/concepts/booleans) -- [Analytic solid](/api/shapes/analytic-solid) - -## Live demos - -- [Boolean operations demo](https://demo.opengeometry.io/operations/boolean-operations.html) -- [Analytic boolean coverage demo](https://demo.opengeometry.io/operations/analytic-boolean-operations.html) -- [Extruded boolean operations demo](https://demo.opengeometry.io/operations/extruded-boolean-operations.html) diff --git a/docs/api/operations/extrude.mdx b/docs/api/operations/extrude.mdx deleted file mode 100644 index e218ad47..00000000 --- a/docs/api/operations/extrude.mdx +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: 'Extrude' -description: 'Create closed solids by extruding a face-like BRep profile through the kernel' -icon: 'cubes' ---- - -## Overview - -OpenGeometry's production extrusion path is BRep-first. The kernel extrudes a face or wire into a -closed solid while preserving loop structure, which means concave profiles and holes are supported. -This is the main extrusion workflow for browser CAD and AEC/BIM tasks that start from planar -profiles. - -In the Three.js API, the most common public entrypoint is: - -```ts -const solid = polygon.extrude(height); -``` - -That path uses the same kernel face-extrusion primitive described on this page. - -## Three.js API - -### polygon.extrude() - -Extrudes a `Polygon` and returns a renderable [`Solid`](/api/shapes/solid). - -```ts -const solid = polygon.extrude(height); -``` - -### Solid.extrude() - -Extrudes a face-like BRep source and wraps the result as a `Solid`. - -```ts -const solid = Solid.extrude(source, height, options); -``` - -### extrudeBrepFace() - -Low-level helper that calls the wasm export directly and returns serialized BRep JSON. - -```ts -import { extrudeBrepFace } from "opengeometry"; - -const brepSerialized = extrudeBrepFace(source, height); -``` - -Accepted `source` forms: - -- Serialized local BRep JSON -- Parsed BRep object -- Another wrapper exposing `getLocalBrepSerialized()` -- Another wrapper exposing `getLocalBrepData()` -- Another wrapper exposing `getBrepSerialized()` or `getBrepData()` - -## Rust API - -### extrude_brep_face - -```rust -pub fn extrude_brep_face(brep_face: Brep, height: f64) -> Brep -``` - -This is implemented in: - -`main/opengeometry/src/operations/extrude.rs` - -## Behavior - -- The kernel extrudes along the current local Y direction. -- The source must contain a face-like profile, wire, or at minimum a usable point loop. -- Outer loops and hole loops are preserved, so polygons with holes stay hole-aware after extrusion. -- Concave profiles are supported. -- `height` must be finite and non-zero. -- The result is a closed-shell BRep suitable for boolean operations. - -## Usage Examples - -### Analytic profile extrusion and cut - -```ts -import * as THREE from "three"; -import { AnalyticSolid, OpenGeometry } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); - -const scene = new THREE.Scene(); - -const wall = new AnalyticSolid({ - kind: "linearExtrusion", - outer: [[-2.2, -0.18], [2.2, -0.18], [2.2, 0.18], [-2.2, 0.18]], - holes: [], - height: 2.8, - color: 0x60a5fa, -}); -const opening = new AnalyticSolid({ - kind: "linearExtrusion", - outer: [[-0.7, -0.34], [0.9, -0.34], [0.9, 0.34], [-0.7, 0.34]], - holes: [], - height: 1.35, -}); -opening.position.y = 0.85; - -const cut = wall.subtract([opening], { deflection: 0.005 }); - -scene.add(cut); -``` - -### Direct low-level helper - -```ts -import { Solid, extrudeBrepFace } from "opengeometry"; - -const extrudedBrep = extrudeBrepFace(localFaceBrepSerialized, 3.0); - -const solid = new Solid({ - brep: extrudedBrep, - color: 0x10b981, -}); -``` - -### Rust kernel usage - -```rust -use opengeometry::{ - brep::BrepBuilder, - operations::extrude::extrude_brep_face, -}; -use openmaths::Vector3; -use uuid::Uuid; - -let mut builder = BrepBuilder::new(Uuid::new_v4()); -builder.add_vertices(&[ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(1.0, 0.0, 0.0), - Vector3::new(1.0, 0.0, 1.0), - Vector3::new(0.0, 0.0, 1.0), -]); -builder.add_face(&[0, 1, 2, 3], &[]).unwrap(); -let profile = builder.build().unwrap(); - -let solid = extrude_brep_face(profile, 3.0); -assert!(solid.shells.iter().any(|shell| shell.is_closed)); -``` - -## See Also - -- [Polygon](/api/shapes/polygon) -- [Solid](/api/shapes/solid) -- [Sweep](/api/operations/sweep) -- [Boolean operations](/api/operations/boolean-operations) - -## Live demo - -- [Extruded boolean operations demo](https://demo.opengeometry.io/operations/extruded-boolean-operations.html) diff --git a/docs/api/operations/loft.mdx b/docs/api/operations/loft.mdx deleted file mode 100644 index f035cfc4..00000000 --- a/docs/api/operations/loft.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: 'Polygon loft' -description: 'Create a capped ruled solid between two planar polygon sections' -icon: 'layer-group' ---- - -## Overview - -`loftPolygonSections()` creates an authoritative Plane/Line BRep between two closed polygon -sections. `Polygon.loftTo()` provides the same operation directly from two placed polygon wrappers. -The operation matches winding and cyclic start indices automatically, constructs one shared edge -for every paired boundary, and caps both ends. - -```ts -import { loftPolygonSections } from "opengeometry"; - -const solid = loftPolygonSections([ - [[-1, -1, 0], [1, -1, 0], [1, 1, 0], [-1, 1, 0]], - [[-.6, -.6, 2], [.6, -.6, 2], [.6, .6, 2], [-.6, .6, 2]], -], { deflection: 0.01 }); -``` - -From existing polygons: - -```ts -const solid = lower.loftTo(upper, { - alignment: "auto", - deflection: 0.01, - color: 0x329ac7, -}); -``` - -Both paths return an [`AnalyticSolid`](/api/shapes/analytic-solid). The source polygons remain -unchanged and are not retained as hidden dependencies of the result. - -## Requirements - -- Each section is a simple closed polygon with at least three vertices. -- The sections have the same vertex count and no holes. -- Both section planes are parallel and separated by more than the geometric tolerance. -- Every corresponding side quadrilateral is planar. -- Automatic alignment must have one unambiguous minimum-length correspondence. - -Reversed winding and different start vertices are supported. If symmetry creates multiple equally -good correspondences, provide an indexed alignment: - -```ts -const solid = lower.loftTo(upper, { - alignment: { upperStartIndex: 2, reverseUpper: true }, -}); -``` - -Unequal vertex counts and warped side quadrilaterals return `unsupported_geometry`. Ambiguous -automatic correspondence returns `ambiguous_profile_alignment`. General twisted and smooth lofts -need a ruled-surface or spline surface family and are not silently triangulated. - -## Live examples - -- [OpenGeometry polygon loft](https://demo.opengeometry.io/operations/polygon-loft.html) - diff --git a/docs/api/operations/offset.mdx b/docs/api/operations/offset.mdx deleted file mode 100644 index 1b42793c..00000000 --- a/docs/api/operations/offset.mdx +++ /dev/null @@ -1,272 +0,0 @@ ---- -title: 'Offset' -description: 'Generate parallel offset paths from polylines and polygons with smart corner handling' -icon: 'clone' ---- - -## Overview - -The offset operation creates a new path parallel to the input path at a specified distance. It intelligently handles corners with mitering or beveling, supports both open and closed paths, and maintains geometric correctness for complex shapes. - -## Function Signature - -```rust -pub fn offset_path( - points: &[Vector3], - distance: f64, - force_closed: Option, - options: OffsetOptions, -) -> OffsetResult -``` - -Generates an offset path from a sequence of points. - - - Array of 3D points defining the path to offset. For 2D paths, use the XZ plane (Y=0 or constant). - - - - Offset distance. Positive values offset to the left (counter-clockwise side), negative values offset to the right. The distance is measured perpendicular to the path direction. - - - - Explicitly specify whether the path should be treated as closed: - - `Some(true)`: Force closed path - - `Some(false)`: Force open path - - `None`: Auto-detect (closed if first and last points are nearly identical) - - - - Configuration options controlling corner handling behavior. - - -## Configuration - -### OffsetOptions - -```rust -pub struct OffsetOptions { - pub bevel: bool, - pub acute_threshold_degrees: f64, -} -``` - - - Enable beveling for outer corners when the interior angle is below the threshold. When `true`, sharp corners are cut off creating two vertices; when `false`, attempts to miter all corners. - - - - The interior angle threshold (in degrees) for sharp-corner fallback. Outer corners bevel when `bevel` is enabled and the angle is at or below the threshold. Open-path inner corners clip instead of mitering when the angle is at or below the threshold. Valid range: 1.0 to 179.0 degrees. Higher values apply beveling and clipping more aggressively. - - -### Default Options - -```rust -OffsetOptions { - bevel: true, - acute_threshold_degrees: 35.0, -} -``` - -## Return Type - -### OffsetResult - -```rust -pub struct OffsetResult { - pub points: Vec, - pub beveled_vertex_indices: Vec, - pub is_closed: bool, -} -``` - - - The offset path vertices. For closed paths, the last point duplicates the first. - - - - Indices of vertices in the original path where outer-corner beveling was applied. Open-path inner-corner clipping can also add points, but those vertices are not included here because they are not bevels. - - - - Whether the result is a closed loop. - - -## How It Works - -1. **Path Sanitization**: Removes consecutive duplicate points and detects if the path is closed -2. **Segment Analysis**: Calculates unit direction vectors and left-normal vectors for each segment -3. **Corner Processing**: - - **Straight segments**: Simple perpendicular offset - - **Outer corners**: Mitered intersection or beveled based on angle threshold - - **Inner corners** (open paths): Mitered for broader turns, clipped below the threshold to prevent spikes - - **Collinear segments**: Merged smoothly -4. **Path Closing**: For closed paths, ensures first and last points match exactly - -## Code Examples - -### Basic Line Offset - -```rust -use opengeometry::operations::offset::{offset_path, OffsetOptions}; -use openmaths::Vector3; - -// Straight line from origin to (5, 0, 0) -let line = vec![ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(5.0, 0.0, 0.0), -]; - -// Offset 1 unit to the left (positive Z direction) -let result = offset_path(&line, 1.0, Some(false), OffsetOptions::default()); - -// Result points at Z=1.0: -// Vector3::new(0.0, 0.0, 1.0) -// Vector3::new(5.0, 0.0, 1.0) -assert_eq!(result.points.len(), 2); -assert!((result.points[0].z - 1.0).abs() < 1e-6); -``` - -### Closed Rectangle Offset - -```rust -use opengeometry::operations::offset::{offset_path, OffsetOptions}; -use openmaths::Vector3; - -// Rectangle -let rectangle = vec![ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(2.0, 0.0, 0.0), - Vector3::new(2.0, 0.0, 2.0), - Vector3::new(0.0, 0.0, 2.0), - Vector3::new(0.0, 0.0, 0.0), // Close the loop -]; - -// Inset by 0.2 units (negative offset) -let result = offset_path(&rectangle, -0.2, None, OffsetOptions::default()); - -assert!(result.is_closed); -assert!(result.points.len() >= 5); -``` - -### Beveling Acute Corners - -```rust -use opengeometry::operations::offset::{offset_path, OffsetOptions}; -use openmaths::Vector3; - -// Path with a sharp corner -let sharp_path = vec![ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(2.0, 0.0, 0.0), - Vector3::new(1.0, 0.0, 0.3), // Creates acute angle -]; - -let result = offset_path( - &sharp_path, - 0.3, - Some(false), - OffsetOptions { - bevel: true, - acute_threshold_degrees: 45.0, - }, -); - -// Check that beveling occurred -assert!(!result.beveled_vertex_indices.is_empty()); -assert!(result.points.len() >= 4); // Extra vertex from bevel -``` - -### Custom Corner Handling - -```rust -use opengeometry::operations::offset::{offset_path, OffsetOptions}; -use openmaths::Vector3; - -let path = create_complex_path(); // Your path creation logic - -// Aggressive beveling for smoother offsets -let smooth_options = OffsetOptions { - bevel: true, - acute_threshold_degrees: 60.0, -}; - -// Sharp corners with minimal beveling -let sharp_options = OffsetOptions { - bevel: true, - acute_threshold_degrees: 20.0, -}; - -let smooth_result = offset_path(&path, 0.5, None, smooth_options); -let sharp_result = offset_path(&path, 0.5, None, sharp_options); -``` - -## Visual Examples - -``` -Open Path Offset: - -Original: Offset (distance=0.5): - - p1────p2 p1'──p2' - │ │ - p0────p1 → p0'──p1' - - -Closed Path with Beveled Corner: - - Offset with beveling: - p2 - ╱│ ┌─────┐ - ╱ │ → │ ╱b2│ (corner beveled) - p0─p1 b1───┘ -``` - -## Corner Behavior - -### Outer Corners - -- **Angle > threshold**: Mitered (intersection point calculated) -- **Angle ≤ threshold**: Beveled (two vertices inserted) -- **Parallel segments**: Smooth continuation - -### Inner Corners - -- **Closed paths**: Mitered to intersection point -- **Open paths, angle > threshold**: Mitered to intersection point -- **Open paths, angle ≤ threshold**: Clipped with two vertices to prevent long spikes - -## Implementation Details - -### Source Location - -`main/opengeometry/src/operations/offset.rs` - -### Precision - -- Uses `EPSILON = 1.0e-9` for geometric comparisons -- Works in 2D projection (XZ plane, Y preserved) -- Robust handling of degenerate cases (zero-length segments, duplicate points) - -### Performance Considerations - -- Linear time complexity: O(n) where n is the number of input points -- Minimal memory allocation beyond output storage -- Removes duplicate points during sanitization - -## Edge Cases - -- **Zero distance**: Returns a copy of the input path -- **Insufficient points**: Returns empty result -- **Collinear points**: Handled gracefully with tangent smoothing -- **Self-intersecting paths**: Not automatically resolved; may produce overlapping geometry - -## See Also - -- [Sweep](/api/operations/sweep) - Offset a profile along a path -- [Extrude](/api/operations/extrude) - Create 3D geometry from 2D shapes - -## Live demo - -- [Offset demo](https://demo.opengeometry.io/operations/offset.html) -- [Wall from offsets demo](https://demo.opengeometry.io/operations/wall-from-offsets.html) diff --git a/docs/api/operations/sweep.mdx b/docs/api/operations/sweep.mdx deleted file mode 100644 index 5bde9097..00000000 --- a/docs/api/operations/sweep.mdx +++ /dev/null @@ -1,298 +0,0 @@ ---- -title: 'Sweep' -description: 'Create 3D surfaces by sweeping a profile shape along a path with automatic frame calculation' -icon: 'route' ---- - -## Overview - -The sweep operation generates a 3D surface (BREP) by moving a 2D profile shape along a 3D path. It automatically computes rotation-minimizing frames along the path to prevent twisting, making it ideal for creating pipes, tubes, rails, and architectural moldings. - -## Function Signature - -```rust -pub fn sweep_profile_along_path( - path_points: &[Vector3], - profile_points: &[Vector3], - options: SweepOptions, -) -> Brep -``` - -Sweeps a profile curve along a path curve to create a 3D boundary representation. - - - The 3D path curve to sweep along. Must have at least 2 points. If the first and last points are identical (within epsilon), the path is treated as closed. - - - - The 2D or 3D profile shape to sweep. Must have at least 3 points to form a valid closed profile. The profile is automatically centered and oriented relative to the path. - - - - Configuration controlling end cap generation. - - -## Configuration - -### SweepOptions - -```rust -pub struct SweepOptions { - pub cap_start: bool, - pub cap_end: bool, -} -``` - - - Generate a closed face at the start of the sweep (only for open paths). Set to `false` to create an open tube. - - - - Generate a closed face at the end of the sweep (only for open paths). Set to `false` to create an open tube. - - -### Default Options - -```rust -SweepOptions { - cap_start: true, - cap_end: true, -} -``` - -## Return Type - -Returns a `Brep` (Boundary Representation) using OpenGeometry's current half-edge topology schema -(see [BRep](/concepts/brep)). At a high level, the result contains: - -- Vertices for each profile section placed along the path -- Side faces connecting successive sections -- Optional end caps (for open paths) when enabled - -## How It Works - -1. **Path Sanitization**: Removes consecutive duplicate points and detects if the path forms a closed loop -2. **Profile Preparation**: - - Computes profile centroid - - Calculates profile plane normal - - Converts profile to local coordinates (u, v, w basis) -3. **Frame Calculation**: - - Computes tangent vectors along the path - - Builds rotation-minimizing frames using parallel transport - - Ensures smooth frame transitions without twisting -4. **Vertex Placement**: Transforms each profile point into world space at each path section -5. **Face Generation**: - - Creates quadrilateral side faces connecting successive sections - - Adds end caps for open paths (if enabled) - - Connects vertices to form a watertight mesh - -## Code Examples - -### Basic Sweep: Creating a Pipe - -```rust -use opengeometry::{ - brep::Brep, - operations::sweep::{sweep_profile_along_path, SweepOptions}, -}; -use openmaths::Vector3; - -// Straight path from origin upward -let path = vec![ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(0.0, 2.0, 0.0), -]; - -// Circular profile (approximated with 8 points) -let radius = 0.5; -let segments = 8; -let mut profile = Vec::new(); -for i in 0..segments { - let angle = (i as f64) * 2.0 * std::f64::consts::PI / (segments as f64); - profile.push(Vector3::new( - radius * angle.cos(), - 0.0, - radius * angle.sin(), - )); -} - -let pipe = sweep_profile_along_path(&path, &profile, SweepOptions::default()); - -// Result: A capped cylinder -assert_eq!(pipe.vertices.len(), 16); // 8 profile × 2 sections -assert_eq!(pipe.faces.len(), 10); // 8 sides + 2 caps -``` - -### Curved Path Sweep - -```rust -use opengeometry::operations::sweep::{sweep_profile_along_path, SweepOptions}; -use openmaths::Vector3; - -// Curved path (quarter circle arc) -let mut path = Vec::new(); -for i in 0..=10 { - let t = (i as f64) / 10.0; - let angle = t * std::f64::consts::PI / 2.0; - path.push(Vector3::new( - angle.cos(), - 0.0, - angle.sin(), - )); -} - -// Rectangular profile -let profile = vec![ - Vector3::new(-0.2, 0.0, -0.1), - Vector3::new(0.2, 0.0, -0.1), - Vector3::new(0.2, 0.0, 0.1), - Vector3::new(-0.2, 0.0, 0.1), -]; - -let curved_beam = sweep_profile_along_path(&path, &profile, SweepOptions::default()); - -// Result: Curved rectangular beam following the arc -``` - -### Open Tube Without Caps - -```rust -use opengeometry::operations::sweep::{sweep_profile_along_path, SweepOptions}; -use openmaths::Vector3; - -let path = vec![ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(0.0, 1.0, 0.0), - Vector3::new(1.0, 2.0, 0.0), -]; - -let profile = create_circle_profile(0.4, 12); // 12-sided circle - -// Create open tube -let tube = sweep_profile_along_path( - &path, - &profile, - SweepOptions { - cap_start: false, - cap_end: false, - }, -); - -assert_eq!(tube.vertices.len(), 36); // 12 profile × 3 sections -assert_eq!(tube.faces.len(), 24); // Only side faces, no caps -``` - -### Closed Loop Sweep - -```rust -use opengeometry::operations::sweep::{sweep_profile_along_path, SweepOptions}; -use openmaths::Vector3; - -// Circular closed path -let mut path = Vec::new(); -for i in 0..16 { - let angle = (i as f64) * 2.0 * std::f64::consts::PI / 16.0; - path.push(Vector3::new( - 2.0 * angle.cos(), - 0.0, - 2.0 * angle.sin(), - )); -} -path.push(path[0]); // Close the loop - -// Small circular profile -let profile = create_circle_profile(0.2, 8); - -// Sweep to create a torus-like shape -let torus = sweep_profile_along_path(&path, &profile, SweepOptions::default()); - -// Note: End caps are NOT generated for closed paths -assert_eq!(torus.vertices.len(), 128); // 8 profile × 16 sections -assert_eq!(torus.faces.len(), 128); // Only side faces -``` - -## Visual Examples - -``` -Sweep Process: - - Path Profile Result - - ● ○ ╭─○─╮ - │ │ │ - ● → ●───● - │ │ │ - ● ╰─○─╯ - - -Closed Path Sweep (Torus): - - Path (circle) Profile (circle) Result - - ╭───╮ ● ╭─────╮ - │ │ ╱ ╭───╮ ╲ - ╰───╯ ● → │ │ │ │ - ╲ ╰───╯ ╱ - ╰─────╯ -``` - -## Frame Calculation Details - -### Rotation-Minimizing Frames - -The sweep operation uses a parallel transport method to compute frames that: - -- Follow the path tangent direction -- Minimize rotation (twist) along the path -- Handle sudden direction changes smoothly -- Work correctly for both open and closed paths - -### Frame Components - -- **Tangent**: Direction along the path -- **Normal**: First perpendicular direction (maps to profile U axis) -- **Binormal**: Second perpendicular direction (maps to profile V axis) - -## Implementation Details - -### Source Location - -`main/opengeometry/src/operations/sweep.rs` - -### Precision - -- Uses `EPSILON = 1.0e-9` for geometric comparisons -- Robust handling of near-zero vectors -- Graceful fallback for degenerate cases - -### Profile Orientation - -- Profile is automatically centered at its centroid -- Profile normal is computed using Newell's method -- Profile is decomposed into local orthonormal basis (u, v, w) -- No manual profile alignment required - -## Edge Cases - -- **Insufficient Points**: - - Path < 2 points: Returns empty BREP - - Profile < 3 points: Returns empty BREP -- **Closed Paths**: Automatically detected and handled (no end caps generated) -- **Degenerate Frames**: Fallback to default orthogonal vectors -- **Collinear Path Segments**: Frames smoothly interpolated - -## Performance Considerations - -- Vertex count: `profile_points × path_sections` -- Face count (open): `profile_points × (path_sections - 1) + 2 caps` -- Face count (closed): `profile_points × path_sections` -- Memory: O(vertices + faces) - -## See Also - -- [Extrude](/api/operations/extrude) - Special case of sweep along a straight vertical path -- [Offset](/api/operations/offset) - Create parallel offset curves in 2D - -## Live demo - -Try it in the browser: [Sweep path/profile demo](https://demo.opengeometry.io/operations/sweep-path-profile.html). diff --git a/docs/api/operations/triangulate.mdx b/docs/api/operations/triangulate.mdx deleted file mode 100644 index 4b70f7b4..00000000 --- a/docs/api/operations/triangulate.mdx +++ /dev/null @@ -1,281 +0,0 @@ ---- -title: 'Triangulate' -description: 'Convert polygons with holes into triangle meshes using ear-clipping algorithm' -icon: 'diagram-project' ---- - -## Overview - -The triangulate operation decomposes complex polygons (including those with holes) into a set of triangles. This is essential for rendering, collision detection, and finite element analysis. OpenGeometry uses the robust ear-clipping (earcut) algorithm with automatic projection to handle 3D polygons. - -## Function Signature - -```rust -pub fn triangulate_polygon_with_holes( - face_vertices: &Vec, - holes: &Vec>, -) -> Vec<[usize; 3]> -``` - -Triangulates a polygon with optional holes into a set of triangles. - - - The outer boundary vertices of the polygon in order (either clockwise or counter-clockwise). Must have at least 3 vertices to form a valid polygon. - - - - A vector of hole polygons, each defined by its own ordered vertex list. Holes must be entirely contained within the outer boundary. Pass an empty vector if there are no holes. - - -## Return Type - -Returns `Vec<[usize; 3]>` - a vector of triangle indices, where each `[usize; 3]` array contains three indices into the combined vertex list (outer boundary vertices followed by all hole vertices). - -### Index Mapping - -- Indices `0..face_vertices.len()` refer to outer boundary vertices -- Indices `face_vertices.len()..` refer to hole vertices in order - -Example: -- Outer boundary: 5 vertices (indices 0-4) -- Hole 1: 4 vertices (indices 5-8) -- Hole 2: 3 vertices (indices 9-11) - -## How It Works - -1. **Normal Calculation**: Computes the average normal of the polygon using Newell's method -2. **Projection Selection**: Chooses the best 2D projection plane based on the dominant axis: - - If |Z| is dominant: Project to XY plane - - If |X| is dominant: Project to YZ plane - - Otherwise: Project to XZ plane -3. **Vertex Flattening**: Converts all 3D vertices to 2D coordinates in the chosen plane -4. **Hole Index Tracking**: Records the starting index of each hole in the flattened array -5. **Earcut Algorithm**: Runs the robust ear-clipping triangulation -6. **Winding Order Correction**: Automatically reverses triangles if needed for consistent orientation - -## Code Examples - -### Simple Triangle - -```rust -use opengeometry::operations::triangulate::triangulate_polygon_with_holes; -use openmaths::Vector3; - -let triangle = vec![ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(1.0, 0.0, 0.0), - Vector3::new(0.5, 0.0, 1.0), -]; - -let triangles = triangulate_polygon_with_holes(&triangle, &vec![]); - -assert_eq!(triangles.len(), 1); -assert_eq!(triangles[0], [0, 1, 2]); -``` - -### Quadrilateral Triangulation - -```rust -use opengeometry::operations::triangulate::triangulate_polygon_with_holes; -use openmaths::Vector3; - -// Rectangle -let quad = vec![ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(2.0, 0.0, 0.0), - Vector3::new(2.0, 0.0, 2.0), - Vector3::new(0.0, 0.0, 2.0), -]; - -let triangles = triangulate_polygon_with_holes(&quad, &vec![]); - -// Quadrilateral splits into 2 triangles -assert_eq!(triangles.len(), 2); - -// Example output: -// [[0, 1, 2], [0, 2, 3]] -``` - -### Polygon with a Hole - -```rust -use opengeometry::operations::triangulate::triangulate_polygon_with_holes; -use openmaths::Vector3; - -// Outer square -let outer = vec![ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(4.0, 0.0, 0.0), - Vector3::new(4.0, 0.0, 4.0), - Vector3::new(0.0, 0.0, 4.0), -]; - -// Inner square hole -let hole = vec![ - Vector3::new(1.0, 0.0, 1.0), - Vector3::new(3.0, 0.0, 1.0), - Vector3::new(3.0, 0.0, 3.0), - Vector3::new(1.0, 0.0, 3.0), -]; - -let holes = vec![hole]; -let triangles = triangulate_polygon_with_holes(&outer, &holes); - -// Returns multiple triangles that avoid the hole -assert!(triangles.len() >= 8); // Minimum for a square with square hole - -// Indices 0-3 are outer vertices, 4-7 are hole vertices -``` - -### Complex Polygon with Multiple Holes - -```rust -use opengeometry::operations::triangulate::triangulate_polygon_with_holes; -use openmaths::Vector3; - -fn create_hexagon(center: Vector3, radius: f64) -> Vec { - let mut vertices = Vec::new(); - for i in 0..6 { - let angle = (i as f64) * std::f64::consts::PI / 3.0; - vertices.push(Vector3::new( - center.x + radius * angle.cos(), - center.y, - center.z + radius * angle.sin(), - )); - } - vertices -} - -let outer = create_hexagon(Vector3::new(0.0, 0.0, 0.0), 5.0); -let hole1 = create_hexagon(Vector3::new(-1.5, 0.0, 0.0), 0.8); -let hole2 = create_hexagon(Vector3::new(1.5, 0.0, 0.0), 0.8); - -let triangles = triangulate_polygon_with_holes(&outer, &vec![hole1, hole2]); - -// Complex triangulation avoiding both holes -println!("Generated {} triangles", triangles.len()); -``` - -### 3D Non-Planar Polygon (Auto-Projected) - -```rust -use opengeometry::operations::triangulate::triangulate_polygon_with_holes; -use openmaths::Vector3; - -// Polygon on a tilted plane -let tilted_polygon = vec![ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(1.0, 0.2, 0.0), - Vector3::new(1.0, 0.3, 1.0), - Vector3::new(0.0, 0.1, 1.0), -]; - -let triangles = triangulate_polygon_with_holes(&tilted_polygon, &vec![]); - -// Automatically projects to best 2D plane and triangulates -assert_eq!(triangles.len(), 2); -``` - -## Visual Examples - -``` -Simple Polygon: Polygon with Hole: - - v3────v2 v3────v2 - │╲ │ │ ╲ │ - │ ╲ │ → │ h3─h2 - │ ╲ │ │ │╲ ││ - v0────v1 │ h0─h1 - │╱ │ - Triangles: v0────v1 - [0,1,2], [0,2,3] - Triangles avoid hole - - -Multiple Holes: - - Outer Result - ┌──────────┐ ┌──────────┐ - │ h1 h2 │ │╱╲╱╲╱╲╱╲╱│ - │ ○ ○ │ → │╲╱╲╱╲╱╲╱╲│ - │ │ │╱╲╱╲╱╲╱╲╱│ - └──────────┘ └──────────┘ -``` - -## Winding Order - -The function automatically corrects winding order: - -- Analyzes the first triangle's orientation -- Reverses all triangles if winding is inconsistent -- Ensures consistent face normals for rendering - -## Implementation Details - -### Source Location - -`main/opengeometry/src/operations/triangulate.rs` - -### Algorithm - -Uses the **earcutr** library, which implements: -- Fast ear-clipping triangulation -- Robust handling of self-touching vertices -- Support for complex polygons with holes - -### Projection Axis Selection - -```rust -if normal.z.abs() > normal.x.abs() && normal.z.abs() > normal.y.abs() { - // Project to XY plane (indices 0, 1) -} else if normal.x.abs() > normal.y.abs() { - // Project to YZ plane (indices 1, 2) -} else { - // Project to XZ plane (indices 0, 2) -} -``` - -### Normal Calculation (Newell's Method) - -```rust -for i in 0..vertices.len() { - let p1 = &vertices[i]; - let p2 = &vertices[(i + 1) % vertices.len()]; - normal.x += (p1.y - p2.y) * (p1.z + p2.z); - normal.y += (p1.z - p2.z) * (p1.x + p2.x); - normal.z += (p1.x - p2.x) * (p1.y + p2.y); -} -``` - -## Edge Cases - -- **Insufficient Vertices**: Returns empty vector if outer boundary has < 3 vertices -- **Degenerate Polygons**: May produce no triangles or unexpected results -- **Self-Intersecting**: Earcut algorithm handles some cases but behavior is undefined -- **Holes Outside Boundary**: Results are undefined; ensure holes are contained -- **Non-Planar Polygons**: Automatically projected, but significant non-planarity may cause artifacts - -## Performance Considerations - -- Time Complexity: O(n log n) average case for earcut algorithm -- Memory: O(n) for vertex storage and triangle output -- Efficient for polygons with hundreds of vertices -- Minimal overhead from projection - -## Common Use Cases - -- **Rendering**: Convert arbitrary polygons to GPU-compatible triangle meshes -- **Physics**: Generate collision meshes from polygon boundaries -- **CAD/CAM**: Prepare geometry for manufacturing or simulation -- **GIS**: Triangulate geographic regions with exclusion zones -- **Architecture**: Process floor plans with room boundaries and obstacles - -## See Also - -- [Extrude](/api/operations/extrude) - Often used after triangulation to create 3D geometry -- [Sweep](/api/operations/sweep) - Creates surfaces that may need triangulation - -## Live demo - -There is no dedicated triangulate demo page yet. Start from the demo index: -[OpenGeometry demos](https://demo.opengeometry.io/). diff --git a/docs/api/primitives/arc.mdx b/docs/api/primitives/arc.mdx deleted file mode 100644 index 19343f5c..00000000 --- a/docs/api/primitives/arc.mdx +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Arc -description: An authoritative circular edge rendered to a requested chord error -icon: 'circle-notch' ---- - -## Overview - -`Arc` stores one analytic circle edge and its parameter span in strict BRep schema v2. Rendering samples that edge to `deflection`; changing the deflection never changes the model topology. - - - Initialize `OpenGeometry.create(...)` before constructing `Vector3` or an `Arc`. - - -## Constructor - -```ts -const arc = new Arc(options?: IArcOptions); -``` - - - Stable entity identifier. Generated when omitted. - - - - Circle center. Defaults to the origin. - - - - Positive circle radius. - - - - Edge start parameter in radians. - - - - Signed sweep in radians. Its magnitude must be nonzero and at most one full turn. - - - - Maximum requested chord error for the transient render line. - - - - Three.js line color. - - -## Methods - -`retessellate(deflection)` updates only the render sampling and returns the achieved error and segment count. `getBrepSerialized()` returns the strict v2 wire, while `getBrep()` returns the parsed object. Use `edgeIdForSegment(index)` to map a picked render segment back to the authoritative edge. Call `dispose()` when removing the object. - -```ts -import { Arc, OpenGeometry, Vector3 } from "opengeometry"; - -await OpenGeometry.create({ wasmURL }); -const arc = new Arc({ - center: new Vector3(0, 0, 0), - radius: 2.2, - startAngle: 0, - sweepAngle: Math.PI * 1.5, - deflection: 0.01, - color: 0x2563eb, -}); -scene.add(arc); - -arc.retessellate(0.002); -``` - -A full circle uses one model vertex and one closed edge. The default right-handed frame lies in the XZ plane with Y as its normal. - -## Live demo - -- [Arc demo](https://demo.opengeometry.io/primitives/arc.html) diff --git a/docs/api/primitives/curve.mdx b/docs/api/primitives/curve.mdx deleted file mode 100644 index bb3b5222..00000000 --- a/docs/api/primitives/curve.mdx +++ /dev/null @@ -1,185 +0,0 @@ ---- -title: Curve -description: A control-point-driven curve primitive -icon: 'bezier-curve' ---- - -## Overview - -`Curve` is a line-based wrapper driven by a `controlPoints` array. It supports kernel-backed -placement, anchor management, freeform conversion, and offset generation for parallel guide paths. - - - Initialize `OpenGeometry.create(...)` before constructing `Vector3` or running the examples on - this page. - - -## Constructor - - - - ```rust - let curve = OGCurve::new("curve-1".to_string()); - ``` - - - ```ts - const curve = new Curve(options?: ICurveOptions); - ``` - - - -### ICurveOptions - - - Unique identifier for the curve. Auto-generated when omitted. - - - - Ordered control points used to build the curve geometry. - - - - Curve color as a hex number. - - - - Initial placement translation. - - - - Initial placement rotation in radians. - - - - Initial placement scale. - - -## Methods - -### setConfig() - -Updates the control point array or render color. - -```ts -curve.setConfig(options: CurveConfigUpdate): void -``` - -### getConfig(), getPlacement() - -Returns the current curve config or cloned placement values. - -```ts -const config = curve.getConfig(); -const placement = curve.getPlacement(); -``` - -### getAnchor(), setAnchor(), resetAnchor() - -Reads or updates the modeling anchor used by the kernel-backed primitive. - -```ts -const anchor = curve.getAnchor(); -curve.setAnchor(anchor); -curve.resetAnchor(); -``` - -### setPlacement(), setTransform(), setTranslation(), setRotation(), setScale() - -Placement helpers for moving the curve through the kernel transform path. - -```ts -curve.setPlacement({ translation?, rotation?, scale? }); -``` - -### getOffset() - -Returns an offset result for the current curve. - -```ts -const offset = curve.getOffset( - distance, - acuteThresholdDegrees = 35, - bevel = true -); -``` - -### toFreeform() - -Converts the curve into a freeform geometry wrapper. - -```ts -const freeform = curve.toFreeform(id?); -``` - -## Properties - - - Stable identifier for the curve wrapper. - - - - Current curve configuration and placement state. - - - - Gets or sets the curve color. - - -## Examples - -### Create a guide curve - -```ts -import { Curve, Vector3 } from "opengeometry"; - -const curve = new Curve({ - controlPoints: [ - new Vector3(-2.5, 0, -1.5), - new Vector3(-0.9, 0, 0.8), - new Vector3(0.8, 0, 0.55), - new Vector3(2.4, 0, 1.4), - ], - color: 0x16a34a, -}); -``` - -### Offset a curve into a second guide - -```ts -const centerline = new Curve({ - controlPoints: [ - new Vector3(-3, 0, -1.1), - new Vector3(-1.2, 0, 0.7), - new Vector3(0.8, 0, 0.2), - new Vector3(2.9, 0, 1.4), - ], - color: 0x0f172a, -}); - -const offset = centerline.getOffset(0.35); - -const outerGuide = new Curve({ - controlPoints: offset.points, - color: 0x2563eb, -}); -``` - -### Update the control points - -```ts -curve.setConfig({ - controlPoints: [ - new Vector3(-2.5, 0, -1.4), - new Vector3(-1.1, 0, 1.2), - new Vector3(1.2, 0, 0.7), - new Vector3(2.8, 0, 1.9), - ], -}); - -curve.setTranslation(new Vector3(0, 0.15, 0)); -``` - -## Live demo - -- [Curve demo](https://demo.opengeometry.io/primitives/curve.html) diff --git a/docs/api/primitives/elliptical-arc.mdx b/docs/api/primitives/elliptical-arc.mdx deleted file mode 100644 index 31f19c01..00000000 --- a/docs/api/primitives/elliptical-arc.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Elliptical Arc -description: An authoritative elliptical edge rendered to a requested chord error -icon: 'circle-ellipsis' ---- - -## Overview - -`EllipticalArc` stores an analytic ellipse edge and its parameter span in strict BRep schema v2. It accepts `majorRadius`, `minorRadius`, `startAngle`, signed `sweepAngle`, and render `deflection`; it has no modeling segment count. - -```ts -import { EllipticalArc, OpenGeometry, Vector3 } from "opengeometry"; - -await OpenGeometry.create({ wasmURL }); -const ellipse = new EllipticalArc({ - center: new Vector3(0, 0, 0), - majorRadius: 3, - minorRadius: 1.25, - startAngle: 0, - sweepAngle: -Math.PI, - deflection: 0.01, - color: 0x7c3aed, -}); -scene.add(ellipse); - -ellipse.retessellate(0.002); -``` - -The radii require `majorRadius >= minorRadius > 0`. `getBrepSerialized()`, `getBrep()`, `edgeIdForSegment(index)`, and `dispose()` follow the `Arc` contract. - -## Live demo - -- [Elliptical arc demo](https://demo.opengeometry.io/primitives/elliptical_arc.html) diff --git a/docs/api/primitives/line.mdx b/docs/api/primitives/line.mdx deleted file mode 100644 index 58f74df3..00000000 --- a/docs/api/primitives/line.mdx +++ /dev/null @@ -1,207 +0,0 @@ ---- -title: Line -description: A line primitive defined by start and end points -icon: 'minus' ---- - -## Overview - -`Line` is the simplest line-based wrapper in the Three.js API. It creates a straight segment between -two points, supports optional wide-line rendering, exposes placement helpers, and can generate -offset geometry for parallel construction workflows. - - - Initialize `OpenGeometry.create(...)` before constructing `Vector3` or running the examples on - this page. - - -## Constructor - - - - ```rust - let line = OGLine::new("line-1".to_string()); - ``` - - - ```ts - const line = new Line(options?: ILineOptions); - ``` - - - -### ILineOptions - - - Unique identifier for the line. Auto-generated when omitted. - - - - Start point of the segment. - - - - End point of the segment. - - - - Line color as a hex number. - - - - Enables wide-line rendering with `Line2`. - - - - Wide-line width used when `fatLines` is enabled. - - - - Initial placement translation. - - - - Initial placement rotation in radians. - - - - Initial placement scale. - - -## Methods - -### setConfig() - -Updates geometry or render style and regenerates the segment when needed. - -```ts -line.setConfig(options: LineConfigUpdate): void -``` - -### getConfig() - -Returns the current line options. - -```ts -const config = line.getConfig(); -``` - -### getPlacement() - -Returns the current placement values as cloned vectors. - -```ts -const placement = line.getPlacement(); -``` - -### setPlacement() - -Updates translation, rotation, or scale through the kernel-backed placement path. - -```ts -line.setPlacement({ translation?, rotation?, scale? }): void -``` - -### setTransform(), setTranslation(), setRotation(), setScale() - -Convenience placement helpers. - -```ts -line.setTransform(translation, rotation, scale); -line.setTranslation(translation); -line.setRotation(rotation); -line.setScale(scale); -``` - -### getOffset() - -Returns a parallel offset result for the current segment. - -```ts -const offset = line.getOffset( - distance, - acuteThresholdDegrees = 35, - bevel = true -); -``` - -### toFreeform() - -Converts the line into a freeform geometry wrapper for direct editing. - -```ts -const freeform = line.toFreeform(id?); -``` - -### discardGeometry() - -Disposes the current Three.js geometry buffer. Use this only when you are handling lifecycle -manually. - -```ts -line.discardGeometry(): void -``` - -## Properties - - - Stable identifier for the line wrapper. - - - - Current line configuration and placement state. - - - - Gets or sets the rendered line color. - - -## Examples - -### Create a line - -```ts -import { Line, Vector3 } from "opengeometry"; - -const line = new Line({ - start: new Vector3(-2, 0, -0.8), - end: new Vector3(2, 0, 0.8), - color: 0x111827, - fatLines: true, - width: 10, -}); - -line.setTranslation(new Vector3(0, 0.2, 0)); -``` - -### Create a parallel guide - -```ts -const baseLine = new Line({ - start: new Vector3(-2, 0, 0), - end: new Vector3(2, 0, 0), - color: 0x111827, -}); - -const offset = baseLine.getOffset(0.4); - -const guideLine = new Line({ - start: offset.points[0], - end: offset.points[1], - color: 0x2563eb, -}); -``` - -### Update endpoints after creation - -```ts -line.setConfig({ - start: new Vector3(-3, 0, -0.6), - end: new Vector3(3, 0, 1.1), - color: 0xf97316, -}); -``` - -## Live demo - -- [Line demo](https://demo.opengeometry.io/primitives/line.html) diff --git a/docs/api/primitives/polyline.mdx b/docs/api/primitives/polyline.mdx deleted file mode 100644 index d19c8a75..00000000 --- a/docs/api/primitives/polyline.mdx +++ /dev/null @@ -1,197 +0,0 @@ ---- -title: Polyline -description: A connected sequence of line segments defined by an ordered points array -icon: 'wave-square' ---- - -## Overview - -`Polyline` creates an ordered chain of straight segments. It supports optional wide-line rendering, -incremental point editing with `addPoint(...)`, placement helpers, freeform conversion, and offset -generation. The wrapper also exposes whether the current path is closed through `isClosed`. - - - Initialize `OpenGeometry.create(...)` before constructing `Vector3` or running the examples on - this page. - - -## Constructor - - - - ```rust - let polyline = OGPolyline::new("poly-1".to_string()); - ``` - - - ```ts - const polyline = new Polyline(options?: IPolylineOptions); - ``` - - - -### IPolylineOptions - - - Unique identifier for the polyline. Auto-generated when omitted. - - - - Ordered points that define the path. - - - - Polyline color as a hex number. - - - - Enables wide-line rendering with `Line2`. - - - - Wide-line width used when `fatLines` is enabled. - - - - Initial placement translation. - - - - Initial placement rotation in radians. - - - - Initial placement scale. - - -## Methods - -### setConfig() - -Updates the points array or render style. - -```ts -polyline.setConfig(options: PolylineConfigUpdate): void -``` - -### addPoint() - -Appends a point to the current path and regenerates geometry when possible. - -```ts -polyline.addPoint(point: Vector3): void -``` - -### getConfig(), getPlacement() - -Returns the current polyline config or cloned placement values. - -```ts -const config = polyline.getConfig(); -const placement = polyline.getPlacement(); -``` - -### setPlacement(), setTransform(), setTranslation(), setRotation(), setScale() - -Placement helpers for moving the polyline through the kernel transform path. - -```ts -polyline.setPlacement({ translation?, rotation?, scale? }); -``` - -### getOffset() - -Returns an offset result for the current path. - -```ts -const offset = polyline.getOffset( - distance, - acuteThresholdDegrees = 35, - bevel = true -); -``` - -### toFreeform() - -Converts the polyline into a freeform geometry wrapper. - -```ts -const freeform = polyline.toFreeform(id?); -``` - -### discardGeometry() - -Disposes the current Three.js geometry buffer. - -```ts -polyline.discardGeometry(): void -``` - -## Properties - - - Stable identifier for the polyline wrapper. - - - - Current polyline configuration and placement state. - - - - Indicates whether the current point array forms a closed loop. - - - - Gets or sets the rendered polyline color. - - -## Examples - -### Create a polyline - -```ts -import { Polyline, Vector3 } from "opengeometry"; - -const polyline = new Polyline({ - points: [ - new Vector3(-2.5, 0, -1.7), - new Vector3(-1.2, 0, -0.9), - new Vector3(0.3, 0, 0.1), - new Vector3(1.1, 0, 0.9), - new Vector3(2.4, 0, 1.7), - ], - color: 0x0f172a, - fatLines: true, - width: 10, -}); -``` - -### Append points incrementally - -```ts -const path = new Polyline({ - points: [ - new Vector3(-2, 0, -1), - new Vector3(-0.5, 0, -0.3), - ], - color: 0x111827, -}); - -path.addPoint(new Vector3(0.6, 0, 0.5)); -path.addPoint(new Vector3(2.1, 0, 1.2)); -``` - -### Offset a centerline - -```ts -const offset = polyline.getOffset(0.3); - -const wallGuide = new Polyline({ - points: offset.points, - color: 0x2563eb, -}); -``` - -## Live demo - -- [Polyline demo](https://demo.opengeometry.io/primitives/polyline.html) diff --git a/docs/api/primitives/rectangle.mdx b/docs/api/primitives/rectangle.mdx deleted file mode 100644 index ef2169a1..00000000 --- a/docs/api/primitives/rectangle.mdx +++ /dev/null @@ -1,209 +0,0 @@ ---- -title: Rectangle -description: A rectangular profile defined by center, width, and breadth -icon: 'vector-square' ---- - -## Overview - -`Rectangle` is a closed line-based profile wrapper on the XZ plane. It supports wide-line -rendering, offset generation, anchor management, placement helpers, freeform conversion, and a -parsed BRep accessor. - - - Initialize `OpenGeometry.create(...)` before constructing `Vector3` or running the examples on - this page. - - -## Constructor - - - - ```rust - let rectangle = OGRectangle::new("rect-1".to_string()); - ``` - - - ```ts - const rectangle = new Rectangle(options?: IRectangleOptions); - ``` - - - -### IRectangleOptions - - - Unique identifier for the rectangle. Auto-generated when omitted. - - - - Center point of the rectangle. - - - - Rectangle width along the X axis. - - - - Rectangle breadth along the Z axis. - - - - Rectangle color as a hex number. - - - - Enables wide-line rendering with `Line2`. - - - - Wide-line width used when `fatLines` is enabled. - - - - Initial placement translation. - - - - Initial placement rotation in radians. - - - - Initial placement scale. - - -## Methods - -### setConfig() - -Updates geometry or render style. - -```ts -rectangle.setConfig(options: RectangleConfigUpdate): void -``` - -### getConfig(), getPlacement() - -Returns the current rectangle config or cloned placement values. - -```ts -const config = rectangle.getConfig(); -const placement = rectangle.getPlacement(); -``` - -### getAnchor(), setAnchor(), resetAnchor() - -Reads or updates the modeling anchor used by the kernel-backed primitive. - -```ts -const anchor = rectangle.getAnchor(); -rectangle.setAnchor(anchor); -rectangle.resetAnchor(); -``` - -### setPlacement(), setTransform(), setTranslation(), setRotation(), setScale() - -Placement helpers for moving the rectangle through the kernel transform path. - -```ts -rectangle.setPlacement({ translation?, rotation?, scale? }); -``` - -### getOffset() - -Returns an offset result for the current rectangle profile. - -```ts -const offset = rectangle.getOffset( - distance, - acuteThresholdDegrees = 35, - bevel = true -); -``` - -### toFreeform() - -Converts the rectangle into a freeform geometry wrapper. - -```ts -const freeform = rectangle.toFreeform(id?); -``` - -### getBrep() - -Returns the parsed BRep object for the current rectangle. - -```ts -const brep = rectangle.getBrep(); -``` - -### discardGeometry() - -Disposes the current Three.js geometry buffer. - -```ts -rectangle.discardGeometry(): void -``` - -## Properties - - - Stable identifier for the rectangle wrapper. - - - - Current rectangle configuration and placement state. - - - - Gets or sets the rectangle color. - - -## Examples - -### Create a rectangle profile - -```ts -import { Polyline, Rectangle, Vector3 } from "opengeometry"; - -const rectangle = new Rectangle({ - center: new Vector3(0, 0, 0), - width: 2.4, - breadth: 1.6, - color: 0x2563eb, - fatLines: true, - lineWidth: 8, -}); -``` - -### Create an inset or outset profile - -```ts -const room = new Rectangle({ - center: new Vector3(0, 0, 0), - width: 6, - breadth: 4, - color: 0x0f172a, -}); - -const inset = room.getOffset(-0.2); - -const finishLine = new Polyline({ - points: inset.points, - color: 0x2563eb, -}); -``` - -### Move and rotate the profile - -```ts -rectangle.setPlacement({ - translation: new Vector3(0, 0, 1.2), - rotation: new Vector3(0, Math.PI / 6, 0), - scale: new Vector3(1, 1, 1), -}); -``` - -## Live demo - -- [Rectangle demo](https://demo.opengeometry.io/primitives/rectangle.html) diff --git a/docs/api/scene/scene-management.mdx b/docs/api/scene/scene-management.mdx deleted file mode 100644 index 4b7ee855..00000000 --- a/docs/api/scene/scene-management.mdx +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: WorldGraph -description: Place geometry in a kernel-owned scene graph, then query, project, and export it ---- - -## Overview - -`WorldGraph` is the kernel's single scene. It stores: - -- **definitions** — a body's geometry, stored once and shared by every node that uses it -- **nodes** — a parent, a transform relative to that parent, an optional definition, and an - optional `kind` label - -World transforms are derived from the parent chain, so moving a node moves everything beneath it. -Queries (clash, clearance, distance), 2D projection, and export all read those world transforms. - - -`WorldGraph` replaces `OGSceneManager` and `OGEntityRegistry`, which were removed in 2.0.16. See -[Migrating from OGSceneManager](#migrating-from-ogscenemanager). - - -```ts -import { Cuboid, OpenGeometry, Vector3, WorldGraph } from "opengeometry"; -import * as THREE from "three"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); - -const graph = new WorldGraph(); -const shelf = new Cuboid({ center: new Vector3(0, 0.5, 0), width: 1.2, height: 1, depth: 0.4 }); - -graph.define("shelf", shelf); -graph.addNode({ id: "room" }); -graph.addNode({ id: "shelf-1", parent: "room", definition: "shelf", kind: "furniture" }); -graph.addNode({ - id: "shelf-2", - parent: "room", - definition: "shelf", - local: new THREE.Matrix4().makeTranslation(2, 0, 0), -}); - -graph.setLocal("room", new THREE.Matrix4().makeRotationY(Math.PI / 2)); -``` - -## Transforms - -Local transforms are `THREE.Matrix4` values that must be rigid with a positive **uniform** scale. -Shear, reflection, and non-uniform scale throw — analytic geometry stays exact only under -similarity transforms. Resize a body by changing its parameters, not its scale. - -## Definitions - -| Method | Purpose | -|---|---| -| `define(id, solid)` | Store an `AnalyticSolid`'s local BRep. | -| `defineLegacy(id, brepSerialized)` | Store a schema-v1 BRep (`Polygon`, `Sweep`, `Wedge`, …). | -| `hasDefinition(id)` / `undefine(id)` | `undefine` fails while a node still uses the definition. | - -Legacy definitions take part in projection and in the legacy STL/STEP/IFC exporters. Clash and -clearance need analytic geometry: `clash` marks pairs that involve a legacy body `unresolved`, and -`clearance` throws a `WorldGraphError` with code `geometry` whose detail is `UnsupportedGeometry`. - -## Nodes - -| Method | Purpose | -|---|---| -| `addNode({ id, parent?, definition?, local?, kind? })` | Add a node. | -| `setLocal(id, matrix)` | Move a node relative to its parent. | -| `reparent(id, parent?)` | Rejects cycles. | -| `removeNode(id)` | Removes the node and its subtree. | -| `getWorldMatrix(id)` / `getWorldBounds(id)` | Derived world transform and subtree bounds. | -| `bind(object, id)` | Drive a Three.js object's matrix from the graph (one direction). | - -`kind` is inherited by descendants. Projection uses it for AIA layer codes (`wall` → `A-WALL`, -`door` → `A-DOOR`, …) and IFC export uses it as the entity kind. - -## Queries - -| Method | Returns | -|---|---| -| `clash(itemsA, itemsB, { depth })` | `hard`, `touch`, or `unresolved` per item pair. | -| `clearance(itemsA, itemsB, clearance)` | Item pairs closer than `clearance`, with `distance`, `errorBound`, and closest `points`. | -| `distance(itemA, itemB, tolerance)` | Minimum distance between two items. | - -Parts inside the same item are never tested against each other. - -## Projection - -```ts -const camera = { - position: { x: 8, y: 6, z: 8 }, - target: { x: 0, y: 0, z: 0 }, - up: { x: 0, y: 1, z: 0 }, - near: 0.1, - projection_mode: "Orthographic" as const, -}; - -const { lines } = graph.projectLines(["room"], camera, { hide_hidden_edges: true }, 0.01); -const views = graph.projectViews(["room"], [{ id: "iso", camera }], 0.01); -``` - -`projectLines` returns a flat `Scene2DLines` payload. `projectViews` returns one `Scene2D` per -view, with each segment's `layer` and `source_entity_id` (the node id) filled in. The last -argument is the tessellation deflection used for curved analytic surfaces. See -[Projection](/api/export/projection). - -## Export - -`exportStl(items)`, `exportStep(items)`, and `exportIfc(items)` write the world-placed schema-v1 -bodies under `items`. Analytic definitions are refused — export those through the analytic -exporters on `AnalyticSolid`. Single-BRep helpers `exportBrepToStl`, `exportBrepToStep`, and -`exportBrepToIfc` are plain functions exported from `opengeometry`. - -## Migrating from OGSceneManager - -| Before | After | -|---|---| -| `new OGSceneManager()` + `createScene(...)` | `new WorldGraph()` | -| `addBrepEntityToScene(scene, id, kind, brep)` | `defineLegacy(id, brep)` + `addNode({ id, definition: id, kind })` | -| `add{Line,Polygon,Cuboid,…}ToScene(...)` | `defineLegacy(id, shape.getBrepSerialized())` or `define(id, analyticSolid)` | -| `projectTo2DLines` / `projectCurrentTo2DLines` | `projectLines(items, camera, hlr, deflection)` | -| `projectTo2DCamera` | `projectViews(items, [{ id, camera, hlr }], deflection)` | -| `OGEntityRegistry.projectCurrentToViews` | `projectViews(...)` with `kind` set on nodes | -| `exportSceneToStl` / `Step` / `Ifc` | `exportStl` / `exportStep` / `exportIfc(items)` | -| `manager.exportBrepToStl(brep)` | `exportBrepToStl(brep)` | -| `projectToPDF` (native) | `WorldGraph::project_to_pdf` (Rust, native) | - -Behavioural differences: - -- The graph is **live**: moving a node changes every later query and projection. There are no - frozen scene snapshots, scene lists, or "current scene". -- Positions come from node transforms. Pass local BReps plus a transform instead of pre-baked - world BReps (pre-baked BReps still work with an identity node). -- Section planes on view requests were never implemented and are no longer accepted. - -## Related - -- [Scene graph concepts](/concepts/scene-graph) -- [Projection](/api/export/projection) -- [PDF export](/api/export/pdf) diff --git a/docs/api/shapes/analytic-solid.mdx b/docs/api/shapes/analytic-solid.mdx deleted file mode 100644 index ecc60d3d..00000000 --- a/docs/api/shapes/analytic-solid.mdx +++ /dev/null @@ -1,206 +0,0 @@ ---- -title: "Analytic solid" -description: "Render authoritative analytic primitives with chord-error tessellation." ---- - -`AnalyticSolid` constructs line-profile extrusions, cuboids, cylinders, spheres, cones, frusta, ring tori, annular sector extrusions, coaxial circle lofts, and rectangular revolutions from analytic surfaces. Its required surface and curve geometry uses BRep schema version 2. Render triangles are generated from that geometry. - -The public boolean helpers accept only `AnalyticSolid` operands and use the in-house analytic engine. -Schema-v1 and faceted operands are rejected; there is no mesh fallback. - -The current validator checks structural links and sampled curve/surface residuals. Full solid validity, arbitrary trim arrangements, and numerical intersection branch completeness are not yet certified. Current curved tessellation supports rectangular UV trims with axis-aligned hole loops; unsupported trims return an error. - -```ts -import { OpenGeometry, AnalyticSolid } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); - -const solid = new AnalyticSolid({ - kind: "cylinder", - radius: 1, - height: 2, - deflection: 0.01, - color: 0x6699dd, -}); -scene.add(solid); - -const stats = solid.retessellate(0.002); -const serialized = solid.getBrepSerialized(); -``` - -## Construction - -Use `kind: "cuboid"` with `width`, `depth`, and `height`; `"cylinder"` or `"cone"` with `radius` and `height`; `"sphere"` with `radius`; `"frustum"` with `lowerRadius`, `upperRadius`, and `height`; or `"torus"` with `majorRadius` and `minorRadius`. Restricted modeling verbs use `"coaxialCircleLoft"` with two radii and a height, `"revolvedRectangle"` with inner/outer radii and a height, `"chamferedCuboid"` for an exact planar chamfer on the four vertical corners, and `"filletedCylinder"` for two supported circular-edge fillets. The fillet uses two trimmed ring-torus faces and requires `filletRadius < min(radius / 2, height / 2)`. These forms deliberately reject profiles that would require a surface family outside the v2 contract. - -Use `kind: "linearExtrusion"` with an `outer` array of 2D points, a required `holes` array, and positive `height`. Coordinates are evaluated in the frame's XY plane and extrusion follows its Z axis. The constructor emits shared Line edges, Plane faces, cap hole loops, and pcurves directly in v2. It rejects self-intersections, touching boundaries, nested or overlapping holes, and features below the geometric tolerance. - -```ts -const profile = new AnalyticSolid({ - kind: "linearExtrusion", - outer: [[-2, -1], [2, -1], [2, 1], [-2, 1]], - holes: [[[-0.5, -0.4], [-0.5, 0.4], [0.5, 0.4], [0.5, -0.4]]], - height: 2, -}); -``` - -Dimensions must be finite and positive. A frustum may have a zero upper radius. Ring tori require `majorRadius > minorRadius > 0`. - -Use `kind: "annularSectorExtrusion"` with reference `radius`, `thickness`, `height`, `startAngle`, and signed `sweepAngle` in radians. The frame origin is the arc center at the extrusion base. Radius must exceed half thickness; sweep must be nonzero and smaller than a full turn. Negative sweep retains the authored start/end identity. - -`kind: "annularSectorExtrusionWithOpenings"` adds a required `openings` array. Each opening supplies `id`, center `angle`, tangent `width`, `bottom`, and `height`. Interior openings retain exact inner/outer cylinder trim holes plus planar lower, upper, and lateral cut faces with source ancestry. Set `bottom: 0` for a bottom-reaching opening: the cylinder trims follow the bottom notch, the remaining bottom regions are split exactly, and the cut contains an upper face and two lateral faces without an inset. Openings must remain strictly inside the authored sweep ends and leave resolved material above the head. - -```ts -const sector = new AnalyticSolid({ - kind: "annularSectorExtrusionWithOpenings", - radius: 3, - thickness: 0.3, - height: 3, - startAngle: 0, - sweepAngle: Math.PI / 2, - openings: [{ id: "aperture-1", angle: 0.8, width: 0.9, bottom: 0.9, height: 1.2 }], -}); -``` - -Use `kind: "annularSectorExtrusionWithArchedOpening"` for one arched opening on an annular sector extrusion. -Its `opening` has the same fields. `height` is the total opening height and must exceed -`width / 2`. The lower cut region uses exact annular-sector trimming; the arch cap is a cylindrical -face bounded by corrected intersection curves on the inner and outer cylindrical supports. - -Use `kind: "boxWithArchedOpening"` with box `width`, `depth`, and `height`, plus -`opening: { id, station, width, bottom, height }`. It constructs the opening directly with two -shared semicircle edges and a cylindrical arch-cap face. The opening must remain strictly inside the -box ends and top. These arched forms avoid overlapping cutter booleans and remain authoritative -when retessellated. - -`solid.shell(thickness, options?)` offsets inward and returns a closed analytic shell for canonical cuboids, cylinders, spheres, cones, frusta, ring tori, and straight-edge line-profile extrusions. It builds an oriented cavity shell, retains the source face mapping, and includes the solid's complete world placement. Cone offsets move the cavity apex by the true normal offset; frustum offsets trim both caps and retain the authored semi-angle. Profile offsets intersect neighboring offset planes at exact miter vertices and expand authored holes. Thickness must leave a resolved positive interior in every offset dimension; collapsing, reversing, or self-intersecting offsets return `UnresolvedIntersection`. Already-composite solids return `CoverageGap`. - -```ts -const source = new AnalyticSolid({ kind: "cuboid", width: 2, depth: 2, height: 2 }); -const shelled = source.shell(0.2, { deflection: 0.01 }); -scene.add(shelled); -``` - -The default frame uses Y as the height axis. Supply `frame: { origin, x, y, z }` to choose a different right-handed orthonormal frame; each value is a three-number array. `z` is the primitive's axis. - -## Tessellation - -`retessellate(deflection)` updates the child `surface` mesh, retaining its analytic model and face IDs. Deflection is a chord-error bound in model units, not a segment count. The default is `0.001`. - -The kernel caches meshes and samples shared edges consistently. Normals come from the analytic surfaces. The wrapper packs positions around a local origin and includes Float32 encoding error in `achievedDeflection`. - -Each WASM runtime shares a 64 MiB mesh cache with at most three entries per body. Tessellation objects and GPU arrays held by callers are additional transient allocations. - -Resource or precision limits throw an error and preserve the previous render geometry. Very small deflections below the model tolerance are rejected. - -## Picking and placement - -Raycast against `solid.surface`, then call `solid.faceIdForTriangle(hit.faceIndex)`. The returned ID identifies an analytic face and remains independent of mesh density. - -`solid.normalAtFace(faceId, modelPoint)` projects onto the retained support and evaluates its oriented normal. Convert a raycast's world point with `solid.worldToLocal(hit.point.clone())` first. The returned vector is in model space; this query does not classify trim membership. Surface singularities without a unique normal return an error. - -`AnalyticSolid` is a Three.js group. Apply render placement to that group; `getBrepSerialized()` returns the model before the group's Three.js transform. The child mesh's position stores its GPU packing origin. - -`getModelBounds()` returns a conservative bounding box from analytic faces and curves before the group's transform. It includes curved extents absent from the topological vertex set. - -Call `solid.dispose()` when you remove it permanently. - -## STEP export and diagnostics - -`solid.exportStep("metre")` returns `{ text, report }` directly from v2 surfaces, shared curves and oriented edge uses. It supports all five target surface families, frusta, annular sector extrusions and the current sphere and aligned-cuboid boolean results, including cavities. It does not require a viewport mesh or facet regrouping. - -Authored coordinates are interpreted as metres. Pass `"millimetre"` to convert coordinates and dimensions once and emit the corresponding unit context. Export applies the complete Three.js world placement once, including positive uniform scale. `getWorldBrepSerialized()` returns the corresponding world model; `getBrepSerialized()` retains local geometry. Retessellation does not alter export text. - -The report states the validation level: v2 structure, sampled residuals and Part-21 reference integrity. Complete external schema and importer validation remains pending. Numerical intersection edges are fitted as export-only non-rational cubic B-splines when their conservative curve enclosure fits within the remaining exchange budget. The fitted error is included in `exchange_error_bound`; projected pcurves without a certified representation still return `UnsupportedGeometry`. - -The report includes `exchange_error_bound` in the output unit, accounting for geometric tolerance, frame normalization and coordinate precision. Export rejects budgets below this bound and bodies exceeding its resource limits. Report revisions are decimal strings, preserving the full unsigned 64-bit value. - -`JSON.parse(validateAnalyticBrep(serialized))` returns `{ valid, validation_level, error }`. Import the helper from `"opengeometry"` and initialize the WASM runtime first. Invalid schema, required fields, topology or sampled residuals produce structured diagnostics. A successful report does not certify general self-intersections or cavity containment. Rebuild defective geometry from authored parameters rather than assuming vertex welding repairs analytic models. - -## IFC4 exchange - -`solid.prepareIfcExchange()` returns a strict `AnalyticExchangeBodyV2`: shared IFC geometry definitions, solid membership, face ancestry, quality and exchange error bounds. Rust applies world placement and converts Y-up metres to Z-up metres exactly once. The receiver assembles those definitions without geometry reconstruction. - -`solid.exportIfc()` returns `{ text, report }` for standalone IFC4 export. The Python semantic service accepts the same prepared body with required `schemaVersion: "2.0"` and `type: "FREEFORM_ANALYTIC"`. Old semantic versions and old raw BRep are rejected. Shared native fixtures pass formal IFC4 entity and EXPRESS validation. - -Cavity bodies use analytic CSG differences of AdvancedBreps. This avoids the inverted inner comparison in [IFC4's published `VoidsHaveAdvancedFaces` rule](https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/schema/ifcgeometricmodelresource/lexical/ifcadvancedbrepwithvoids.htm) while preserving exact surfaces and cut ancestry. General numerical intersection edges use the same bounded export-only cubic fitting as STEP. - -## Worker camera LOD - -Import `AnalyticTessellationWorker` and `AnalyticLodController` from `"opengeometry"`. Construct the worker with explicit `workerURL` (the published `opengeometry/analytic-worker.js` asset), `kernelURL` (the public WASM glue asset) and `wasmURL`. Await `lod.register(solid)` after each authored model replacement; unchanged camera requests send only its handle and deflection. Unregister removed models and dispose both controller and worker. - -Call `lod.update(camera, renderer.domElement.height)` each frame. Visible bodies target 0.5 physical pixels at rest and 2 during motion, with factor-two buckets, 25% hysteresis, at most 100 ms scheduling and 150 ms settle refinement. Stale responses are discarded. Resource or precision failures retain the prior mesh and call `onError`. Sync computations already running in WASM finish before the next queued job; they cannot be interrupted midway. - -Await `lod.refine(worldDeflection)` before image export to require explicit refinement. Positive uniform scale adjusts local deflection; unsupported placement returns an error. Render LOD never refreshes authored scene snapshots. - -Floorkit `OpenThree.enableAnalyticLod(options)` uses this service. Await `syncAnalyticLod()` after authored tree replacements, then `refineAnalyticView(deflection)` before synchronous image capture. The downstream `views/analytic-rendering.html` example exercises those calls and semantic v2 exchange. Current development uses the local tested kernel artifact; a coordinated published major release remains pending. - -## Feature outlines - -Set `shape.outline = true` to show analytic boundary and crease edges. The tessellator suppresses -chart seams and shared coplanar subdivisions. Outlines retessellate together with surfaces and -use the same local GPU origin and combined error budget. Raycast against `shape.featureOutline` -and pass `Math.floor(hit.index / 2)` to `shape.edgeIdForOutlineSegment(...)` to retrieve the EdgeId. -Dispose the shape to release both its surface and outline buffers. - -## Analytic booleans - -`host.boolean(cutter, operation, options?)` supports `"union"`, `"intersection"`, and `"subtraction"` for canonical full spheres, aligned cuboids, line-profile extrusions with coextensive slabs or matching profiles, coaxial cone/frustum containment, and the documented cylinder configurations. This experimental path uses in-house intersection and topology construction with retained analytic faces and shared edges. It does not use the mesh bridge. The standalone `booleanUnion`, `booleanIntersection`, and `booleanSubtraction` helpers route pairs of `AnalyticSolid` operands to the same path. - -```ts -const host = new AnalyticSolid({ kind: "sphere", radius: 1, deflection: 0.01 }); -const cutter = new AnalyticSolid({ - kind: "sphere", radius: 1, deflection: 0.01, - frame: { origin: [1, 0, 0], x: [1, 0, 0], y: [0, 0, -1], z: [0, 1, 0] }, -}); -const result = host.boolean(cutter, "subtraction", { deflection: 0.01 }); -// Equivalent: booleanSubtraction(host, cutter, { outline: true }) -scene.add(result); -console.log(result.report); // contacts and input-to-result face mappings -``` - -Disjoint union retains separate closed solids; external point contacts are reported without sewing shells. Subtracting an enclosed cutter creates an inward-oriented cavity shell. Coincident faces use host ownership and record both sources. Empty intersections and fully removed hosts return an empty v2 model. Results inherit the host's color unless `options.color` overrides it. - -Boolean operands include their complete world placement, including positive uniform scale. Results contain world-space geometry with identity group placement; add them to the scene root. Nonuniform scale, reflections, shear and insufficient coordinate precision return errors. - -Aligned cuboid inputs sharing the same axes use a bounded plane arrangement for union, -intersection and subtraction. Coextensive `linearExtrusion` operands use a grouped winding -arrangement that preserves authored holes, boundary-touching differences, and every disconnected -result region. Results retain Plane surfaces, shared Line edges, and immediate face ancestry; -cutter side faces are marked as reversed cut faces. Face contact joins regularized material; -edge and point contacts keep separate solids. Plane arrangements with unresolved widths return -`UnresolvedIntersection`. Matching-profile extrusions also support different axial spans: overlap -merges or intersects the intervals, and subtraction can return two closed solids with cutter-cap -ancestry. Extrusions that differ in both profile and height span, different extrusion axes, boxes -with different axes, and other planar solids still return `CoverageGap`. - -Cylinder coverage includes coaxial overlap and containment, parallel generator contact, coextensive transverse material operations, bounded transverse intersection, embedded transverse union/subtraction, full-span cuts, concentric and eccentric through-holes, and sealed cavities. Every result remains Plane/Cylinder BRep with one-boolean provenance. Strictly nested coaxial cones/frusta, sphere/conic, coaxial cylinder/conic, and cuboid/conic containment, nested coaxial ring tori, and sphere/torus containment also preserve exact supports and create oriented cavity shells. Ring tori can additionally form exact cavities inside proven enclosing cylinders, cuboids, and coaxial cone/frustum sections. Coincident conic bodies resolve deterministic ownership; cap or lateral contact within the geometric budget returns `UnresolvedIntersection`. Other intersecting conic and torus arrangements still return `CoverageGap`. - - -The SSI query layer covers analytic fast cases and bounded numerical branches for finite sphere/torus source charts, including general torus interactions. Boolean topology construction still returns `CoverageGap` for intersecting surface arrangements outside the documented sphere, cuboid, cylinder, and containment cases. Internal tangency that would join a cavity to the host at a point and caps or clearances below geometric resolution return `UnresolvedIntersection`. No automatic faceted fallback occurs in this API. - -Each result face records immediate input entity/body/face-key ancestry, split/cut/coincident role, and reversal. `result.report.face_mappings` includes discarded input faces with empty result lists. Naming across arbitrary chained edits is not guaranteed. - -`AnalyticSolid.fromBrep(serialized, { deflection, color })` renders a validated v2 model with its original body ID. It rejects old raw BRep payloads. Retessellating a boolean result changes render density without changing its geometry or provenance. - -## Analytic arcs - -`AnalyticCurve` constructs an authoritative circle or ellipse edge with a parameter span and an oriented wire use. Its `startAngle` and signed `sweepAngle` use radians. Sweeps must be nonzero and at most one full turn; a full circle has one model vertex and one closed edge. Positive sweep follows the supplied right-handed frame. - -```ts -import { AnalyticCurve } from "opengeometry"; - -// Construct after OpenGeometry.create() resolves. -const arc = new AnalyticCurve({ - kind: "arc", radius: 2, startAngle: 0, sweepAngle: Math.PI, deflection: 0.01, -}); -const ellipse = new AnalyticCurve({ - kind: "ellipticalArc", majorRadius: 3, minorRadius: 1, - startAngle: 0, sweepAngle: -Math.PI, deflection: 0.01, -}); -scene.add(arc, ellipse); -arc.retessellate(0.002); -``` - -Ellipse radii require `majorRadius >= minorRadius > 0`. The frame's `x` direction carries the major radius and `y` the minor radius. The default frame draws in the XZ plane with Y as its normal. - -Raycast against `curve.line` and pass `Math.floor(hit.index / 2)` to `curve.edgeIdForSegment(...)`. Call `curve.getBrepSerialized()` for its strict v2 wire model and `curve.dispose()` when removing it. Deflection sampling uses the same kernel service and cache as analytic solids; the render segments never replace the circle or ellipse definition. diff --git a/docs/api/shapes/cuboid.mdx b/docs/api/shapes/cuboid.mdx deleted file mode 100644 index 8545f3ca..00000000 --- a/docs/api/shapes/cuboid.mdx +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: 'Cuboid' -description: 'Create an authoritative six-plane BRep v2 solid' -icon: 'cube' ---- - -## Overview - -`Cuboid` is a strict analytic BRep v2 solid. Six plane surfaces, twelve line curves, face trims, -edge uses, and provenance remain authoritative. Three.js triangles are transient output generated -from the requested `deflection`. - -Initialize `OpenGeometry.create(...)` before constructing `Vector3` or a cuboid. - -## Constructor - -```ts -const cuboid = new Cuboid(options?: ICuboidOptions); -``` - - - Stable model identifier. It is generated when omitted. - - - - Center in the cuboid's local coordinates. - - - - Positive local X extent. - - - - Positive local Y extent. - - - - Positive local Z extent. - - - - Maximum requested world-space tessellation error. - - - - Three.js render color; it does not alter the BRep. - - - - - - Scale must be positive and uniform when evaluated by geometry operations. - - -## Geometry and placement - -`setConfig()` rebuilds analytic planes and trims. Placement remains on the Three.js object and is -applied once when a boolean or export requests world geometry. - -```ts -cuboid.setConfig({ width: 7.2, height: 3.2, depth: 0.28 }); -cuboid.setPlacement({ - translation: new Vector3(2, 0, 0), - rotation: new Vector3(0, Math.PI / 10, 0), - scale: new Vector3(1, 1, 1), -}); -``` - -Use `getBrepSerialized()` or `getBrepData()` for the local strict v2 model and -`getWorldBrepSerialized()` for the placed model. `retessellate(deflection)` changes only the GPU -mesh. `faceIdForTriangle()` and `edgeIdForOutlineSegment()` map rendered picks back to topology. - -Direct v2 freeform conversion is not implemented. `canConvertToFreeform()` returns `false` and -`toFreeform()` reports `UnsupportedAnalyticEdit`. - -## Boolean example - -```ts -import { Cuboid, Opening, OpenGeometry, Vector3 } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); - -const wall = new Cuboid({ - center: new Vector3(0, 1.5, 0), - width: 6, - height: 3, - depth: 0.3, - color: 0x9ca3af, - deflection: 0.005, -}); -const opening = new Opening({ - center: new Vector3(0, 1.2, 0), - width: 1.2, - height: 1.5, - depth: 0.45, -}); -const cut = opening.subtractFrom(wall, { deflection: 0.005 }); -cut.outline = true; -``` - -## Live demos - -- [Cuboid demo](https://demo.opengeometry.io/shapes/cuboid.html) -- [Cuboid placement demo](https://demo.opengeometry.io/shapes/cuboid-placement.html) diff --git a/docs/api/shapes/cylinder.mdx b/docs/api/shapes/cylinder.mdx deleted file mode 100644 index 9a87f09f..00000000 --- a/docs/api/shapes/cylinder.mdx +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: 'Cylinder' -description: 'Create authoritative cylindrical solids and sectors with deflection-controlled rendering' -icon: 'database' ---- - -## Overview - -`Cylinder` creates a strict BRep v2 solid aligned to the Y axis. A full cylinder contains one -trimmed cylindrical face and two planar caps. A partial sweep adds two exact radial planes. -Changing render deflection never changes this topology. - - - Initialize `OpenGeometry.create(...)` before constructing `Vector3` or `Cylinder`. - - -## Constructor - -```ts -const cylinder = new Cylinder(options?: ICylinderOptions); -``` - -### ICylinderOptions - - - Stable entity identifier. Auto-generated when omitted. - - - - Object center. Defaults to the origin. - - - - Authoritative cylinder radius. - - - - Height along the local Y axis. - - - - Sector start parameter in radians. - - - - Signed sector sweep in radians. A full turn creates a periodic full cylinder. - - - - Maximum requested render chord error in model units. - - - - Three.js surface color. - - -## Geometry and booleans - -`getBrepSerialized()` and `getBrepData()` return the strict schema-version-2 model. Use -`retessellate(deflection)` to replace only the transient GPU mesh. `faceIdForTriangle(...)` and -`edgeIdForOutlineSegment(...)` map picking results back to model topology. - -`Cylinder` inherits `union(other)`, `intersection(other)`, `subtract([cutters])`, and -`boolean(other, operation)`. Every operand must be an `AnalyticSolid`; unsupported surface -arrangements return a structured kernel error instead of falling back to a mesh boolean. - -Use the normal Three.js `position`, `rotation`, and uniform positive `scale` properties for -placement. Boolean operations and world BRep serialization evaluate that placement exactly. - -## Examples - -```ts -import { Cylinder, Vector3 } from "opengeometry"; - -const cylinder = new Cylinder({ - center: new Vector3(0, 1, 0), - radius: 0.9, - height: 2, - deflection: 0.01, - color: 0xf97316, -}); -cylinder.outline = true; -``` - -```ts -const sector = new Cylinder({ - center: new Vector3(0, 1.1, 0), - radius: 1.4, - height: 2.2, - startAngle: -Math.PI / 4, - sweepAngle: Math.PI * 1.25, - deflection: 0.01, - color: 0x2563eb, -}); -``` - -## Live demos - -- [Cylinder](https://demo.opengeometry.io/shapes/cylinder.html) -- [Cylinder sector](https://demo.opengeometry.io/shapes/cylinder-sector.html) diff --git a/docs/api/shapes/opening.mdx b/docs/api/shapes/opening.mdx deleted file mode 100644 index c14f7fa7..00000000 --- a/docs/api/shapes/opening.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: 'Opening' -description: 'Subtract a strict analytic box volume from a BRep v2 host' -icon: 'door-open' ---- - -## Overview - -`Opening` is an authoritative six-plane BRep v2 cutter. It extends `Cuboid`, renders its surface -transparent by default, and keeps its topology available for selection, export, and provenance. -`subtractFrom()` runs the in-house analytic boolean engine and returns a new `AnalyticSolid`; it -does not mutate the host or rebuild a triangle BRep. - -Initialize `OpenGeometry.create(...)` before constructing `Vector3` or an opening. - -## Constructor - -```ts -const opening = new Opening(options?: IOpeningOptions); -``` - -The options are `ogid`, `center`, `width`, `height`, `depth`, `color`, `deflection`, `accuracy`, -`translation`, `rotation`, and positive uniform `scale`. Defaults are a `1 × 1 × 0.2` cutter -centered at the origin. - -## Subtract from a host - -```ts -import { Cuboid, Opening, OpenGeometry, Vector3 } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); - -const wall = new Cuboid({ - center: new Vector3(0, 1.6, 0), - width: 4.4, - height: 3.2, - depth: 0.32, - color: 0xcbd5e1, -}); -const opening = new Opening({ - center: new Vector3(0, 1.35, 0), - width: 1.4, - height: 2, - depth: 0.45, -}); - -const cutWall = opening.subtractFrom(wall, { deflection: 0.005 }); -cutWall.outline = true; -``` - -`setConfig()` regenerates the cutter. `setPlacement()` changes translation, rotation, and scale. -`getBrepSerialized()`, `getBrepData()`, `getWorldBrepSerialized()`, picking mappings, STEP/IFC -exchange, and `retessellate()` are inherited from the analytic solid API. - -The boolean report is available as `cutWall.report`. It includes source-to-result face mappings, -cut-face ancestry, contact points, and coincident-boundary status. - -## Live demo - -- [Opening boolean demo](https://demo.opengeometry.io/shapes/opening.html) diff --git a/docs/api/shapes/polygon.mdx b/docs/api/shapes/polygon.mdx deleted file mode 100644 index 1ebeefc5..00000000 --- a/docs/api/shapes/polygon.mdx +++ /dev/null @@ -1,280 +0,0 @@ ---- -title: 'Polygon' -description: 'Create planar polygon faces with holes, outlines, booleans, and kernel-backed extrusion' -icon: 'draw-polygon' ---- - -## Overview - -`Polygon` is the planar profile wrapper in the Three.js API. It creates a filled face on the XZ -plane, supports holes, can participate in coplanar booleans, converts to freeform geometry, and -extrudes into a renderable [`Solid`](/api/shapes/solid). - -Outer loops should be provided counter-clockwise when viewed from above. Hole loops should be -provided clockwise. - - - Initialize `OpenGeometry.create(...)` before constructing `Vector3` or running the examples on - this page. - - -## Constructor - -```ts -const polygon = new Polygon(options?: IPolygonOptions); -``` - -### IPolygonOptions - - - Unique identifier for the polygon. Auto-generated when omitted. - - - - Vertices for the outer loop. - - - - Optional inner loops. Each hole is its own vertex array. - - - - Face color as a hex number. - - - - Enables wide outline rendering with `LineSegments2`. - - - - Outline width used when `fatOutlines` is enabled. - - - - Initial placement translation. - - - - Initial placement rotation in radians. - - - - Initial placement scale. - - -## Methods - -### setConfig(), getConfig() - -Updates or reads the current polygon config. - -```ts -polygon.setConfig(options: PolygonConfigUpdate): void -const config = polygon.getConfig(); -``` - -### addVertices(), addHole() - -Convenience helpers for replacing the outer loop or appending a new hole loop. - -```ts -polygon.addVertices(vertices: Vector3[]): void -polygon.addHole(holeVertices: Vector3[]): void -``` - -### getPlacement(), getAnchor(), setAnchor(), resetAnchor() - -Returns cloned placement values or reads/updates the current kernel anchor. - -```ts -const placement = polygon.getPlacement(); -const anchor = polygon.getAnchor(); -polygon.setAnchor(anchor); -polygon.resetAnchor(); -``` - -### setPlacement(), setTransform(), setTranslation(), setRotation(), setScale() - -Placement helpers for moving the polygon through the kernel transform path. - -```ts -polygon.setPlacement({ translation?, rotation?, scale? }); -``` - -### extrude() - -Extrudes the polygon face and returns a renderable [`Solid`](/api/shapes/solid). - -```ts -const solid = polygon.extrude(height); -``` - - - Finite, non-zero extrusion height. - - -### loftTo() - -Creates a capped analytic ruled solid between this polygon and another placed polygon. - -```ts -const loft = lower.loftTo(upper, { alignment: "auto", deflection: 0.01 }); -``` - -The two polygons must have equal vertex counts, no holes, parallel section planes, and planar side -quadrilaterals. See [Polygon loft](/api/operations/loft) for correspondence controls and errors. - -### toFreeform() - -Converts the polygon into a freeform geometry wrapper. - -```ts -const freeform = polygon.toFreeform(id?); -``` - -### getBrepData() - -Returns the serialized BRep JSON string for the current polygon face. - -```ts -const brepSerialized = polygon.getBrepData(); -``` - -`tessellateFacetedBrep` evaluates the kernel's planar triangulation, including every hole, -and returns transient triangle positions as a `Float64Array`. It preserves the input's -coordinate space and face orientation. Invalid topology, empty output, and resource limits -throw errors. This helper accepts explicitly faceted BReps; use `AnalyticSolid.retessellate` -for versioned analytic geometry. - -```ts -import { tessellateFacetedBrep } from "opengeometry"; - -const positions = tessellateFacetedBrep(polygon.getBrepData()); -const triangleCount = positions.length / 9; -``` - -### generateGeometry(), cleanGeometry(), dispose() - -Rebuilds the polygon mesh or clears owned Three.js resources. - -```ts -polygon.generateGeometry(): void -polygon.cleanGeometry(): void -polygon.dispose(): void -``` - -## Properties - - - Stable identifier for the polygon wrapper. - - - - Current polygon configuration and placement state. - - - - Gets or sets the face color. - - - - Enables or disables outline rendering. - - - - Enables or disables wide outlines. - - - - Outline width used for wide outlines. - - - - Gets or sets the outline color. - - -## Examples - -### Polygon with a hole - -```ts -import { Polygon, Vector3 } from "opengeometry"; - -const slab = new Polygon({ - vertices: [ - new Vector3(0, 0, 0), - new Vector3(8, 0, 0), - new Vector3(8, 0, 6), - new Vector3(0, 0, 6), - ], - holes: [[ - new Vector3(5, 0, 4), - new Vector3(5, 0, 2), - new Vector3(3, 0, 2), - new Vector3(3, 0, 4), - ]], - color: 0x2563eb, -}); - -slab.outline = true; -``` - -### Build a polygon incrementally - -```ts -import { Polygon, Vector3 } from "opengeometry"; - -const footprint = new Polygon({ - vertices: [ - new Vector3(0, 0, 0), - new Vector3(4, 0, 0), - new Vector3(4, 0, 3), - new Vector3(0, 0, 3), - ], - color: 0x0f172a, -}); - -footprint.addHole([ - new Vector3(2.8, 0, 2.2), - new Vector3(2.8, 0, 1.2), - new Vector3(1.8, 0, 1.2), - new Vector3(1.8, 0, 2.2), -]); -``` - -### Build an analytic extrusion for booleans - -```ts -import { AnalyticSolid } from "opengeometry"; - -const wall = new AnalyticSolid({ - kind: "linearExtrusion", - outer: [[-2.2, -0.18], [2.2, -0.18], [2.2, 0.18], [-2.2, 0.18]], - holes: [], - height: 2.8, - color: 0x60a5fa, -}); -const opening = new AnalyticSolid({ - kind: "linearExtrusion", - outer: [[-0.7, -0.34], [0.9, -0.34], [0.9, 0.34], [-0.7, 0.34]], - holes: [], - height: 1.35, -}); -opening.position.y = 0.85; -const cut = wall.subtract([opening], { deflection: 0.005 }); -``` - -### Move or rotate the polygon profile - -```ts -wallProfile.setPlacement({ - translation: new Vector3(1.5, 0, 0), - rotation: new Vector3(0, Math.PI / 8, 0), - scale: new Vector3(1, 1, 1), -}); -``` - -## Live demo - -- [Polygon demo](https://demo.opengeometry.io/shapes/polygon.html) -- [Extruded boolean operations demo](https://demo.opengeometry.io/operations/extruded-boolean-operations.html) diff --git a/docs/api/shapes/solid.mdx b/docs/api/shapes/solid.mdx deleted file mode 100644 index c89524c3..00000000 --- a/docs/api/shapes/solid.mdx +++ /dev/null @@ -1,212 +0,0 @@ ---- -title: 'Solid' -description: 'Generic renderable BRep-backed solid used by polygon extrusion and other kernel outputs' -icon: 'cube' ---- - -## Overview - -`Solid` is the generic BRep-backed mesh wrapper used when the kernel produces a solid that is not a -dedicated parametric primitive. The most common public path is: - -```ts -const solid = polygon.extrude(height); -``` - -`Solid` supports kernel-backed placement, outline rendering, freeform conversion, parsed and -serialized BRep access, and boolean subtraction. - - - Initialize `OpenGeometry.create(...)` before constructing `Vector3` or running the examples on - this page. - - -## Constructor - -```ts -const solid = new Solid(options: ISolidOptions); -``` - -### ISolidOptions - - - Unique identifier for the solid. Auto-generated when omitted. - - - - Serialized BRep JSON, parsed BRep-like data, or another wrapper exposing supported BRep accessors. - - - - Mesh color as a hex number. - - - - Enables wide outline rendering with `LineSegments2`. - - - - Outline width used when `fatOutlines` is enabled. - - - - Optional modeling anchor. - - - - Initial placement translation. - - - - Initial placement rotation in radians. - - - - Initial placement scale. - - -## Static helper - -### Solid.extrude() - -Extrudes a face-like BRep source and immediately wraps it as a `Solid`. - -```ts -const solid = Solid.extrude(source, height, options); -``` - -## Methods - -### getPlacement(), getAnchor() - -Returns cloned placement values or the current modeling anchor. - -```ts -const placement = solid.getPlacement(); -const anchor = solid.getAnchor(); -``` - -### setPlacement(), setTransform(), setTranslation(), setRotation(), setScale(), setAnchor() - -Placement helpers for moving the solid through the wrapped freeform placement path. - -```ts -solid.setPlacement({ translation?, rotation?, scale? }); -solid.setAnchor(anchor); -``` - -### toFreeform() - -Converts the solid back into a freeform geometry wrapper. - -```ts -const freeform = solid.toFreeform(id?); -``` - -### getBrepSerialized(), getLocalBrepSerialized(), getBrepData() - -Returns the world-space serialized BRep, the local-space serialized BRep, or the parsed world-space -BRep object. - -```ts -const serialized = solid.getBrepSerialized(); -const localSerialized = solid.getLocalBrepSerialized(); -const brep = solid.getBrepData(); -``` - -### generateGeometry() - -Rebuilds the visible mesh and outline state from the wrapped BRep/freeform data. - -```ts -solid.generateGeometry(): void -``` - -## Properties - - - Stable identifier for the solid wrapper. - - - - Gets or sets the render color. - - - - Enables or disables outline rendering. - - - - Enables or disables wide outlines. - - - - Outline width used for wide outlines. - - - - Gets or sets the outline color. - - -## Examples - -### Recommended path: polygon extrusion - -```ts -import { Polygon, Vector3 } from "opengeometry"; - -const profile = new Polygon({ - vertices: [ - new Vector3(-1, 0, -0.2), - new Vector3(1, 0, -0.2), - new Vector3(1, 0, 0.2), - new Vector3(-1, 0, 0.2), - ], - color: 0x2563eb, -}); - -const wall = profile.extrude(2.8); -wall.outline = true; -``` - -### Use the static extrusion helper - -```ts -import { Polygon, Solid, Vector3 } from "opengeometry"; - -const profile = new Polygon({ - vertices: [ - new Vector3(-0.8, 0, -0.25), - new Vector3(0.8, 0, -0.25), - new Vector3(0.8, 0, 0.25), - new Vector3(-0.8, 0, 0.25), - ], - color: 0x0f172a, -}); - -const solid = Solid.extrude(profile, 2.4, { - color: 0x10b981, - outlineWidth: 2, -}); -``` - -### Wrap an existing BRep payload - -```ts -import { Solid } from "opengeometry"; - -const solid = new Solid({ - brep: existingBrepSerialized, - color: 0x10b981, -}); -``` - -### Convert the solid to freeform - -```ts -const freeform = solid.toFreeform(); -``` - -## Live demo - -- [Extruded boolean operations demo](https://demo.opengeometry.io/operations/extruded-boolean-operations.html) diff --git a/docs/api/shapes/sphere.mdx b/docs/api/shapes/sphere.mdx deleted file mode 100644 index 9aaa180a..00000000 --- a/docs/api/shapes/sphere.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: 'Sphere' -description: 'Create an authoritative spherical solid with deflection-controlled rendering' -icon: 'globe' ---- - -## Overview - -`Sphere` creates a strict BRep v2 solid with one spherical face, one periodic seam, and explicit -collapsed pole uses. Render triangles are generated on demand and never become model geometry. - - - Initialize `OpenGeometry.create(...)` before constructing `Vector3` or `Sphere`. - - -## Constructor - -```ts -const sphere = new Sphere(options?: ISphereOptions); -``` - -### ISphereOptions - - - Stable entity identifier. Auto-generated when omitted. - - - - Sphere center. Defaults to the origin. - - - - Authoritative sphere radius. - - - - Maximum requested render chord error in model units. - - - - Three.js surface color. - - -## Geometry and booleans - -`getBrepSerialized()` and `getBrepData()` return the strict schema-version-2 model. Use -`retessellate(deflection)` to change display density while preserving the single spherical face. -Picking maps through `faceIdForTriangle(...)` and normals come from `normalAtFace(...)`. - -`Sphere` inherits `union(other)`, `intersection(other)`, `subtract([cutters])`, and -`boolean(other, operation)`. Every operand must be an `AnalyticSolid`; the kernel reports missing -coverage or unresolved intersections rather than using a mesh bridge. - -Use the normal Three.js `position`, `rotation`, and uniform positive `scale` properties for -placement. - -## Example - -```ts -import { Sphere, Vector3 } from "opengeometry"; - -const sphere = new Sphere({ - center: new Vector3(0, 1.1, 0), - radius: 1.1, - deflection: 0.01, - color: 0x0891b2, -}); -sphere.outline = true; -``` - -## Live demo - -- [Sphere](https://demo.opengeometry.io/shapes/sphere.html) diff --git a/docs/api/shapes/sweep.mdx b/docs/api/shapes/sweep.mdx deleted file mode 100644 index 28583d53..00000000 --- a/docs/api/shapes/sweep.mdx +++ /dev/null @@ -1,215 +0,0 @@ ---- -title: 'Sweep' -description: 'Create swept solids from a path array and a profile array' -icon: 'life-ring' ---- - -## Overview - -`Sweep` creates a solid by sweeping a planar `profile` array along a 3D `path` array. It supports -optional start and end caps, kernel-backed placement, anchor control, freeform conversion, parsed -BRep access, and boolean subtraction. - - - Initialize `OpenGeometry.create(...)` before constructing `Vector3` or running the examples on - this page. - - -## Constructor - -```ts -const sweep = new Sweep(options?: ISweepOptions); -``` - -### ISweepOptions - - - Unique identifier for the sweep. Auto-generated when omitted. - - - - Path points used to drive the sweep. At least two points are required. - - - - Profile points to sweep along the path. At least three points are required. - - - - Mesh color as a hex number. - - - - Adds a start cap when enabled. - - - - Adds an end cap when enabled. - - - - Enables wide outline rendering with `LineSegments2`. - - - - Outline width used when `fatOutlines` is enabled. - - - - Initial placement translation. - - - - Initial placement rotation in radians. - - - - Initial placement scale. - - -## Methods - -### setConfig(), getConfig() - -Updates or reads the current sweep config. - -```ts -sweep.setConfig(options: SweepConfigUpdate): void -const config = sweep.getConfig(); -``` - -### getPlacement(), getAnchor(), setAnchor(), resetAnchor() - -Returns cloned placement values or reads/updates the current kernel anchor. - -```ts -const placement = sweep.getPlacement(); -const anchor = sweep.getAnchor(); -sweep.setAnchor(anchor); -sweep.resetAnchor(); -``` - -### setPlacement(), setTransform(), setTranslation(), setRotation(), setScale() - -Placement helpers for moving the sweep through the kernel transform path. - -```ts -sweep.setPlacement({ translation?, rotation?, scale? }); -``` - -### toFreeform() - -Converts the sweep into a freeform geometry wrapper. - -```ts -const freeform = sweep.toFreeform(id?); -``` - -### getBrep() - -Returns the parsed BRep object for the current sweep. - -```ts -const brep = sweep.getBrep(); -``` - -### generateGeometry(), discardGeometry() - -Rebuilds or disposes the current Three.js geometry. - -```ts -sweep.generateGeometry(): void -sweep.discardGeometry(): void -``` - -## Properties - - - Stable identifier for the sweep wrapper. - - - - Current sweep configuration and placement state. - - - - Gets or sets the render color. - - - - Enables or disables outline rendering. - - - - Enables or disables wide outlines. - - - - Outline width used for wide outlines. - - -## Examples - -### Create a capped sweep - -```ts -import { Sweep, Vector3 } from "opengeometry"; - -const sweep = new Sweep({ - path: [ - new Vector3(-1.4, 0, -1.6), - new Vector3(-0.5, 0.6, -0.5), - new Vector3(0.4, 1.3, 0.8), - new Vector3(1.2, 2.4, 2.1), - ], - profile: [ - new Vector3(-0.4, 0, -0.25), - new Vector3(0.4, 0, -0.25), - new Vector3(0.4, 0, 0.25), - new Vector3(-0.4, 0, 0.25), - ], - color: 0x3b82f6, - capStart: true, - capEnd: true, -}); -``` - -### Create an open-ended tube or rail - -```ts -const openSweep = new Sweep({ - path: [ - new Vector3(0, 0, 0), - new Vector3(0, 1.2, 0), - new Vector3(1.4, 2.1, 0.6), - ], - profile: [ - new Vector3(-0.2, 0, -0.2), - new Vector3(0.2, 0, -0.2), - new Vector3(0.2, 0, 0.2), - new Vector3(-0.2, 0, 0.2), - ], - color: 0x0f172a, - capStart: false, - capEnd: false, -}); -``` - -### Update the path or profile - -```ts -sweep.setConfig({ - path: [ - new Vector3(-1.6, 0, -1.8), - new Vector3(-0.6, 0.8, -0.6), - new Vector3(0.3, 1.6, 0.9), - new Vector3(1.5, 2.7, 2.2), - ], -}); -``` - -## Live demo - -- [Sweep demo](https://demo.opengeometry.io/shapes/sweep.html) -- [Window frame sweep demo](https://demo.opengeometry.io/shapes/window-frame-sweep.html) -- [Sweep path/profile demo](https://demo.opengeometry.io/operations/sweep-path-profile.html) diff --git a/docs/api/shapes/wedge.mdx b/docs/api/shapes/wedge.mdx deleted file mode 100644 index 9e49df17..00000000 --- a/docs/api/shapes/wedge.mdx +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: 'Wedge' -description: 'Create wedge solids with configurable dimensions, placement, outlines, and booleans' -icon: 'triangle' ---- - -## Overview - -`Wedge` creates a prism-like wedge solid defined by `center`, `width`, `height`, and `depth`. It -supports kernel-backed placement, freeform conversion, parsed BRep access, and boolean -subtraction. - - - Initialize `OpenGeometry.create(...)` before constructing `Vector3` or running the examples on - this page. - - -## Constructor - -```ts -const wedge = new Wedge(options?: IWedgeOptions); -``` - -### IWedgeOptions - - - Unique identifier for the wedge. Auto-generated when omitted. - - - - Center point of the wedge. - - - - Width along the X axis. - - - - Height along the Y axis. - - - - Depth along the Z axis. - - - - Mesh color as a hex number. - - - - Enables wide outline rendering with `LineSegments2`. - - - - Outline width used when `fatOutlines` is enabled. - - - - Initial placement translation. - - - - Initial placement rotation in radians. - - - - Initial placement scale. - - -## Methods - -### setConfig(), getConfig() - -Updates or reads the current wedge config. - -```ts -wedge.setConfig(options: WedgeConfigUpdate): void -const config = wedge.getConfig(); -``` - -### getPlacement(), getAnchor() - -Returns cloned placement values or the current kernel anchor. - -```ts -const placement = wedge.getPlacement(); -const anchor = wedge.getAnchor(); -``` - -### setPlacement(), setTransform(), setTranslation(), setRotation(), setScale() - -Placement helpers for moving the wedge through the kernel transform path. - -```ts -wedge.setPlacement({ translation?, rotation?, scale? }); -``` - -### toFreeform() - -Converts the wedge into a freeform geometry wrapper. - -```ts -const freeform = wedge.toFreeform(id?); -``` - -### getBrepData() - -Returns the parsed BRep object for the current wedge. - -```ts -const brep = wedge.getBrepData(); -``` - -### generateGeometry(), discardGeometry() - -Rebuilds or disposes the current Three.js geometry. - -```ts -wedge.generateGeometry(): void -wedge.discardGeometry(): void -``` - -## Properties - - - Stable identifier for the wedge wrapper. - - - - Current wedge configuration and placement state. - - - - Gets or sets the render color. - - - - Enables or disables outline rendering. - - - - Enables or disables wide outlines. - - - - Outline width used for wide outlines. - - -## Examples - -### Create a wedge or ramp - -```ts -import { Wedge, Vector3 } from "opengeometry"; - -const wedge = new Wedge({ - center: new Vector3(0, 0.85, 0), - width: 2.2, - height: 1.7, - depth: 1.4, - color: 0x7c3aed, -}); -``` - -### Place and rotate the wedge - -```ts -wedge.setPlacement({ - translation: new Vector3(1.5, 0, 0), - rotation: new Vector3(0, Math.PI / 2, 0), - scale: new Vector3(1, 1, 1), -}); -``` - -### Resize the wedge - -```ts -wedge.setConfig({ - width: 3.2, - height: 1.9, - depth: 2.4, - color: 0x2563eb, -}); -``` - -## Live demo - -- [Wedge demo](https://demo.opengeometry.io/shapes/wedge.html) diff --git a/docs/concepts/architecture.mdx b/docs/concepts/architecture.mdx deleted file mode 100644 index e17f4f91..00000000 --- a/docs/concepts/architecture.mdx +++ /dev/null @@ -1,201 +0,0 @@ ---- -title: 'Architecture Overview' -description: 'Understanding the layered architecture of OpenGeometry' ---- - -OpenGeometry is built with a layered architecture designed to bring high-performance CAD operations to the web. The system follows a clear separation between the computational core and the rendering layer. - -## System Architecture - -The architecture consists of three primary layers: - -``` -┌─────────────────────────────────────────┐ -│ TypeScript/Three.js Application │ ← User-facing API -│ (Browser/Node.js) │ -└─────────────────┬───────────────────────┘ - │ - │ WASM bindings - ↓ -┌─────────────────────────────────────────┐ -│ WebAssembly Module │ ← Compiled from Rust -│ (opengeometry.wasm) │ -└─────────────────┬───────────────────────┘ - │ - │ Core algorithms - ↓ -┌─────────────────────────────────────────┐ -│ Rust Core (opengeometry) │ ← Graphics kernel -│ • Primitives │ -│ • Operations │ -│ • BREP │ -│ • Export │ -└─────────────────────────────────────────┘ -``` - -### Data Flow - -1. **User Input** → TypeScript wrapper classes (Line, Cuboid, etc.) -2. **TypeScript** → WASM function calls via `wasm-bindgen` -3. **Rust Core** → Geometric computations, BREP construction -4. **WASM Output** → Serialized geometry data (JSON/typed arrays) -5. **TypeScript** → Three.js mesh rendering - -## Module Structure - -The Rust core is organized into focused modules as defined in `src/lib.rs`: - -### Core Modules - -**primitives** -- `arc` - Circular arc segments -- `cuboid` - Box primitives -- `curve` - Parametric curves -- `cylinder` - Cylindrical solids -- `line` - Line segments -- `polygon` - N-sided planar polygons -- `polyline` - Connected line segments -- `rectangle` - Rectangular faces -- `sphere` - Spherical solids -- `sweep` - Swept surfaces -- `wedge` - Wedge/prism solids - -**operations** -- `extrude` - Extrude 2D profiles into 3D solids -- `offset` - Offset curves and faces -- `sweep` - Sweep profiles along paths -- `triangulate` - Convert faces to triangular meshes -- `windingsort` - Polygon winding order utilities - -**booleans** -- Kernel-backed boolean operations (union, intersection, subtraction) - -**brep** -Boundary representation data structures: -- `vertex` - Point in 3D space -- `halfedge` - Directed half-edge topology (twin/next/prev) -- `edge` - Undirected edge with primary/twin half-edge references -- `loop` - Face boundary loops (outer and inner holes) -- `face` - Face normal and loop references -- `wire` - Polyline topology (open or closed) -- `shell` - Face groups (open or closed) -- `builder` - Safe B-Rep construction helper that validates topology -- `error` - B-Rep error types used during building and validation - -**world** -`WorldGraph`: the kernel's single scene — shared definitions, nodes with parent-relative -transforms, clash/clearance queries, 2D projection, and scene-level export. - -**export** -- `projection` - 2D projection with hidden line removal (experimental) -- `pdf` - PDF export (native only, experimental) -- `stl` - STL export (bytes, experimental) -- `step` - STEP export (text, experimental) -- `ifc` - IFC export (text, experimental) - -**geometry** -Base geometry utilities and triangle operations. - -**utility** -Helper functions for geometric computations. - -## Build Process - -### Rust to WASM Compilation - -The core is compiled to WebAssembly using `wasm-pack`: - -```bash -cd main/opengeometry -wasm-pack build --target web -``` - -This generates: -- `opengeometry_bg.wasm` - The compiled WebAssembly binary -- `opengeometry.js` - JavaScript bindings -- `opengeometry.d.ts` - TypeScript type definitions - -### TypeScript Wrapper Build - -The Three.js integration layer is bundled using Rollup: - -```bash -npm run build-three -``` - -This creates the user-facing API that wraps WASM calls with Three.js-compatible interfaces. - -### Complete Build - -```bash -npm run build -``` - -This runs: -1. `build-core` - Compiles Rust to WASM -2. `build-three` - Bundles TypeScript wrapper -3. `copy-wasm` - Copies artifacts to dist/ - -## Configuration - -### Cargo.toml - -The library is configured to build both as a WebAssembly module and a native Rust library: - -```toml -[lib] -crate-type = ["cdylib", "rlib"] -``` - -- **cdylib** - C-compatible dynamic library for WASM -- **rlib** - Rust library for native compilation - -### Key Dependencies - -**WASM/Serialization:** -- `wasm-bindgen` - Rust/JavaScript interop -- `serde` - Serialization framework -- `serde-wasm-bindgen` - WASM-specific serialization - -**Math:** -- `openmaths` - Vector and matrix operations - -**Geometry:** -- `earcutr` - Polygon triangulation -- `uuid` - Unique identifiers for entities - -**Export (native only):** -- `printpdf` - PDF generation (requires native compilation) - -## Platform Targets - -### Web (WASM) -Primary target using `target_arch = "wasm32"`: -- Runs in browser via WebAssembly -- Limited to WASM-compatible operations -- No file I/O, no native PDF export - -### Native (CLI/Server) -Secondary target for server-side use: -- Full Rust performance -- File I/O capabilities -- PDF export via `printpdf` -- Configured with `cfg(not(target_arch = "wasm32"))` - -## Performance Characteristics - -- **Rust Core**: Near-native performance, memory-safe -- **WASM Overhead**: Minimal for compute-heavy operations -- **Serialization**: JSON for complex types, typed arrays for vertex data -- **Three.js Integration**: Efficient mesh creation from BREP output - -## Next Steps - - - - Learn about the boundary representation data model - - - Understand multi-entity scene management - - diff --git a/docs/concepts/booleans.mdx b/docs/concepts/booleans.mdx deleted file mode 100644 index 4c0f6d27..00000000 --- a/docs/concepts/booleans.mdx +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Booleans -description: How authoritative analytic boolean operations work in OpenGeometry ---- - -## What booleans do - -Union combines occupied material, intersection retains common material, and subtraction removes the -cutter's occupied material from the host. OpenGeometry applies these operations to strict analytic -BRep v2 solids. - -The model keeps surfaces, curves, trims, edge uses, pcurves, shell membership, and face provenance. -Triangles are generated after the operation for rendering and never become the result's authority. - -## Inputs and results - -Use the binary `booleanUnion`, `booleanIntersection`, and `booleanSubtraction` helpers, or the -corresponding `AnalyticSolid` methods. Every operand must be an `AnalyticSolid`. Public `Cylinder` -and `Sphere` instances satisfy that contract. - -The result is another `AnalyticSolid`. Its report contains contacts, coincident ownership, and -one-to-many source-face mappings. Separate solids that touch only at an edge or point remain -separate closed shells. - -## Tolerances - -The model carries separate geometric, intersection, tessellation, and exchange budgets. Boolean -callers do not override these with a single tolerance. Rebuild an authored solid with the required -accuracy when a different modeling budget is needed. - -Changing render deflection changes triangle density only. It does not change intersections, trims, -classification, or topology. - -## Failure behavior - -The analytic engine does not use a faceted fallback. It returns `AnalyticGeometryError` when: - -- the requested surface-family case is not covered (`coverage_gap`) -- an intersection branch cannot be certified within its numerical budget (`unresolved_intersection`) -- topology or required geometry is invalid -- a resource limit is exhausted - -Unknown point classification is never treated as outside. Invalid input is never routed to an -approximate bridge. - -## Release coverage and explicit limits - -The SSI service dispatches every unordered pair of Plane, Sphere, Cylinder, Cone, and ring Torus. -It uses analytic sections where they can be certified and bounded numerical branches elsewhere. -The boolean topology layer covers the released canonical solids, planar multi-loop extrusions, -closed-loop imprints, periodic winding, two-sided curved cutter bands, cavities, disconnected -results, and deterministic identical-body ownership. - -The following configurations remain explicit release limits and return a structured error: - -- a numerical branch whose conservative UV tube can cross a trim boundary between certified anchors -- a higher-order singularity or tangency that cannot be separated within the intersection budget -- a partial coincident overlap between independently trimmed nonplanar faces outside a canonical fast path -- an arrangement where several open SSI branches cross more than two unrelated trimmed faces and the - available imprint path cannot prove one closed manifold result -- features, clearances, or cap spans at or below the model's geometric budget -- exhaustion of patch visits, branch steps, Newton corrections, or subdivision depth - -These failures preserve the operands and identify `coverage_gap`, `unresolved_intersection`, or -`limit_exceeded`. They never produce a faceted substitute or claim an unverified result. - -## Provenance - -Each result face records its source entity, body, and face key together with its preserved, split, -cut, or coincident role. Subtraction reverses retained cutter faces where required. The report maps -each input face to all corresponding result faces for the completed boolean. - -## Related - -- [Boolean operations API](/api/operations/boolean-operations) -- [Analytic solid](/api/shapes/analytic-solid) -- [Exports](/concepts/exports) diff --git a/docs/concepts/brep.mdx b/docs/concepts/brep.mdx deleted file mode 100644 index 65d21e89..00000000 --- a/docs/concepts/brep.mdx +++ /dev/null @@ -1,291 +0,0 @@ ---- -title: 'Boundary Representation (BREP)' -description: 'Understanding the BREP data structure in OpenGeometry' ---- - -Boundary Representation (BREP) is the core data structure used in OpenGeometry to represent geometric entities. It describes 3D objects by defining their boundaries through vertices, edges, and faces. - -## What is BREP? - -BREP is a method of representing shapes by explicitly defining their boundaries. Instead of storing a solid as a filled volume, BREP stores: - -- **Vertices** - Points in 3D space -- **Edges** - Connectivity between vertices -- **Faces** - Surfaces bounded by edges (with explicit boundary loops) - -This representation is: -- **Exact** - Preserves geometric precision -- **Topology-aware** - Maintains relationships between elements -- **Efficient** - Avoids redundant storage of shared vertices/edges - -## Why BREP? - -OpenGeometry uses BREP because it: - -1. **Supports complex operations** - Boolean operations, offsetting, and extrusion work naturally on boundaries -2. **Maintains precision** - No approximation errors from voxelization or tessellation -3. **Industry standard** - Compatible with CAD file formats like STEP, IGES, and Parasolid -4. **Flexible** - Can represent wireframes, surfaces, and solids with the same structure - -## BREP Body Types - -OpenGeometry can represent different types of geometric bodies: - -- **Solid body** - Has volume (e.g., cube, sphere) -- **Shell body** - Has surface but no volume (e.g., car body) -- **Sheet body** - Has 2D surface (e.g., flat plate) -- **Wireframe body** - Has only edges (e.g., line drawing) -- **Point body** - Single vertex in space - -## Data Structure - -The BREP structure is defined in the Rust core (`main/opengeometry/src/brep/mod.rs` in this repo): - -```rust -pub struct Brep { - pub id: Uuid, - pub vertices: Vec, - pub halfedges: Vec, - pub edges: Vec, - pub loops: Vec, - pub faces: Vec, - pub wires: Vec, - pub shells: Vec, -} -``` - - -IDs (`u32`) in the BREP are array indices. For example, `brep.vertices[vertex_id as usize]` is the -vertex with id `vertex_id`. - - -### Core Components - -#### Vertex - -Defined in `main/opengeometry/src/brep/vertex.rs`, a vertex represents a point in 3D space and may -reference an outgoing half-edge for topology traversal: - -```rust -pub struct Vertex { - pub id: u32, - pub position: Vector3, - pub outgoing_halfedge: Option, -} -``` - -**Example:** -```rust -let v = Vertex::new(0, Vector3::new(1.0, 2.0, 3.0)); -``` - -#### HalfEdge - -Defined in `main/opengeometry/src/brep/halfedge.rs`, a half-edge is the directed topology primitive. -Half-edges are the basis for efficient adjacency queries, loop traversal, and hidden line removal. - -```rust -pub struct HalfEdge { - pub id: u32, - pub from: u32, - pub to: u32, - pub twin: Option, - pub next: Option, - pub prev: Option, - pub edge: u32, - pub face: Option, - pub loop_ref: Option, - pub wire_ref: Option, -} -``` - -Key links: -- `twin` points to the opposite half-edge (when the underlying edge is shared). -- `next` and `prev` walk the boundary of a face loop (or a closed wire). - -#### Edge - -Defined in `main/opengeometry/src/brep/edge.rs`, an edge is an undirected edge that points at one -or two half-edges: - -```rust -pub struct Edge { - pub id: u32, - pub halfedge: u32, - pub twin_halfedge: Option, -} -``` - -The endpoints of an edge come from its referenced half-edge(s). - -#### Face - -Defined in `main/opengeometry/src/brep/face.rs`, a face is bounded by an outer loop and zero or -more inner loops (holes): - -```rust -pub struct Face { - pub id: u32, - pub normal: Vector3, - pub outer_loop: u32, - pub inner_loops: Vec, - pub shell_ref: Option, -} -``` - -**Example:** -```rust -let face = Face::new(0, Vector3::new(0.0, 0.0, 1.0), 0, Vec::new(), None); -``` - -#### Loop - -Defined in `main/opengeometry/src/brep/loop.rs`, a loop is a face boundary (outer boundary or an -inner hole) represented by a half-edge cycle: - -```rust -pub struct Loop { - pub id: u32, - pub halfedge: u32, - pub face: u32, - pub is_hole: bool, -} -``` - -#### Wire - -Defined in `main/opengeometry/src/brep/wire.rs`, a wire is an (optionally closed) polyline stored as -a list of half-edges: - -```rust -pub struct Wire { - pub id: u32, - pub halfedges: Vec, - pub is_closed: bool, -} -``` - -#### Shell - -Defined in `main/opengeometry/src/brep/shell.rs`, a shell groups faces and can be marked as open or -closed: - -```rust -pub struct Shell { - pub id: u32, - pub faces: Vec, - pub is_closed: bool, -} -``` - -## BREP Operations - -The `Brep` struct provides several utility methods. Most callers should construct BReps through -`BrepBuilder` (see below) and treat the resulting BRep as an immutable kernel output. - -### Querying Geometry - -```rust -// Get count of elements -let vertex_count = brep.get_vertex_count(); -let halfedge_count = brep.get_halfedge_count(); -let edge_count = brep.get_edge_count(); -let loop_count = brep.get_loop_count(); -let face_count = brep.get_face_count(); -let wire_count = brep.get_wire_count(); -let shell_count = brep.get_shell_count(); - -// Get vertices for a specific face -let vertices: Vec = brep.get_vertices_by_face_id(0); - -// Get all vertices as flat array -let all_vertices: Vec = brep.get_flattened_vertices(); - -// Get a flat triangle buffer (x, y, z triples) -let triangle_buffer: Vec = brep.get_triangle_vertex_buffer(); - -// Get a flat outline buffer (line segments) -let outline_buffer: Vec = brep.get_outline_vertex_buffer(); -``` - -### Handling Holes - -Faces can contain holes (inner loops): - -```rust -// Get face with holes -let (face_vertices, hole_vertices) = brep.get_vertices_and_holes_by_face_id(0); -// face_vertices: outer boundary -// hole_vertices: Vec of hole boundaries -``` - -If you need to build or modify topology, use `BrepBuilder` (below). You can also clear all geometry -with `brep.clear()`. - -## Example: building a BREP with `BrepBuilder` - -`BrepBuilder` creates consistent half-edge/edge/loop links and validates topology on `build()`: - -```rust -use openmaths::Vector3; -use opengeometry::brep::BrepBuilder; -use uuid::Uuid; - -let mut builder = BrepBuilder::new(Uuid::new_v4()); - -// Add vertices -builder.add_vertices(&[ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(1.0, 0.0, 0.0), - Vector3::new(1.0, 0.0, 1.0), - Vector3::new(0.0, 0.0, 1.0), -]); - -// Add a quad face using vertex indices (the builder creates loops, half-edges, and edges). -builder.add_face(&[0, 1, 2, 3], &[])?; - -let brep = builder.build()?; -``` - -## Serialization - -BREP structures are serializable via `serde`: - -```rust -// Serialize to JSON -let json = serde_json::to_string(&brep)?; - -// Deserialize from JSON -let brep: Brep = serde_json::from_str(&json)?; -``` - -This enables passing BREP data between Rust and JavaScript via WASM. - -## Topology Validation - -`BrepBuilder::build()` calls `brep.validate_topology()` before returning. Exporters can also validate -topology (depending on the export config). - -Valid BREP structures should maintain: - -- **Vertex references** - All referenced vertex IDs exist in vertex list -- **Half-edge symmetry** - `twin`, `next`, and `prev` links are consistent -- **Manifold edges** - An edge has at most two incident faces - -## References - -The BREP implementation is based on: -- [Boundary Representation (Wikipedia)](https://en.wikipedia.org/wiki/Boundary_representation) -- [Doubly Connected Edge List](https://en.wikipedia.org/wiki/Doubly_connected_edge_list) -- [CMU Graphics Lectures](https://15462.courses.cs.cmu.edu/spring2021content/lectures/11_meshes/11_meshes_slides.pdf) - -## Next Steps - - - - Understand how BREP fits in the system architecture - - - Learn how BREP bodies are managed in scenes - - diff --git a/docs/concepts/exports.mdx b/docs/concepts/exports.mdx deleted file mode 100644 index 7d969beb..00000000 --- a/docs/concepts/exports.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Exports -description: Export authoritative analytic BRep v2 models and transient tessellations ---- - -## Analytic and tessellated formats - -Strict BRep v2 solids expose export directly on `AnalyticSolid` and the public analytic wrappers: - -- `exportStep("metre" | "millimetre")` retains analytic geometry and topology. -- `exportIfc()` writes one analytic IFC4 product. -- `prepareIfcExchange()` returns Rust-prepared geometry for semantic IFC assembly. -- `exportStl(deflection)` creates a bounded transient triangle representation. -- `projectTo2DLines(camera, hlr)` projects analytic edges and classifications. - -STEP and IFC read the BRep. STL reads a tessellation generated from the BRep at the requested -deflection. None of these paths rebuilds authority from the Three.js `BufferGeometry`. - -```ts -const step = solid.exportStep("metre"); -const ifc = solid.exportIfc(); -const exchange = solid.prepareIfcExchange(); -const stl = solid.exportStl(0.005); -``` - -## Placement and units - -Authored dimensions are metres. Export applies the complete Three.js world placement once and -supports only positive uniform scale, which preserves the analytic surface families. STEP can emit -metres or millimetres. Prepared IFC bodies are world-space, Z-up, and metres so a downstream -assembler must not transform them again. - -## Errors and budgets - -Exchange and tessellation have separate error budgets. An invalid model, unsupported placement, -unrepresentable entity, exhausted resource limit, or unattainable Float32 STL tolerance produces a -structured error. Export never substitutes a viewport mesh or silently lowers the requested -quality. - -## Scene workflows - -[`WorldGraph`](/api/scene/scene-management) is the kernel's single scene. Its `exportStl`, -`exportStep`, and `exportIfc` write world-placed schema-v1 bodies and refuse analytic definitions; -export analytic solids through their own STEP/STL/IFC methods. For semantic multi-element -IFC, collect `prepareIfcExchange()` bodies under schema `"2.0"`; Floorkit keeps multiple bodies of -one authored element in one `FREEFORM_ANALYTIC.geometries` array. - -## Runtime differences - -Browser/WASM exports return in-memory strings or bytes. Applications create a `Blob`, upload the -data, or persist it themselves. Native-only PDF and file-writing helpers are separate APIs. - -## Related - -- [Projection and hidden-line removal](/api/export/projection) -- [PDF export](/api/export/pdf) -- [STL export](/api/export/stl) -- [STEP export](/api/export/step) -- [IFC export](/api/export/ifc) diff --git a/docs/concepts/operations.mdx b/docs/concepts/operations.mdx deleted file mode 100644 index ba202f77..00000000 --- a/docs/concepts/operations.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Operations -description: How you transform and combine geometry in OpenGeometry ---- - -Operations are how you *modify* or *derive* geometry from other geometry. - -In OpenGeometry you will typically use: - -- **Offset** to create parallel paths and profiles -- **Extrude** to turn a planar profile into a solid -- **Loft** to bridge and cap compatible polygon or coaxial-circle sections -- **Sweep** to move a profile along a path -- **Booleans** to union, intersect, or subtract solids - -This page gives you the mental model and points you to the API reference. - -## Offset - -Use offset operations when you need wall thickness, toolpaths, clearances, or parallel curves. - -In TypeScript, offset is exposed as methods on primitives like `Line`, `Polyline`, `Rectangle`, and -`Curve` (for example `line.getOffset(...)`). - -Go to the API pages: - -- [Offset operation](/api/operations/offset) -- [Line](/api/primitives/line) -- [Polyline](/api/primitives/polyline) -- [Rectangle](/api/primitives/rectangle) -- [Curve](/api/primitives/curve) - -## Extrude - -Extrusion turns a planar profile into a 3D result by pushing it along a direction (currently the Y -axis in the kernel operation). - -In the current Three.js wrapper API, the main entrypoints are: - -- `polygon.extrude(height)` for polygon-to-solid workflows -- `Solid.extrude(source, height, options)` when you already have a face-like B-Rep source - -Go to the API page: - -- [Extrude](/api/operations/extrude) - -## Sweep - -Sweeps generate 3D geometry by moving a profile along a path. This is useful for rails, pipes, -moldings, and architectural trims. - -In the public Three.js layer, the most direct API is usually the `Sweep` shape wrapper: - -```ts -const sweep = new Sweep({ path, profile, capStart: true, capEnd: true }); -``` - -Go to the API pages: - -- [Sweep operation](/api/operations/sweep) -- [Sweep shape (Three.js wrapper)](/api/shapes/sweep) - -## Loft - -Use `lower.loftTo(upper)` or `loftPolygonSections([lower, upper])` for two simple planar polygon -sections with equal vertex counts and planar ruled sides. Reversed winding and shifted start -vertices are aligned automatically. Coaxial circular sections remain available through -`AnalyticSolid`'s `coaxialCircleLoft` specialization. - -Go to the API page: - -- [Polygon loft](/api/operations/loft) - -## Booleans - -Booleans combine solids or cut one solid by another. - -The standalone boolean helpers consume strict analytic BRep v2 solids and return a renderable -`AnalyticSolid` with retained face provenance and analytic exchange support. - -Go to the API and concept pages: - -- [Boolean operations API](/api/operations/boolean-operations) -- [Booleans concept](/concepts/booleans) - -## Next steps - -- If you are exporting results, start with [Exports](/concepts/exports). -- If you want to understand kernel topology, read [BRep](/concepts/brep). -- Browse the hosted demos at [demo.opengeometry.io](https://demo.opengeometry.io/). diff --git a/docs/concepts/primitives-and-shapes.mdx b/docs/concepts/primitives-and-shapes.mdx deleted file mode 100644 index 160040f9..00000000 --- a/docs/concepts/primitives-and-shapes.mdx +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Primitives and Shapes -description: The building blocks you use to model geometry in OpenGeometry ---- - -OpenGeometry exposes two main modeling layers for browser CAD, AEC/BIM, and other geometry-heavy -web tools: - -- **2D primitives** for paths and profiles -- **3D shapes** for solids and surfaces - -If you are new, start by skimming what exists, then jump into the API pages. - -## Before you start - -Initialize OpenGeometry once before you construct `Vector3`, primitives, or shapes: - -```ts -import { OpenGeometry } from "opengeometry"; - -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); -``` - -See [OpenGeometry runtime](/api/core/opengeometry) for setup details. - -## 2D primitives - -Use primitives to draw, offset, and build profiles for shapes and operations. - - - - A single segment between two points. - - - A chain of connected segments. - - - A circular arc (or full circle). - - - A control-point driven curve. - - - A rectangular profile (useful for quick tests). - - - -## 3D shapes - -Shapes are kernel-backed `THREE.Object3D` wrappers, so you can add them directly to a Three.js -scene. Analytic curved shapes contain transient surface and outline children. - - - - A planar polygon (supports holes) with outline support. - - - A generic BRep-backed solid returned by workflows like `polygon.extrude(height)`. - - - A box primitive (good baseline for booleans and exports). - - - An authoritative cylinder or sector with deflection-controlled rendering. - - - An authoritative spherical face with explicit poles. - - - A wedge / prism shape. - - - Sweep a profile along a path. - - - A boolean-cutting volume workflow for architectural openings. - - - -## Next steps - -- Learn about kernel data structures in [BRep](/concepts/brep). -- See boolean workflows in [Booleans](/concepts/booleans) and [Boolean operations API](/api/operations/boolean-operations). -- Browse the hosted demos at [demo.opengeometry.io](https://demo.opengeometry.io/). diff --git a/docs/concepts/scene-graph.mdx b/docs/concepts/scene-graph.mdx deleted file mode 100644 index 9728694c..00000000 --- a/docs/concepts/scene-graph.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: 'Scene Graph' -description: 'How WorldGraph places, shares, and queries geometry inside the kernel' ---- - -OpenGeometry keeps one scene inside the kernel: `WorldGraph`. It is the single place that knows -**where** geometry is, so every spatial question — clash, clearance, 2D projection, export — is -answered from the same transforms. - -## Definitions and nodes - -A **definition** is geometry stored once. A **node** places it: - -``` -room ─┬─ storage-wall ─┬─ cabinet-1 ─┬─ top-panel (definition: cabinet/top-panel) - │ │ └─ door-left (definition: cabinet/door-left) - │ └─ cabinet-2 ─┬─ top-panel (same definitions, different node) - │ └─ door-left - └─ walls ──────── wall-0 (definition: wall-0 body) -``` - -Each node stores its transform **relative to its parent**. A node's world transform is the product -of every transform on the way down from the root, the same model used by IFC -(`IfcLocalPlacement.PlacementRelTo`), USD, and CAD assemblies. Forty identical cabinets store one -set of definitions and forty small nodes. - -## One source of truth - -The graph is live. `setLocal`, `reparent`, and `removeNode` take effect on the next query or -projection; nothing is copied into a separate snapshot. - -When a Three.js scene draws graph content, bind each object with `graph.bind(object, nodeId)`. The -graph then writes that object's matrix. Do not also move the object in Three.js: a bound object -takes its position from the graph only. Objects that are not bound keep ordinary Three.js -behaviour. - -## Transform rules - -Transforms are rigid with a positive uniform scale. Analytic surfaces stay exact under these -similarity transforms; shear, reflection, and non-uniform scale are rejected instead of -approximated. - -## Geometry families - -| Family | Stored with | Clash / clearance | Projection | STL / STEP / IFC | -|---|---|---|---|---| -| Analytic (`AnalyticSolid`, `Cuboid`, `Cylinder`, …) | `define` | yes | yes | analytic exporters on `AnalyticSolid` | -| Schema-v1 (`Polygon`, `Sweep`, `Wedge`, …) | `defineLegacy` | refused (`unresolved` / error) | yes | `WorldGraph.exportStl/Step/Ifc` | - -## Next steps - - - - Methods, query results, and migration from OGSceneManager - - - 2D projection and hidden line removal - - diff --git a/docs/docs.json b/docs/docs.json index 6bf132d6..42caa338 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -1,139 +1,273 @@ { "$schema": "https://mintlify.com/docs.json", - "name": "OpenGeometry", "theme": "almond", "colors": { "primary": "#4460FF", - "light": "#4460FF", - "dark": "#4460FF" + "light": "#7C8FFF", + "dark": "#2A44D6" }, - "navbar": { - "primary": { - "type": "github", - "href": "https://github.com/OpenGeometry-io/OpenGeometry" - } + "contextual": { + "options": ["copy", "view", "chatgpt", "claude", "perplexity", "mcp", "cursor", "vscode"] }, - "footer": { - "socials": { - "github": "https://github.com/OpenGeometry-io/OpenGeometry" + "metadata": { + "timestamp": true + }, + "name": "OpenGeometry", + "description": "OpenGeometry is an open-source CAD kernel for the browser: B-rep solids, booleans, extrude, sweep, revolve and STEP export, in Rust and WebAssembly with a TypeScript SDK for Three.js.", + "seo": { + "indexing": "navigable", + "metatags": { + "og:site_name": "OpenGeometry Docs", + "og:locale": "en_US", + "twitter:card": "summary", + "twitter:site": "@openGeometry" } }, "navigation": { "tabs": [ { "tab": "Documentation", - "global": { - "anchors": [ - { - "anchor": "Blog", - "href": "https://mintlify.com/blog", - "icon": "newspaper" - }, - { - "anchor": "Discord", - "href": "https://discord.gg/9wJpbfgGGA", - "icon": "discord" - }, - { - "anchor": "SDK", - "href": "https://npmjs.com/org/mintlify", - "icon": "npm" - } - ] - }, - "groups": [ + "icon": "book-open", + "pages": [ { - "group": "Introduction", + "group": "Documentation", "pages": [ - "what-is-opengeometry", - "installation", - "quickstart" - ] - }, - { - "group": "Core Concepts", - "pages": [ - "concepts/architecture", - "concepts/primitives-and-shapes", - "concepts/operations", - "concepts/brep", - "concepts/booleans", - "concepts/exports", - "concepts/scene-graph" - ] - }, - { - "group": "Integration", - "pages": [ - "integration/threejs", - "integration/examples" + { + "group": "Get started", + "icon": "rocket", + "expanded": true, + "pages": [ + "opengeometry/what-is-opengeometry", + "opengeometry/installation", + "opengeometry/quickstart", + "opengeometry/agents", + "opengeometry/troubleshooting" + ] + }, + { + "group": "Core concepts", + "icon": "layer-group", + "expanded": false, + "pages": [ + "opengeometry/concepts/architecture", + "opengeometry/concepts/bodies", + "opengeometry/concepts/coordinates-and-planes", + "opengeometry/concepts/display", + "opengeometry/concepts/history", + "opengeometry/concepts/errors" + ] + }, + { + "group": "Guides", + "icon": "route", + "expanded": false, + "pages": [ + { + "group": "Make bodies", + "icon": "cube", + "expanded": true, + "pages": [ + "opengeometry/guides/primitives", + "opengeometry/guides/extrude", + "opengeometry/guides/sweep", + "opengeometry/guides/revolve" + ] + }, + { + "group": "Edit bodies", + "icon": "pen-ruler", + "expanded": false, + "pages": [ + "opengeometry/guides/booleans", + "opengeometry/guides/shell", + "opengeometry/guides/rebuild-and-mirror", + "opengeometry/guides/transforms-and-assemblies" + ] + }, + { + "group": "Read and export", + "icon": "file-export", + "expanded": false, + "pages": [ + "opengeometry/guides/measure-and-validate", + "opengeometry/guides/picking", + "opengeometry/guides/export-step", + "opengeometry/guides/ifc-exchange-body" + ] + }, + { + "group": "2D", + "icon": "vector-square", + "expanded": false, + "pages": ["opengeometry/guides/regions-and-offsets"] + }, + { + "group": "Integrate", + "icon": "plug", + "expanded": false, + "pages": [ + "opengeometry/guides/use-your-threejs-scene", + "opengeometry/guides/run-in-node" + ] + } + ] + }, + "opengeometry/examples", + "opengeometry/migrate-from-2-0", + "opengeometry/changelog" ] } ] }, { "tab": "API Reference", + "icon": "code", "groups": [ { - "group": "Core", - "pages": [ - "api/core/opengeometry" - ] + "group": "API Reference", + "icon": "code", + "pages": ["opengeometry/api/overview"] }, { - "group": "Scene", + "group": "Runtime", + "icon": "power-off", + "expanded": false, "pages": [ - "api/scene/scene-management" + "opengeometry/api/opengeometry", + "opengeometry/api/display", + "opengeometry/api/picking" ] }, { - "group": "2D Primitives", + "group": "Bodies", + "icon": "cube", + "expanded": false, "pages": [ - "api/primitives/line", - "api/primitives/arc", - "api/primitives/elliptical-arc", - "api/primitives/rectangle", - "api/primitives/polyline", - "api/primitives/curve" + "opengeometry/api/body", + "opengeometry/api/wire", + "opengeometry/api/solid", + "opengeometry/api/sheet", + "opengeometry/api/system-assembly" ] }, { - "group": "3D Shapes", - "pages": [ - "api/shapes/polygon", - "api/shapes/solid", - "api/shapes/analytic-solid", - "api/shapes/cylinder", - "api/shapes/cuboid", - "api/shapes/sphere", - "api/shapes/wedge", - "api/shapes/sweep", - "api/shapes/opening" - ] + "group": "History", + "icon": "clock-rotate-left", + "expanded": false, + "pages": ["opengeometry/api/og-mark"] }, { - "group": "Operations", - "pages": [ - "api/operations/extrude", - "api/operations/loft", - "api/operations/offset", - "api/operations/sweep", - "api/operations/triangulate", - "api/operations/boolean-operations" - ] + "group": "Export", + "icon": "file-export", + "expanded": false, + "pages": ["opengeometry/api/export"] }, { - "group": "Export (Experimental)", - "pages": [ - "api/export/projection", - "api/export/stl", - "api/export/ifc", - "api/export/pdf", - "api/export/step" - ] + "group": "2D", + "icon": "vector-square", + "expanded": false, + "pages": ["opengeometry/api/regions", "opengeometry/api/offsets"] + }, + { + "group": "Errors and constants", + "icon": "list-check", + "expanded": false, + "pages": ["opengeometry/api/og-error", "opengeometry/api/constants"] } ] } + ], + "global": { + "anchors": [ + { + "anchor": "npm", + "href": "https://www.npmjs.com/package/opengeometry", + "icon": "npm" + }, + { + "anchor": "GitHub", + "href": "https://github.com/OpenGeometry-io/OpenGeometry", + "icon": "github" + }, + { + "anchor": "Discord", + "href": "https://discord.com/invite/9wJpbfgGGA", + "icon": "discord" + }, + { + "anchor": "llms.txt", + "href": "/llms.txt", + "icon": "file" + } + ] + } + }, + "redirects": [ + { + "source": "/OpenGeometry", + "destination": "/opengeometry/what-is-opengeometry" + }, + { + "source": "/OpenGeometry/:slug*", + "destination": "/opengeometry/what-is-opengeometry" + }, + { + "source": "/opengeometry", + "destination": "/opengeometry/what-is-opengeometry" + }, + { + "source": "/what-is-opengeometry", + "destination": "/opengeometry/what-is-opengeometry" + }, + { + "source": "/installation", + "destination": "/opengeometry/installation" + }, + { + "source": "/quickstart", + "destination": "/opengeometry/quickstart" + }, + { + "source": "/concepts/:slug*", + "destination": "/opengeometry/concepts/architecture" + }, + { + "source": "/integration/threejs", + "destination": "/opengeometry/guides/use-your-threejs-scene" + }, + { + "source": "/integration/examples", + "destination": "/opengeometry/examples" + }, + { + "source": "/api/:slug*", + "destination": "/opengeometry/api/overview" + } + ], + "logo": { + "light": "/logo/logoDark.png", + "dark": "/logo/logoLight.png" + }, + "favicon": "/favicon.svg", + "navbar": { + "links": [ + { + "label": "Website", + "href": "https://opengeometry.io", + "icon": "globe" + } ] + }, + "footer": { + "socials": { + "website": "https://opengeometry.io", + "github": "https://github.com/OpenGeometry-io/OpenGeometry", + "discord": "https://discord.com/invite/9wJpbfgGGA", + "x": "https://x.com/openGeometry", + "linkedin": "https://linkedin.com/company/openGeometry" + } + }, + "icons": { + "library": "fontawesome" } } diff --git a/docs/favicon.svg b/docs/favicon.svg new file mode 100644 index 00000000..b3c55bb0 --- /dev/null +++ b/docs/favicon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/docs/installation.mdx b/docs/installation.mdx deleted file mode 100644 index e5cc5500..00000000 --- a/docs/installation.mdx +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Installation -description: Install OpenGeometry and set up the runtime for browser CAD, AEC/BIM, and geometry-heavy web applications ---- - -## Install OpenGeometry - -Install the OpenGeometry package using your preferred package manager: - - - -```bash npm -npm install opengeometry -``` - -```bash yarn -yarn add opengeometry -``` - -```bash pnpm -pnpm add opengeometry -``` - - - -## Peer Dependencies - -OpenGeometry requires Three.js for 3D rendering. Install it as a peer dependency: - - - -```bash npm -npm install three@^0.168.0 -``` - -```bash yarn -yarn add three@^0.168.0 -``` - -```bash pnpm -pnpm add three@^0.168.0 -``` - - - -## TypeScript Support - -If you're using TypeScript, install the Three.js type definitions: - - - -```bash npm -npm install --save-dev @types/three -``` - -```bash yarn -yarn add --dev @types/three -``` - -```bash pnpm -pnpm add --dev @types/three -``` - - - -OpenGeometry includes built-in TypeScript definitions, so no additional types are needed for the core library. - -## WebAssembly Setup - -OpenGeometry uses WebAssembly for high-performance geometry. You need to do two things: - -1. Serve the `.wasm` file so your app can fetch it. -2. Call `await OpenGeometry.create({ wasmURL })` once before you create `Vector3`, primitives, or shapes. - -### Where the WASM file lives - -When installed from npm, the WASM binary is located at: - -`node_modules/opengeometry/opengeometry_bg.wasm` - -### Vite (recommended) - -Copy the WASM file into your app `public/` folder so it is served at `/opengeometry_bg.wasm`: - -```bash -cp node_modules/opengeometry/opengeometry_bg.wasm public/opengeometry_bg.wasm -``` - -Then initialize OpenGeometry like this: - -```ts -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); -``` - -### Other setups - -As long as the WASM file is served and you pass the correct `wasmURL`, OpenGeometry works. If your -build fingerprints assets, pass the fingerprinted URL. - -## Verify Installation - -Create a simple test file to verify your installation: - -```typescript -import { OpenGeometry, Cuboid, Vector3 } from 'opengeometry'; -import * as THREE from 'three'; - -// Initialize the WASM module once before creating Vector3 or shapes -await OpenGeometry.create({ wasmURL: '/opengeometry_bg.wasm' }); - -// Create a simple test cuboid -const cuboid = new Cuboid({ - center: new Vector3(0, 0, 0), - width: 2, - height: 1, - depth: 1, - color: 0x4460ff -}); - -console.log('OpenGeometry cuboid created:', cuboid); -console.log('OGID:', cuboid.ogid); -``` - - - Call `await OpenGeometry.create(...)` once before constructing `Vector3`, kernel-backed primitives, - and shapes. - - -## Next Steps - -Now that you have OpenGeometry installed, you're ready to create your first 3D geometry: - - - Follow the quickstart guide to create your first 3D shape - diff --git a/docs/integration/examples.mdx b/docs/integration/examples.mdx deleted file mode 100644 index 6ae13456..00000000 --- a/docs/integration/examples.mdx +++ /dev/null @@ -1,173 +0,0 @@ ---- -title: Examples -description: The standalone OpenGeometry example catalog and how the customer-facing demos are structured ---- - -OpenGeometry ships a compact public example set for `opengeometry`. - -The goal is simple: each core demo should be easy to open, easy to read, and small enough to use -as a direct reference when wiring the kernel into your own Three.js scene. - -## Core catalog - -The source of truth for the public Three.js examples lives in the Three.js adapter package under -`main/opengeometry-three/examples-vite/`. - -The current customer-facing catalog includes: - -- Primitives: `line`, `arc`, `curve`, `polyline`, `rectangle` -- Shapes: `cuboid`, `cuboid-placement`, `cylinder`, `opening`, `polygon`, `sphere`, `sweep`, `window-frame-sweep`, `wedge` -- Operations: `boolean-operations`, `polygon-boolean-operations`, `extruded-boolean-operations`, `offset`, `step-export`, `stl-export`, `sweep-path-profile`, `wall-from-offsets`, `editor-modes` - -## Hosted demos - -You can browse the hosted demo index at [demo.opengeometry.io](https://demo.opengeometry.io/). - -The URL paths mirror the `examples-vite/` folder. For example: - -- `examples-vite/primitives/line.html` -> `https://demo.opengeometry.io/primitives/line.html` -- `examples-vite/shapes/polygon.html` -> `https://demo.opengeometry.io/shapes/polygon.html` -- `examples-vite/operations/extruded-boolean-operations.html` -> `https://demo.opengeometry.io/operations/extruded-boolean-operations.html` - -## Example structure - -Each public example page is a standalone HTML file. - -The page contract is intentionally simple: - -- Static title card markup -- Static control panel markup -- One `#app` mount point -- One inline ` - -``` - -## Package names in local examples vs published apps - -In this repository, the example dev/build setup resolves the public package name back to the local -SDK source. In your own application, import from the same published package name: - -```ts -import { OpenGeometry, Cuboid, Polygon, Vector3 } from "opengeometry"; -``` - -## Run the examples locally - -1. Install dependencies in the repository root. - -```bash -npm install -``` - -2. Start the Three.js example dev server. - -```bash -npm --prefix main/opengeometry-three run dev-example-three -``` - -3. Open the served catalog or a direct page such as `/primitives/line.html` or `/shapes/polygon.html`. - -4. Build the catalog for release review when you change examples. - -```bash -npm --prefix main/opengeometry-three run build-example-three -``` - -## Related reading - -- [Three.js integration](/integration/threejs) -- [Polygon](/api/shapes/polygon) -- [Boolean operations](/api/operations/boolean-operations) diff --git a/docs/integration/threejs.mdx b/docs/integration/threejs.mdx deleted file mode 100644 index f322de7d..00000000 --- a/docs/integration/threejs.mdx +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: Three.js Integration -description: How to use OpenGeometry primitives, shapes, solids, and booleans with Three.js for browser CAD and AEC/BIM workflows ---- - -OpenGeometry exposes kernel-backed Three.js wrappers from the public `opengeometry` package. This is -the main browser-side integration layer for web CAD, AEC/BIM, and geometry-heavy Three.js tools. - -## Installation - -```ts -import { - OpenGeometry, - Line, - Arc, - Curve, - Polyline, - Rectangle, - Polygon, - Solid, - Cuboid, - Cylinder, - Sphere, - Sweep, - Wedge, - Opening, - AnalyticSolid, - Vector3, -} from "opengeometry"; -``` - -## Initialization - -Initialize the OpenGeometry runtime once before you construct `Vector3` values or wrappers: - -```ts -await OpenGeometry.create({ - wasmURL: "/opengeometry_bg.wasm", -}); -``` - -## Wrapper model - -### Primitive wrappers - -`Line`, `Arc`, `Curve`, `Polyline`, and `Rectangle` are line-based wrappers. They extend -`THREE.Line` and use `setConfig(...)` plus placement helpers such as `setPlacement(...)`, -`setTranslation(...)`, `setRotation(...)`, and `setScale(...)`. - -### Shape wrappers - -`Cuboid`, `Opening`, `Cylinder`, and `Sphere` are analytic `THREE.Group` wrappers containing a -transient surface mesh and feature outlines. `Polygon`, `Sweep`, and `Wedge` use their explicit -faceted paths. -All wrappers render directly in a Three.js scene; only strict analytic wrappers participate in the -v2 boolean engine. - -### Solid wrapper - -`Solid` is the generic BRep-backed mesh wrapper returned by workflows like: - -```ts -const wall = polygon.extrude(2.8); -``` - -## Common patterns - -### Create once, then update with setConfig - -```ts -const cuboid = new Cuboid({ - center: new Vector3(0, 0.8, 0), - width: 1.5, - height: 1.6, - depth: 1.2, - color: 0x10b981, -}); - -cuboid.setConfig({ - width: 2, - height: 2.2, - depth: 1.4, -}); -``` - -### Use placement helpers for modeling transforms - -For wrapper geometry, prefer the wrapper placement APIs when you want the kernel-backed geometry to -move with the object state: - -```ts -cuboid.setPlacement({ - translation: new Vector3(2, 0, 0), - rotation: new Vector3(0, Math.PI / 4, 0), - scale: new Vector3(1, 1, 1), -}); -``` - -### Use Three.js scene APIs normally - -The wrappers still behave like normal Three.js objects: - -```ts -scene.add(cuboid); -scene.add(line); -``` - -## Examples by wrapper family - -### Polygon and extrusion - -```ts -const polygon = new Polygon({ - vertices: [ - new Vector3(-1, 0, -0.2), - new Vector3(1, 0, -0.2), - new Vector3(1, 0, 0.2), - new Vector3(-1, 0, 0.2), - ], - color: 0x2563eb, -}); - -polygon.outline = true; - -const wall = polygon.extrude(2.8); -wall.outline = true; -scene.add(wall); -``` - -### Cuboid - -```ts -const cuboid = new Cuboid({ - center: new Vector3(0, 0.85, 0), - width: 1.9, - height: 1.7, - depth: 1.2, - color: 0x2563eb, -}); -``` - -### Cylinder - -```ts -const cylinder = new Cylinder({ - center: new Vector3(0, 1, 0), - radius: 0.9, - height: 2, - deflection: 0.01, - color: 0xf97316, -}); -``` - -### Sphere - -```ts -const sphere = new Sphere({ - center: new Vector3(0, 1.1, 0), - radius: 1.1, - deflection: 0.01, - color: 0x0891b2, -}); -``` - -### Sweep - -```ts -const sweep = new Sweep({ - path: [ - new Vector3(-1.4, 0, -1.6), - new Vector3(-0.5, 0.6, -0.5), - new Vector3(0.4, 1.3, 0.8), - new Vector3(1.2, 2.4, 2.1), - ], - profile: [ - new Vector3(-0.4, 0, -0.25), - new Vector3(0.4, 0, -0.25), - new Vector3(0.4, 0, 0.25), - new Vector3(-0.4, 0, 0.25), - ], - color: 0x3b82f6, - capStart: true, - capEnd: true, -}); -``` - -## Booleans - -Booleans require strict analytic BRep v2 operands. Construct flat hosts and cutters with -`AnalyticSolid`; `Cylinder` and `Sphere` already inherit that contract. - -```ts -const wall = new AnalyticSolid({ - kind: "cuboid", - width: 6, - depth: 0.3, - height: 3, - color: 0x9ca3af, -}); -const opening = new AnalyticSolid({ - kind: "cuboid", - width: 1.4, - depth: 0.45, - height: 2, -}); -opening.position.set(0, 0.95, -0.075); - -const cutWall = wall.subtract([opening], { - outline: true, - deflection: 0.005, -}); -``` - -## BRep and freeform access - -Different wrappers expose different BRep helpers. The main patterns are: - -- Parsed BRep object: `getBrep()` or `getBrepData()` -- Serialized BRep JSON: `getBrepSerialized()` or `getLocalBrepSerialized()` -- Freeform conversion: `toFreeform(id?)` - -`Solid` exposes the broadest set of BRep helpers because it is the generic BRep-backed wrapper. - -## Related reading - -- [Examples](/integration/examples) -- [Polygon](/api/shapes/polygon) -- [Solid](/api/shapes/solid) -- [Boolean operations](/api/operations/boolean-operations) diff --git a/docs/llms.txt b/docs/llms.txt new file mode 100644 index 00000000..fe56b947 --- /dev/null +++ b/docs/llms.txt @@ -0,0 +1,96 @@ +# OpenGeometry + +> OpenGeometry is an open-source CAD kernel for the browser: B-rep solids, booleans, extrude, sweep, revolve and STEP export, in Rust and WebAssembly with a TypeScript SDK for Three.js. + +Package: `opengeometry` on npm. These docs describe version 3.0. Check `node_modules/opengeometry/package.json` and `index.d.ts` before you use an example. + +Points and vectors are `[x, y, z]` arrays, units are metres and Y is up. Await `OpenGeometry.create` once before the first body. Code that uses `Cuboid`, `Vector3` or `setPlacement` is written for 2.0 and does not work with 3.0. + +## Get started + +- [What is OpenGeometry?](https://docs.opengeometry.io/opengeometry/what-is-opengeometry.md): An open-source CAD kernel for the browser, written in Rust, compiled to WebAssembly, with a TypeScript SDK for Three.js. +- [Installation](https://docs.opengeometry.io/opengeometry/installation.md): Install opengeometry and three, and serve the WebAssembly kernel and the display worker. +- [Quickstart](https://docs.opengeometry.io/opengeometry/quickstart.md): Make a Vite app, cut a door opening into a wall, show it in Three.js and export it as STEP. +- [Use a coding agent](https://docs.opengeometry.io/opengeometry/agents.md): Give a coding assistant the OpenGeometry 3.0 rules it gets wrong most often, and the sources it can trust. +- [Troubleshooting](https://docs.opengeometry.io/opengeometry/troubleshooting.md): The common problems when you start with OpenGeometry 3.0, what causes them and how to fix them. + +## Core concepts + +- [Architecture](https://docs.opengeometry.io/opengeometry/concepts/architecture.md): How the Rust kernel, the TypeScript SDK, the display worker and your Three.js scene fit together. +- [Bodies](https://docs.opengeometry.io/opengeometry/concepts/bodies.md): Wires, sheets and solids, the shapes they hold, and the difference between a copy and an instance. +- [Coordinates and planes](https://docs.opengeometry.io/opengeometry/concepts/coordinates-and-planes.md): Units, axes, the plane option of a primitive, and where a profile point lands in the world. +- [Display](https://docs.opengeometry.io/opengeometry/concepts/display.md): How a body gets its mesh, level of detail, smooth edges, appearance, and when to call flush or settled. +- [History](https://docs.opengeometry.io/opengeometry/concepts/history.md): Undo a group of edits with a mark, and run edits as a transaction that rolls back if it throws. +- [Errors and limits](https://docs.opengeometry.io/opengeometry/concepts/errors.md): The OGError codes, the events the runtime sends, what a fatal error means, and the limits of 3.0. + +## Guides / Make bodies + +- [Primitives](https://docs.opengeometry.io/opengeometry/guides/primitives.md): Make wires and solids from parameters, on the default plane or on a plane of your own. +- [Extrude](https://docs.opengeometry.io/opengeometry/guides/extrude.md): Raise a closed wire along its plane normal into a solid, with holes. +- [Sweep](https://docs.opengeometry.io/opengeometry/guides/sweep.md): Move a profile along a path of lines and arcs into a solid, an open sheet, or a closed ring. +- [Revolve](https://docs.opengeometry.io/opengeometry/guides/revolve.md): Turn a closed line-and-arc profile a full turn about an axis in its plane. + +## Guides / Edit bodies + +- [Booleans](https://docs.opengeometry.io/opengeometry/guides/booleans.md): Subtract, unite and intersect solids, read the boolean report, and handle refused cuts. +- [Shell](https://docs.opengeometry.io/opengeometry/guides/shell.md): Hollow a solid in place, with walls of one thickness inside every face. +- [Rebuild and mirror](https://docs.opengeometry.io/opengeometry/guides/rebuild-and-mirror.md): Give a body new parameters in place, or rebuild it as its reflection across a plane. +- [Transforms and assemblies](https://docs.opengeometry.io/opengeometry/guides/transforms-and-assemblies.md): Move, turn, scale and place bodies, group them in assemblies, and make copies and instances. + +## Guides / Read and export + +- [Measure and validate](https://docs.opengeometry.io/opengeometry/guides/measure-and-validate.md): Read volume and area within a stated error bound, classify points, read bounds and the B-rep, and check that a body is valid. +- [Picking](https://docs.opengeometry.io/opengeometry/guides/picking.md): Turn a Three.js raycast hit into a body, a face and an edge of the kernel. +- [Export STEP](https://docs.opengeometry.io/opengeometry/guides/export-step.md): Write bodies and assemblies to a STEP file in millimetres or metres, with Y or Z up, and read the export report. +- [IFC exchange body](https://docs.opengeometry.io/opengeometry/guides/ifc-exchange-body.md): Read a solid's exact geometry as an IFC exchange body, in world metres with Z up, for your IFC writer. + +## Guides / 2D + +- [Regions and offsets](https://docs.opengeometry.io/opengeometry/guides/regions-and-offsets.md): 2D booleans on point and line-and-arc regions, exact insets with one distance per edge, and polyline strokes. + +## Guides / Integrate + +- [Use your Three.js scene](https://docs.opengeometry.io/opengeometry/guides/use-your-threejs-scene.md): Put bodies in your own scene, connect your camera for level of detail, and draw bodies through your own instanced or batched layers. +- [Run in Node](https://docs.opengeometry.io/opengeometry/guides/run-in-node.md): Load the kernel in Node, mesh bodies without a renderer, and write STEP files from a script or a test. + +## Documentation + +- [Examples](https://docs.opengeometry.io/opengeometry/examples.md): Runnable example pages for OpenGeometry 3.0, and how to run them from a clone of the repository. +- [Migrate from 2.0](https://docs.opengeometry.io/opengeometry/migrate-from-2-0.md): What changed between OpenGeometry 2.0 and 3.0, and where the full step-by-step guide is. +- [Changelog](https://docs.opengeometry.io/opengeometry/changelog.md): What changed in each OpenGeometry release, newest first. + +## API Reference / API Reference + +- [API reference](https://docs.opengeometry.io/opengeometry/api/overview.md): Every export of the opengeometry 3.0 package, and the page that describes it. + +## API Reference / Runtime + +- [OpenGeometry](https://docs.opengeometry.io/opengeometry/api/opengeometry.md): The runtime statics - start the kernel, listen to events, reset, history, export and the 2D calls. +- [Display](https://docs.opengeometry.io/opengeometry/api/display.md): The statics that control display meshes, level of detail and host-drawn bodies, and the HostGroup type. +- [Picking](https://docs.opengeometry.io/opengeometry/api/picking.md): resolveHit turns a Three.js raycast hit into a body, a face and an edge. + +## API Reference / Bodies + +- [Body methods](https://docs.opengeometry.io/opengeometry/api/body.md): The methods and fields that Wire, Solid and Sheet share, with the types Measure, Validity, MirrorPlane, PointClassification and BodyEventMap. +- [Wire](https://docs.opengeometry.io/opengeometry/api/wire.md): A body of lines and arcs, open or closed, with no faces. +- [Solid](https://docs.opengeometry.io/opengeometry/api/solid.md): A body of closed faces around a volume, with booleans, shell and the boolean report. +- [Sheet](https://docs.opengeometry.io/opengeometry/api/sheet.md): A body of faces that enclose no volume, made by an open-ended sweep. +- [SystemAssembly](https://docs.opengeometry.io/opengeometry/api/system-assembly.md): A node that groups bodies and other assemblies, with its own placement. + +## API Reference / History + +- [OGMark](https://docs.opengeometry.io/opengeometry/api/og-mark.md): A point in the document's history that you can roll back to. + +## API Reference / Export + +- [Export](https://docs.opengeometry.io/opengeometry/api/export.md): exportStep writes STEP files; exportIfcBody returns the IFC exchange body of a solid, with the types AnalyticExchangeBodyV2 and IfcPreparedValue. + +## API Reference / 2D + +- [Regions](https://docs.opengeometry.io/opengeometry/api/regions.md): 2D region booleans and the curved inset, with the types OffsetRegion, CurvedRegion2D and CurvedRegionEdge. +- [Offsets](https://docs.opengeometry.io/opengeometry/api/offsets.md): Variable insets of point and curved rings, polyline strokes and one-sided offsets, with the types OffsetHole, OffsetPath2D and OffsetPolylineOptions. + +## API Reference / Errors and constants + +- [OGError](https://docs.opengeometry.io/opengeometry/api/og-error.md): The error class every call throws, with the types ErrorDetails and OperateErrorDetails. +- [Constants](https://docs.opengeometry.io/opengeometry/api/constants.md): The kind constants for primitives, operations and transforms, the typed parameter helpers and their types, and the region tolerance. diff --git a/docs/logo/logoDark.png b/docs/logo/logoDark.png new file mode 100644 index 0000000000000000000000000000000000000000..80407b69d11787fc41f03f8c9f9d9ce412ec6311 GIT binary patch literal 7980 zcmdscgO)IN4jEE{pp+mmkQgB85F{i9(#=4?0i&fHtJbv0IPT9NDmyScu$?Dl0e0V3)31+b(0^dxoPoHe{}bOg45j|+@j0Qj zwN>iUOW}J>{iDH&gVTy%>CHz76fTPM>ddn}{pt*Rb>{Z>a4dVPw|lU?YNgvo!nI+h zIZM}Gjy=9GRO{e|zn`7I#l-&d{s%=Kb3atr>dWrIski%lmOKdK>vO`d_AKrz^R|mq z)+3~La8Tah0~9x1Z3%!3SYj>dGybx6swwhI)77phYJ0sFMMz!Oxm&#XoQK7fiKgsL zBp$nBUWe5$7B;q)&$zi8%gSC*H@t&59$nvkuf%h*jNbd|*){x!L-P#v`PiuKFsym_iHe7jo`(uu&a0XF z&^5lkzCMYNWghh)&0`ccsy?d2k5k2X?8QR8{+u0dJR?J?Qm9Fc1g~smWo0G8H!nLo z53gVpd2H%UN4U#1@v@7i-`9K?PQgf~Z6~v}In4|mh97XA#}yxNh-W%#Qa;A*Edm1W z(rN%{`aIFrJlp}U-NrzB=ol-p z=fnVG&J|tB(OG*guNUSh$e$;g4&vaQAGczs`pAd5Jv}+ew#q?p4HXo6igI}Yd8f#> z6n3FE>IH*Vw>u_V#l%8mIznM-IdRRQaGmA2PFv-CJsv6l-%jfkg^d*XAr3$BBk&hY zPwM`xM_I*$L8(H(P9U?3HgBI3G`O_gMro8QlIIH;qXo|_-mMl_z_UrG%3Kf3yARHt zkQe@8|5~^=Z7Lxl_CgF;0@~zrDjv6cA6#}X)_p$ZQS)7geDWNcS{-E}ihOF}BSzHi zyXG=lZD+>!&j;Ey=dQGsYpdJf+`zTWn9{z`Xlb2f6Qg`($@T*oAg3C~&M%65@1fFF zEbb5YP_}bgcfOEs% z<_-MFDLt&nXKPw&#__sJ%qWrU?UhAO&3{>8Gb)u>tZrH3XlcEYJ<$@$#$GG#tnJJH zf)um3w^WKYK!;Q4hJpU**7zZl=*FYQ`92;i`FviSW5nA#~tr@8MrV=~TY}wdtA4Xj(b8Qd;oow&{0@pZVJl*77t-%A#ypkg;TXIIq zE6CqH@oiYO=Z8LK1K&)2+^?SeX?h6?SEb&01sY-K9#+bU-De>zwg!AKq|7q0%ouOasPlLZjUCFSgM%@>t#S?13$$}NU!}c&0#h2Kv7;$FBnsKsT=-) zVsUs?CsAI9+t^@Lta!FTyY=}M z1>cxjvT%W^F--SMpRVz%bn%!dag{8|62ns0h$V1baf~pOEf4!aUkG2L;zh3xS7Qdp z>D%iRr#Kn&G7E^m7GiD@VrKI3ll2o*lt(Wf-?n5_FP1M$5sPgx>t*61jxsX2rSoV1 zv^m^BDoD>RJhE!X`#h+D&f4%nJym{uJdOOP@)(45xtd=DBDnN#C-^%2cgPUr=n|WE zP(Aj<)zp_=oo8*7^v&JD{qs$c(t-1^mZS|@S%b2tUz{0WMze!`0q&3p^ zH-V_{zdq2bOuGHC|-faf}&29;2Yu9}LsR*|7#j z^A7I+bI9mi!~Y}zy`xmW7mKPgY=9ZKPX4fU``+eq@HWc&Lk zZ}n`7T) zp=?rbvljWo89dmXORxg`%&_hz1LI$lx8q({A^9TNLPl$oIj?*%0)9!4?~69SJCA3x z+6}u@?}#uzb$J)h&!7o1Tw-bwFum0(Qp_pvij*~Zx_?2lZj*SABI?%*af7ghFFUFZ zcoJ5t${eND4H)BMn@UsAWq^CN$!oDiPfiS9liOJGGMF?ZR{JAzrA=i7L(#UA-&oCU zy#(tC;>(ph3eZ}-(!`Pqjl;7D%cQjoZ-QKB{v^E!N|%5q0hDJP5=@wD_J~kI)=c{J~0vM>^Wp9>46*eU>&RZQ!S| z5Se8pFdM^3QDWROV7_O{OUCoGjyH1HA?2$}P#EMvHWg%(uacB@8z?ja?z;2%zc%qc zz}H3pj!wM(<9y}FJS@j>sdu>Y4R8}dMs4oMH#Dq_szf%C7cz6vB;;YITSgoGGhx}w z@1!(?O2`oDqfz!LuY;zPFIR4^r-J~8F_eDdwO*pbGw5@be(~tHkJY zRj>5%mhyE}eAD|!7!hCBlzsZ8PvG+AI1_-o!U)x4kt*7ZapgGTJXLF^-7OngjMM`5 zZ~H+Ob$tuvyuNLBeR(q%;_PhXmQn%1)ZA?rUDW4#SYUl~uZdJp!_FdZ^)U@P>Q=d2 zfY}0V*MCsCxtpgin7e3(MIbbvFtIP;8oFEZt-Nd@O2&AP$IPP58H_iaH4^H-Soi^! z%WNBYoxm3DL9GIdEcGP`nKf#Lk+(wf;rD0hr7(Ms=<17gkV_^#;-nZ(6yb=!W>T~n z9IQ;!l-N(U`0HwzEp0z!=Of;&mrS>ASD}mv3zh$U~D}2t?Xuf^Du)QDzv#2 ziF_ky3KnIF)sLNi`}s86^1lawwU|~v@t5Dl;LUD=9N=BTU+Ywb(+2 zFg0a;*;itt6-DgB7P~eJqHlUMx!v`MU6TW&B#O3d$PD$qSiS3P$Ogbne<1T0&|^Et z6|);!r+4&n6tgJI&#W+&wYOM`BcuWqv_YMuj={n00wfOjdQlINA~~QF-}uHu_3vVR zllL;L35Z#a;pl{^1jg(P&HP-j+m^CDRD_*@BIOs4zBE{;J zBn<~63try?VLh+;a<5cqr9qVWP$u8HjZDNB+F~VCRX1> zYa$}h=VkcegL?BW@|_5v=BIPz#;h+Nxq<8{Ii*3~9ekxS<4U=p1qb#Md}Oai^+ua-E9 zmze`&G7*ToL!9w*QD3W-HNlvWKMro+X#x7dAVxq38ITgN07QcT9%v{K&`4wim{U~K zl^if^={Klpl(79I|G?L`q3~4^GWU*MkPj2m(`QHt0RRU0-lSO+jjmCde=os=+##N( z@FksG&fvqe9wi{9L-eCmD3t+kglrXa0g>s?NyWdNIZ8b}?DHqGZZ@ zsSczt;MFOxJqz?D!>-A!!U2+@K>!pl31qk?8G7ulQQ|N~@^g3<1=|2lOh$nuHAM6^ z@(-X+^`=jSc${GaL~(sUBx*$vm7~zG&8>Z2Acb>-9tK7HFf74jD+EfX0*;Q3nt%=2 zG~an%k}QnM4s9rm4J#A5H(&#Ha82k|#Oo|_N{EHV2iR#7aKeX6=-;u!vQ5DelbmI9 zjEy~iOmeRdkXNaoB*Ta?rbhJ$(3qtcvtjPA`<<;!!~usxxE0T%Fwn@=RS-sL*F_pp z)mhCq9Rib~!WBM2?u$v%ESzMW0 zxnqS+S@Dn7j5`Klmq`RX0B{lNi!s^$`@NyvrY!QB=rSo$+VDAvJsnVHf_K( zZi9N(iTo;(Oh0QVxvmo^G-gG*0c(?(1dKf!Lf>Gjv9njXSbVOr_ZG*cuheNdkw>~# zo#MVlOz{-Z_Pkj65GS%=3vwEWYbBW`+#<(@t6%1S4IPWge&m0jwmKo-jcWFcc%w%k zA-TG~u@gxBJTu=reHDUi*S>Fw3;+M#CVywrss09V&_n~c&i8HO;VW zT`}nig5*luv}QkevoKxn+}^+6a$u(6km}PtUIG$pRq6}=q&IsX1bauQxi}RMG`k%= zTvO}4h2szDwi#w>OpOJ7-UfVR*M=AXHAUVhhI<+>qy^PbAqga^jQe4BDgTTz8TxzP zB?;+*%lu(|!2vT)@!WZA0CbdO-*O5R?MsQokt#7ZN^-w!zBTF#t+DZY_z{%k*f8^$ z5=vS!v2*-f)=%sEWgY-#xJj2X3>31O(IqO*Hl_JTS8|B+@u>B)L8|^~-@L-DF^f`2 zPPuDu9Tz5BI5O!Y*+}R0-PtNCD(j6HIE3)qOJZNN9nM9K7V|~>sCsxt6 zT{P1#IJ5!MK;6`(WEvR?ax74YO^M^>(-P3%|C-}6xFPTRkS-cusuKZVC7T=IqO>m7;5m58<8d*A2mW%mi|%1- zXP!+Xn!%$Z&$oM{C6&x@A(_J^Yn@NmeK#tZ1CUc^Aye-3Zc*P3ZCh8*;#KDn|6u#I zsWphxqiD-&wRi*?aI`rE|H3VTFfue=(E2MB_d6UQ@CdF^I0BVBA+0l2X8nA8e0GsnW3+1;ftb)!m6x`-woJr-sH3PqGOcf$Mn_J6(3sU{5H-qZj>V= zy2VJN#|X?^Bm?3i$Cbz@Fz*#KN|7NJppP=rxVbAzAPYg%K6S=FimoyCcC2r7$uN)!&h+%$=7U@NydpmT}4LmHf z>1y-DZ_t81;fM2IWqn?{k9iU<;W0Wf&gJ(GNvwf0aebnmKU~4gwqC8bf{cmmZ zQpdUU71P81)A&pSVM26t-aJok0P;((m^j=vH!PE7Ku+M{ ziNwUAf~jA}>D0zbOjNC* z&U>o0q1TG-%qOb5pSY_$$D;O%6VXmxSs$TH$ zL&(A)GkH;)2&Hz7ik$6+CZk`DRt^(asr`oLrXKL>>kGO$I$eeMd=bdgS%)3%H_oN0 zBg_>kL=^M2c;CeS$pn{&=6v70j_cQRqa-XQ4lAHjb2qki(zW+L)PRM3+0&L2HZQ;d zQa?)kzH14(vi<5TUFmH2ZTa+u<|E%f1f`AZiK}Z%ijU`b+x>JUlVJMuCemz|An6}L zVp55(zi$^iPhe^GAGM1nIz}ArvbLX)<&2Ab+>*~|iwz>6h1W8UanICAOA?pNd^L#9 zb#~Mv`bCoy#oXu-q4Jh*aZg*H0;*K)J5V;>=A#=}>S-CY#?ys{eIv;c>W$Fi zP5SZoeav@uhCtnvbDG&-cjfAxrns5{4xJkCPAIIUZvk-p%c#|?ZM&iQ|HB9TUkoG3 zRYZE4EAs;wyEev%dWz43#6=p1>Z@4b72=*$nEGl=z4wdl{#bgHRn0P2`H=jcSYS2I zaX#-QF}W?oF^}+)rzX8$|DCq=o>5h~AiT*zi|ze1d6Fli77izQcRZ~ybb*3DAFF9? z%gzAn(H88lF`d4vdso9MoY4?pCw@Pk67pLx}P!PAdGA{Fp-X~5x~l<#8{f^==Dr>BP$<<(%^7ploKQ!bIZ zL%cFuTippkb&VH(&Oq5*_pfF|HCJ$K>>*G3%dVyV*s;8#+qG~{Y`Z6(;7#2^aAm>c~zm_<71Yew3_n~_G*SO3O=ii5hTKZ zM4V7bbM8!=IDGWC%l2O*^L2c4RT6nQdD2WW`!UM`-! zf4s_UVyt3S&YDHsin6e13*t$6ebL)qasF!&tBhmxAUjp91F7O zayFhQrd8R<7ye$F(N$Uhb3AKs#rf>~dBA?G?&+>OnNc^)z2|Hy%`!ZT*3dm*m7%H z22zIyH2Y%b@4r2rWnKUK?c2Ai7&F(F1S1`93&cpw8n!B@Zubh-c8Bf-@ zc3}LHT0-Fo-jK}Aqb-F_&z`ea<=4;nR0I`>k3O5aWleKq89!g5P^7q-*M0?`3pIrE z5_^5kpZ|Nc3YJVU{T>of*-y%V^F-$H=3lc|n&Sf1M-sG&U^1VyI#y3wYi{(g$j@nR zE`!Br$QW4?I#9;O*AP{q(8?#}w!?J;qZq8l3|9gf#&bQ>KQp-}T#VdlpjPUE^Dv=W zhJ2SNxsliqvGuCZZ)u%A9)!chS>(O#2a>}ptSlAF1L^ zro#`(PENvVyQ?|hg>yBDwnneWYR`MvY$sl^5!+@4H)JtPwLJdRnany*>b@Sf>&OkH z49>U4r%%6icRsr8BmGr;>5FLq literal 0 HcmV?d00001 diff --git a/docs/logo/logoLight.png b/docs/logo/logoLight.png new file mode 100644 index 0000000000000000000000000000000000000000..cf79d3ef3887d52fb2f4669f4b5ee7a441bd1138 GIT binary patch literal 7101 zcmd5>i9gieyO$+VLy{6{NQp_AEZMSFjAdxX78(p$``V3(3}1v6TN%3$W6Vs9?95n_ zqDaQR4H9AuL)Pqf`rUh9_g}c5*Xz7KpYuNFJm)#j=Q-y*%kz6?h5&vsehv-}fDz;l zoP*;C?r%AEl#PU&!c^EVK0kdyR}{$Vbx4x^Zfte zX@7rAmO{42r<*V+4;=PiZYQ{6E)}hCZ^wJ7IhVudp)ij?Mk=j&$U^J^Y2D(DD>4GCwdA) zgyDEP8PB{@9&y{QE$B^~9;E1BjfBh&3!k%nb;Y!8qtI!G1m!S?FF(uuo2i-0b>^>h z#meDFW;r@UXdt|VZg-{0&`ku|`KO2_`QIj}0&yqg$-td`**NESRrB)Z)pY5$XUL4Ga zYr{#}6{RP&X2XDHy(mqdKBE(h8plZZo5yfRQoUrGr4RtSa-*TrEbo~jF+~=@7VAG` zpe-M%%+VK6_&x#ix$3#}jccm>^)Y+F{CFr$GqS(%^d08oewEK^i@m6|TP^Do6nk_V z#7MM;ci3wR9^R9DhA&%mr{K5W3Pc9onY|N}7sn#1kLRmtxPtW0gfKa7wcYzc&84u3G?a#1Y%?b?p(p9_CDq+LDS zDP0X!7ZcoUHt!2K+*H`=3tG8oX;Nk&*_gk6G#fn{ajK8_BB1Uc7odiFQp^P4H*P?2 zKje(*yJ4NE#^?DvdqYBptaQ>vhg>hlEFW%8);BH0_v?me*?C2EzotaYu{ViRdZ?m~ zj+Uwy7)WWsm5|c;vSpknrJL*fWg8RUJ7F`w7rL(`=Snq7{Zei1cFvIq8XM-lXSeZK zR5zvWoUx6I&!rH}O(ZJlaPAP#^Rbzx*ZzCPOAb2K=)%7|!rg0uZHqB?zQxwzN<)6O9h=RfmacE$KIZ`(SAsOwx89v`g^jwlny+MxvsI3ep?O! z#5CFFa0~L`Ji;42#CHw7cHe3hw*!+s8lM^5w*k2UAq*&}>}>ULZ)3uKAiAanHtY2# z1sb+F*%Z)wwCkktjcHx4Kk^jl;?;t_AM<1~)nrmFI{D_ChI9Vj-@61VPv9!Z$wMzm zi!LE|vxjZ&Q1f5pk*Tv=o^)zWo5X>n4#$fAr`hQXA3e^J3MTlZ@m>O{y_fz15G!R4jjNZ6d)U@ENxcX z?;uAt(q3R*#DR;xOnIy_Z7n{4qp{2%sYX=XdH-lj-I|u3)HG~5J(J$U3+FGqWwn+) zKXl!+2LOucnI#|k$H^3_u3kl}PDecKA`~wQT#)W5zBT{RL$_$Ddf7iN4RbRlc%{5d zYF4$#b^QvO##b1b>MnMT>oH*wCbl0})pHc?={#Rqxe&}>u%)7K;+^u1c|vsi%(l=me-cNoO8SN0zW03&YvG0T5AOwzx;G2ubZR>O(^eT0aXPYpjc=k@E}qOC9T=sW z(>-i<6xfMHI9i~nL5;%7Q`yR_kH;JkO%Y9F%@K+EYa(z`qIJ0=jqH8)X5&riQt{G) zJpVX#(a-(kq9C01=9`%SYf+Vl$Y!DQ(5Ae$l|3Aui`Y)4Jo-qGpe+2TTiwUvKV(nR zCl|4Z5suw4LbpR!4Y%EvF3h}&#znbn->_T28>YrA*JUdyr*MNBsucG<8h z<-E*AVCMjR>Rp#5M9a!Bq`61NBX;3fY@eO@V-pehlKEG0WdDT$p%cZ`H&`i3vV?l<_Lf3 z4*n=sJz*D?vG3r$1UyH0=|Fv}8)O37Z( zv45i6*em_r!GvJU#x_ntim2o^N06%0eH|}LM(+&-@ALq(3gO5eUEwRPY=V}Ecg!0P z#_;rl7HHpSHC7yjgL4}2jlUDu)9u@SzriyoefdVqrPR)wtsgHv=-3Ke&rjm_6hYAi zvIdBWPKrB}yxn6sJMZSKbEEiiaeQI=Zhew23AV7bsO9BQCcf}5sZGb#rhI(Yj3&P{ z0akB3Ut`A>LMjQ*9K~xyF^J)gLjpLlwM6z^J$}<8b3-~KcVTNo^eV0_YLJ-h6xwDl zmAY@JGALv^q*AhI^FExrFVK^1{lZ{f{GR7f!zaex1OJJQ`5M}|8jj0~ta>p`T@H%< zRmzz`BJ~BUa51jZ7&Rmgh@=*al2yusBKZGT0$s;uGNN!zW?o%AllMoJNJvQ)EEHY^Q%+iabyK|4Lezk^K)=wG= zL8^R_bmYx5()^b=9(%eFlhgG2G(=8)`&v@Gc;2K>JCa+ehwqZum1HOF@UtTQ$8cg1 z_agi2?iK;>Yy0qQQ_<#EZZc(=M2oY=u$M0?3l@^xNl zr6Aw0>1t!8i|n?_*nTyOU@%Z8o}fSa`S&#{S=bmrl}&cKdBKu0c^0O}pL9KOxx=|! z4Uo0LqIA@8C2Tua5?)JGCkn9p+ZuY&^;5Z1Y}T~PL?9}lOjlYJ`FkA~fMFmCQMqZ< zB%<8)>wZR4P+o+@-~VdI1GSK9Sx+ecI~k+uQO=-mMvNEmR=cH?tC+ahCWW6*rtFu@ zA5dh~efi+2Pq8E01NhN8F7LVsbfqXF25W1Wb;atGsm;JH)lG6>{?lVk4?CN3E?&{W zg4KPk8h!?R2-TTyTgKM@3b>?qVF6pK6Ew(2yD0azdC!QNEt!paMOv1ZBSn-=T)0fF z2V!GO++wf;e_HJgz4AOY|85}Ek}gHKJ$>kvwO*%Jye7EhzxUKP4fvQP1gtf%%mj5; zsbNW(5ih27exuR{3E}6Jnd7Kbf8JRCL$(ob2(w+{mwUG=%fB?)WpTMBXgxq@O9)c^ zOJYc`vqbuT>tlr5wTRX;o6;>0*HJn)j<-8NrP8j;xN4j??Gh6L4&Qz?i&ot)8QFqK zxz-jYTG2|#6LnnsBL?O>{J0dtbZfrt%g||obzHY#8iohXq7nRa;-M9QC-;2mk>NAJ z%iim_bX{ZSE%r%ho!-{2mr|4cc|XQSQ?#_nU44g?TmkJbH@12mvu1$WXpWszIc=gm8j6v{aJxr00H_XdM3T`0S>=z_<+I`5jengL)7RPA@Khxd0 zw9vyjLEvTIIBEsQxyH*HdEuTu!v+#pt>D=Kfw$HCMB1Eo-*q{k@9;6uBH@Au z&ZB=EJHr+Hd2^!Q5APg!``76e15clSg8>8I{M-m^q1S)e_oRWk05r0m`;FKWxCRgF zN4yc?pX&R>#n$s#bzF0P$RDVQ7Ea>oSHMWSnXgAuig-Shec>osDz#=xUB#8SJwggd zTfw6phByVf>S?-tJ^5@i5{Ky5vX-$i>dcp$waA!$nlE(C(r|>vmco-)_R+Vql~r}6 z?Ffk#EnLJZci+O?2HRi><)T|L0pcI>?TCpLXF#};V2#5E(YI6n!Nx>Z!zEmy+;BlF zxPY_;IstaM<-Hv#vBDaJTeRy(saP4=MB^Wn=&(LmR9Q;6c5%ZQb?+K=W-Tnx-e2>+ zpV_>uw`}(=u_6tGlV27m)xXq<>v7k!2zQL2N48g4vuX3d)f?XiYp!&Z>wC*3;b}(& z_UlLNP*_0l=vE(Au6h#p=-kGP>W8q4e>`bV2Po9_P_ZpCtFCnsfGOCjth(unw!S=Y z{W8#O+}7O7kodYP@;0Vx!oAB1;tszbmg!&(8#3bmuodmbHkV!L$h2PZ15Z*S`A%Wh zyJUg&9)TSD7A<6r)aZw|xyOZ|5gfiZla0k61B+$>yD6ivGj`DNmftEPU;GFoa@3OI zqjBxqTM5N$sF=1(WaxHusG~89 zFx%MgRJWNxmd2BmA9Oe>=v|KZNW(8KV%;k;q93iEGee7C?yFPSIfu@`g&j7OM;xAy zfpNo=EYP;vUt7NZ0Dw`vbDIZW!;>auAJNkLT> z_*pNkHt~6;rDSUGV#Do_v-|dK;RsKObrA65j-+ble1pr;4!()PThFIL@YYh*Cyn!d zMcZoG5FORA*N<_fyp=H-LL zcF81H#Olk9eLk33@xGUO&-tHUq6Q-~Y)?-`5rcL+w~H~s{{|^x+B3eX#8fn>c zrOKiuE|UpYGC&%~i~I_>0G(IBe_KcX(|V;R5p@htT7@3uH~PmZUGe><#vWKIrDYVl z*8IxBj()YuXvq7KX?uEG*aq+*Fl;mL;E5VES_Y^3(;lt*l6fPrQV>@%b+4nQTo4cS zyY88@CLEz-Is`i0DTBXRA3}4+ZuVd=Ncpp)cCxHeKb*zW1H*7>5r zxTfvvKhHMD|JfTlVl~UlYpM-RS3*;KEeBJe~DKE>dxp9Qoiq_r11cAUY?d7S^k>$y8HK%P`?%u$7 zKmKJ;wls)kt4vW4VKq{cw|i`ML)MD+@^9anG?wyRbnEHyH9p)~%L~xl;+3=;fbCyu z35HS|D?_)Hjj%MwHf_Ifc$3536V2xHYt7^4Q^d5#JX;YEi=e|mm(I4AryvS%!)el>k4#9H9X@V4 ze^NmNDX>FyQGC`W4IBff6eJ_=Q;Ggl1IKVS$|+vY+X-opV^dTutR9xm5Afjv;n%v@ zs8W42*+g&VQw%%sXQ=oQV{$$cV^W!R^{qV-v~$NQ=sYLmndx*_@7G_KeD+t(N;Idn zuUt7Rt=(JY_kfcab=tHZv)wmbdqW92HVh1+YVEc?VX^|;>BT1iAbEq)JElOjOrbpXDSPMtNdu z{J-;F;>W{Ae_7P?z?!*xIgG)Lw8~J?Z#Q$5RJJMtz^JxH)EHPrRWwpLzjx11E6BZi z<`SaTD>pee8`#^4LWDp=)L2m-_c@72iV$HEyQ&0NT5a5}QSXLPUR>uv(D*eV&fi>h ziWk3j6bXd6aKl~TYKR0wbFCt>_xTVzmeoFkLZyINn2}h|dKo^PK`O~Jl`PoWl;$$p zc0i#TVy;SH(ja$3^| z3pI=#(7w1&jhUq=Po%OU?-Uj|-N>KoCcbMt|Ik!wU72_4AwBOeCC22!onr|}>|p#V zZoq1BlCbL1lzzjJ`q+~1O_iDiTHa=8yy!5!ZNFNP73lNqi?~e$WIFfYT2rWW0+mtc z|2OnM`em*9#eU(3;#*ynFEJb#31MQCgO#Urgc@u7Q~SRBzrD;MQa(cnA{=~AZ&sC1 z+xe(3>3GBo#3JxrxWcAX)tdmGAP0Ame&?BKhg_wgEQjUUlRGvH_z`HfZdT?gxO*NU zz5MVFX0!3_(ofh*4h91X`>qhz&(31>L7NxF#I{<0Fgog*Gp|o6>2N;Rkp&2EQ-W4@ ztV6VRpEk;u#Z5kWy*sP17itrZS^n`vJ&4sE(&6p#4prMwCrC8;n`2Gw@zW|!b Bigy42 literal 0 HcmV?d00001 diff --git a/docs/opengeometry/agents.mdx b/docs/opengeometry/agents.mdx new file mode 100644 index 00000000..fd48316a --- /dev/null +++ b/docs/opengeometry/agents.mdx @@ -0,0 +1,41 @@ +--- +title: Use a coding agent +description: Give a coding assistant the OpenGeometry 3.0 rules it gets wrong most often, and the sources it can trust. +icon: sparkles +--- + +A coding assistant trained on older code often writes OpenGeometry 2.0: `new Cuboid(...)`, `new Vector3(...)`, `setPlacement(...)`. None of that exists in 3.0. Give the assistant these pages and the rules below. + +## Sources to give the assistant + +| Source | Use it for | +| ---------------------------------------- | ----------------------------------------------------- | +| [`/llms.txt`](/llms.txt) | The index of these docs, one line per page | +| Any page with `.md` added to its address | That page as plain Markdown | +| `node_modules/opengeometry/index.d.ts` | Every export and its types, for the installed version | +| `node_modules/opengeometry/README.md` | A compact reference of every call | +| [Examples](/opengeometry/examples) | Working 3.0 code | + +The contextual menu at the top of each page copies the page or opens it in an assistant. + +## Rules to put in the prompt + +```text +This project uses OpenGeometry 3.0 (npm package "opengeometry"). +- Await OpenGeometry.create(input, options) once before making any body. workerURL goes in the second argument. +- Make bodies with new Wire(kind, params), new Solid(kind, params) or new Sheet(OG_OPERATION_SWEEP, params). + kind is an OG_PRIMITIVE_* or OG_OPERATION_* constant. +- Points and vectors are [x, y, z] arrays. Units are metres. Y is up. +- A Profile point [u, v] on the default ground plane lands at world (u, 0, -v). +- Move bodies with body.transform(OG_TRANSFORM_*, params). Do not set position, rotation or scale. +- solid.operate(kind, { tools }) changes the target once. Tools stay separate live solids. +- A shape shared by instances needs { instances: 'all' } or makeUnique() before an edit. +- Add bodies to the THREE.Scene yourself. A SystemAssembly is not a Three.js object. +- Surfaces use MeshStandardMaterial, so the scene needs a light. +- Catch OGError and branch on error.code. +- Do not use Cuboid, Polygon, Opening, Vector3, setPlacement, STL, PDF, IFC file text, projection or loft: they are not in 3.0. +``` + +## Check the result + +Ask the assistant to run the type check. A call to a 2.0 class fails at compile time against the 3.0 types. Then run the page in a browser: a missing light gives a black body, and a missing `create` throws `NotInitialised`. diff --git a/docs/opengeometry/api/body.mdx b/docs/opengeometry/api/body.mdx new file mode 100644 index 00000000..a1854261 --- /dev/null +++ b/docs/opengeometry/api/body.mdx @@ -0,0 +1,126 @@ +--- +title: Body methods +description: The methods and fields that Wire, Solid and Sheet share, with the types Measure, Validity, MirrorPlane, PointClassification and BodyEventMap. +icon: cube +--- + +`Wire`, `Solid` and `Sheet` extend one base class, which extends `THREE.Group`. This page lists what they share. + +## Fields + +| Field | Type | Meaning | +| ------------ | ------------------------------ | ------------------------------------------------------ | +| `ogId` | `string` | The body's id in the document. Read-only | +| `bodyType` | `'Wire' \| 'Sheet' \| 'Solid'` | Read-only | +| `surface` | `THREE.Mesh` | The display surface | +| `outline` | `THREE.LineSegments` | The display outline | +| `appearance` | `Appearance` | The current appearance. Change it with `setAppearance` | + +## Options + +`new Wire | Solid | Sheet(kind, params, options?)` takes `{ ogId?, parent?, plane?, appearance? }`: + +| Option | Type | Meaning | +| ------------ | ------------------------------------------------------------------------- | -------------------------------------------------------- | +| `ogId` | `string` | Your id. It must not be in use | +| `parent` | `SystemAssembly` | The parent node | +| `plane` | `{ origin?, normal?, xDirection? }` | The plane of a primitive. Ignored by operations | +| `appearance` | `{ color?, opacity?, outline?, pickOutline?, deflection?, smoothAngle? }` | See [Display](/opengeometry/concepts/display#appearance) | + +## Appearance + +`setAppearance(partial)` merges new values into `appearance`. + +## Placement and tree + +| Method | Returns | +| ------------------------------------ | ------------------------------------------------------------------------ | +| `transform(kind, params)` | `void`. See [Transforms](/opengeometry/guides/transforms-and-assemblies) | +| `getPlacement()` | `{ origin, xDirection, normal, scale }` relative to the parent | +| `getWorldPlacement()` | The same, in the world | +| `addChild(children, { keepWorld? })` | `void` | +| `removeChild(child, { keepWorld? })` | `void` | +| `getChildren()` | `string[]`, the children's `ogId` values | +| `getParent()` | `string \| null` | + +## Queries + +| Method | Returns | +| ----------------------------- | -------------------------------------------------------------- | +| `getBounds()` | `[minX, minY, minZ, maxX, maxY, maxZ]` in the world, or `null` | +| `getBrep()` | The B-rep in the body's own coordinates | +| `getWorldBrep()` | The B-rep placed in the world | +| `faceNormalAt(faceId, point)` | `[x, y, z]`, the unit normal in the body's own coordinates | +| `classifyPoint(point)` | `PointClassification` | +| `measure({ deflection? })` | `Measure` | +| `validity()` | `Validity` | +| `getInstanceCount()` | `number`, the bodies that share this shape | + +### PointClassification + +`'Inside' | 'Outside' | 'Boundary' | 'Unknown'`. A wire or a sheet throws `InvalidOperand`. + +### Measure + +| Field | Type | Meaning | +| ---------------- | -------- | ----------------------------------------- | +| `volume` | `number` | Within `errorBound` of the exact volume | +| `area` | `number` | Within `areaErrorBound` of the exact area | +| `errorBound` | `number` | The volume bound | +| `areaErrorBound` | `number` | The area bound | +| `deflection` | `number` | The deflection that was used | + +### Validity + +| Field | Type | Meaning | +| ---------- | -------------------------------------- | ----------------------------- | +| `valid` | `boolean` | | +| `closed` | `boolean` | Every shell or wire is closed | +| `bodyType` | `'Wire' \| 'Sheet' \| 'Solid' \| null` | `null` when not valid | +| `error` | `{ code, message }` | Only when not valid | + +## Edits + +| Method | What it does | +| --------------------------------------- | --------------------------------------------------------------- | +| `rebuild(kind, params, { instances? })` | Gives the body new parameters. The body type must stay the same | +| `mirror(plane, { instances? })` | Rebuilds the shape as its reflection across a `MirrorPlane` | +| `makeUnique()` | Gives the body its own copy of a shared shape | +| `dispose()` | Removes the body from the document | + +`instances: 'all'` changes every body that shares the shape. Without it, a shared shape throws `SharedShape`. + +### MirrorPlane + +`{ origin: [x, y, z]; normal: [x, y, z] }`, in the body's own coordinates. The normal need not be of unit length. + +## Copies + +| Method | Returns | +| ------------------------------- | ----------------------------------------------------------- | +| `duplicate({ ogId?, parent? })` | A new body of the same class with its own copy of the shape | +| `instance({ ogId?, parent? })` | A new body of the same class that shares the shape | +| `clone()` | A display copy for Three.js only, not a body | +| `copy()` | Throws `InvalidOperand`. Use `duplicate()` | + +## Events + +`BodyEventMap` adds two events to those of a Three.js object: + +| Event | When | +| ------------------ | ------------------------------------------ | +| `geometrychanged` | After the body installs a new display mesh | +| `placementchanged` | When a flush moves the body | + +```ts +import { OpenGeometry, Solid, OG_PRIMITIVE_CUBOID, type BodyEventMap } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const box = new Solid(OG_PRIMITIVE_CUBOID, { width: 1, height: 1, depth: 1 }); +const event: keyof BodyEventMap = 'geometrychanged'; +box.addEventListener(event, () => console.log('new mesh')); +``` diff --git a/docs/opengeometry/api/constants.mdx b/docs/opengeometry/api/constants.mdx new file mode 100644 index 00000000..ce9fefdc --- /dev/null +++ b/docs/opengeometry/api/constants.mdx @@ -0,0 +1,108 @@ +--- +title: Constants +description: The kind constants for primitives, operations and transforms, the typed parameter helpers and their types, and the region tolerance. +icon: list-check +--- + +Each kind is a string constant. Pass it as the first argument of a constructor, `operate`, `rebuild` or `transform`. + +## Primitives + +| Constant | Value | Body | Parameters type | +| ------------------------------ | ------------------ | ----- | -------------------------- | +| `OG_PRIMITIVE_RECTANGLE` | `'Rectangle'` | Wire | `{ width, breadth }` | +| `OG_PRIMITIVE_CIRCLE` | `'Circle'` | Wire | `{ radius }` | +| `OG_PRIMITIVE_POLYLINE` | `'Polyline'` | Wire | `{ points, closed? }` | +| `OG_PRIMITIVE_PROFILE` | `'Profile'` | Wire | `ProfileParams` | +| `OG_PRIMITIVE_ARC` | `'Arc'` | Wire | `ArcParams` | +| `OG_PRIMITIVE_CUBOID` | `'Cuboid'` | Solid | `{ width, height, depth }` | +| `OG_PRIMITIVE_CYLINDER` | `'Cylinder'` | Solid | `{ radius, height }` | +| `OG_PRIMITIVE_CYLINDER_SECTOR` | `'CylinderSector'` | Solid | `CylinderSectorParams` | +| `OG_PRIMITIVE_POLYHEDRON` | `'Polyhedron'` | Solid | `PolyhedronParams` | +| `OG_PRIMITIVE_SPHERE` | `'Sphere'` | Solid | `SphereParams` | +| `OG_PRIMITIVE_CONE` | `'Cone'` | Solid | `ConeParams` | +| `OG_PRIMITIVE_TORUS` | `'Torus'` | Solid | `TorusParams` | + +## Operations + +| Constant | Value | Used with | +| ------------------------ | ------------- | ------------------------ | +| `OG_OPERATION_EXTRUDE` | `'Extrude'` | `new Solid` | +| `OG_OPERATION_SWEEP` | `'Sweep'` | `new Solid`, `new Sheet` | +| `OG_OPERATION_REVOLVE` | `'Revolve'` | `new Solid` | +| `OG_OPERATION_UNION` | `'Union'` | `solid.operate` | +| `OG_OPERATION_SUBTRACT` | `'Subtract'` | `solid.operate` | +| `OG_OPERATION_INTERSECT` | `'Intersect'` | `solid.operate` | +| `OG_OPERATION_SHELL` | `'Shell'` | `solid.operate` | + +## Transforms + +| Constant | Value | Parameters | +| ------------------------ | ------------- | ------------------------------------------- | +| `OG_TRANSFORM_TRANSLATE` | `'Translate'` | `{ offset }` | +| `OG_TRANSFORM_ROTATE` | `'Rotate'` | `{ axis, degrees, pivot? }` | +| `OG_TRANSFORM_SCALE` | `'Scale'` | `{ factor, pivot? }` | +| `OG_TRANSFORM_PLACE` | `'Place'` | `{ origin?, xDirection?, normal?, scale? }` | + +## Typed parameter helpers + +Each helper returns its argument unchanged. It only gives the object a type, so the compiler checks the field names. + +| Helper | Type | +| ------------------------------------- | ------------------------------- | +| `OG_PRIMITIVE_PARAMS_RECTANGLE` | `{ width, breadth }` | +| `OG_PRIMITIVE_PARAMS_CIRCLE` | `{ radius }` | +| `OG_PRIMITIVE_PARAMS_POLYLINE` | `{ points, closed? }` | +| `OG_PRIMITIVE_PARAMS_CUBOID` | `{ width, height, depth }` | +| `OG_PRIMITIVE_PARAMS_CYLINDER` | `{ radius, height }` | +| `OG_PRIMITIVE_PARAMS_PROFILE` | `ProfileParams` | +| `OG_PRIMITIVE_PARAMS_ARC` | `ArcParams` | +| `OG_PRIMITIVE_PARAMS_CYLINDER_SECTOR` | `CylinderSectorParams` | +| `OG_PRIMITIVE_PARAMS_POLYHEDRON` | `PolyhedronParams` | +| `OG_PRIMITIVE_PARAMS_SPHERE` | `SphereParams` | +| `OG_PRIMITIVE_PARAMS_CONE` | `ConeParams` | +| `OG_PRIMITIVE_PARAMS_TORUS` | `TorusParams` | +| `OG_OPERATION_PARAMS_EXTRUDE` | `{ profile, holes?, distance }` | +| `OG_OPERATION_PARAMS_SWEEP` | `{ profile, path, caps? }` | +| `OG_OPERATION_PARAMS_REVOLVE` | `{ profile, axis? }` | + +```ts +import { + OpenGeometry, + Solid, + OG_PRIMITIVE_CYLINDER_SECTOR, + OG_PRIMITIVE_PARAMS_CYLINDER_SECTOR, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const params = OG_PRIMITIVE_PARAMS_CYLINDER_SECTOR({ + radius: 2, + height: 3, + startAngle: 0, + sweepAngle: Math.PI / 2, +}); +const wedge = new Solid(OG_PRIMITIVE_CYLINDER_SECTOR, params); +console.log(wedge.validity().valid); +``` + +## Parameter types + +| Type | Fields | +| ---------------------- | ------------------------------------------------------- | +| `ProfileParams` | `start: [u, v]`, `segments: ProfileSegment[]`, `closed` | +| `ProfileSegment` | `to: [u, v]`, `arc?: ProfileArc` | +| `ProfileArc` | `center: [u, v]`, `counterClockwise` | +| `ArcParams` | `radius`, `startAngle`, `sweepAngle` | +| `CylinderSectorParams` | `radius`, `height`, `startAngle`, `sweepAngle` | +| `PolyhedronParams` | `points: [x, y, z][]`, `faces: number[][]` | +| `SphereParams` | `radius` | +| `ConeParams` | `radiusBottom`, `radiusTop`, `height` | +| `TorusParams` | `majorRadius`, `minorRadius` | + +## OG_REGION_TOLERANCE + +`1e-6`. The fixed tolerance, in metres, of the 2D region calls. diff --git a/docs/opengeometry/api/display.mdx b/docs/opengeometry/api/display.mdx new file mode 100644 index 00000000..306fadc8 --- /dev/null +++ b/docs/opengeometry/api/display.mdx @@ -0,0 +1,75 @@ +--- +title: Display +description: The statics that control display meshes, level of detail and host-drawn bodies, and the HostGroup type. +icon: display +--- + +See [Display](/opengeometry/concepts/display) for how display works, and [Use your Three.js scene](/opengeometry/guides/use-your-threejs-scene) for host-drawn layers. + +## flush + +`static flush(options?: { geometry?: 'sync'; bodies?: readonly Body[] }): void` + +- No options: applies pending placements and the meshes that are ready. Meshes nothing new. +- `{ geometry: 'sync' }`: also meshes every displayed body that waits for its mesh, before it returns. +- `{ geometry: 'sync', bodies }`: meshes and places only those bodies. + +Hidden bodies, bodies with no shape and bodies disposed while a mark is live are skipped. A fully disposed body, or one from a reset runtime, throws `Disposed` before anything is meshed. `bodies` without `geometry: 'sync'`, a `bodies` that is not an array, or an item that is not a wire, sheet or solid throws `InvalidParameter`. + +## settled + +`static settled(options?: { deflection?: number }): Promise<{ failed: { ogId: string; error: unknown }[] }>` + +Resolves when every displayed body has its mesh. `failed` lists the bodies whose mesh failed. If nothing was rendered, it resolves at once. `deflection` asks for meshes at that deflection, in world metres, while it waits. + +## markDisplayed + +`static markDisplayed(bodies: readonly Body[]): void` + +Counts the bodies as displayed for the current render pass. Call it from the `onBeforeRender` of a layer that draws them. It works for a body hidden by layer, skips a body with `visible = false`, and checks `bodies` as `flush({ bodies })` does. + +## setHostDrawn + +`static setHostDrawn(bodies: readonly Body[], hostDrawn: boolean): void` + +`true` hands the drawing of the bodies to your app: each `visible` becomes `false`, and the kernel keeps the body's own visibility apart. `false` gives the drawing back and sets `visible` to that visibility. Do not set `visible` on a host-drawn body. A `hostDrawn` that is not a boolean throws `InvalidParameter`. + +## hostGroup + +`static hostGroup(bodies: readonly Body[]): HostGroup` + +Returns a `HostGroup` of the bodies. + +### HostGroup + +| Method | What it does | +| ------------- | ----------------------------------------------------------------------------------------------------------- | +| `drawn()` | Counts every member as displayed for the current render pass, at a cost that does not grow with the members | +| `set(bodies)` | Replaces the members. On a disposed group, or one from a reset runtime, it throws `Disposed` | +| `dispose()` | Ends the group. `drawn()` then does nothing | + +A body may be in several groups. A member that is disposed leaves its groups. A group that is dropped without `dispose()` ends when it is garbage collected. + +## setDisplayDeflection + +`static setDisplayDeflection(world?: number): void` + +Sets one mesh deflection, in world metres, for every body. Call it with no value to let the camera choose again. A value that is not positive throws `InvalidParameter`. + +## releaseIdleGeometry + +`static releaseIdleGeometry(): { records: number; bytes: number }` + +Frees the display meshes cached for bodies that do not show them. Returns how many were freed and their size. + +## setCameraMotion + +`static setCameraMotion(moving: boolean): void` + +`true` tells the kernel that the camera moves now, so it can use coarser meshes until the camera stops. + +## observeCamera + +`static observeCamera(renderer: THREE.WebGLRenderer, camera: THREE.Camera): void` + +Uses the first camera seen per renderer frame for level of detail. Call it before each render, or from the `onBeforeRender` of a layer whose drawables are not bodies. diff --git a/docs/opengeometry/api/export.mdx b/docs/opengeometry/api/export.mdx new file mode 100644 index 00000000..16723934 --- /dev/null +++ b/docs/opengeometry/api/export.mdx @@ -0,0 +1,79 @@ +--- +title: Export +description: exportStep writes STEP files; exportIfcBody returns the IFC exchange body of a solid, with the types AnalyticExchangeBodyV2 and IfcPreparedValue. +icon: file-export +--- + +## exportStep + +`static exportStep(options): Promise<{ text: string; report: StepExportReport }>` + +| Option | Type | Default | +| ----------- | -------------------------------------- | ---------------- | +| `nodes` | `(Body \| SystemAssembly \| string)[]` | required | +| `unit` | `'millimetre' \| 'metre'` | `'millimetre'` | +| `upAxis` | `'Z' \| 'Y'` | `'Z'` | +| `name` | `string` | none | +| `timestamp` | `string` | the current time | + +### The report + +| Field | Meaning | +| ------------------------------------------------------- | ----------------------------------------------------- | +| `unit`, `upAxis`, `timestamp` | The settings that were used | +| `products`, `solids`, `faces`, `edges`, `cavityShells` | What was written | +| `entities`, `bytes` | The size of the file | +| `fittedCurves`, `pcurvelessEdges`, `collapsedChartUses` | Approximations in the file | +| `exchangeErrorBound`, `geometricTolerance` | The accuracy of the file | +| `validationLevel` | How the file was checked | +| `bodies` | One entry per body: its `ogId`, shape and counts | +| `skipped` | `{ ogId, reason }` for each node that was not written | + +A wire or a sheet on its own throws `InvalidOperand`. A selection with no solid throws `EmptyResult`. See [Export STEP](/opengeometry/guides/export-step). + +## exportIfcBody + +`static exportIfcBody(node: Body | SystemAssembly): AnalyticExchangeBodyV2` + +Returns the exact geometry of one solid, in world metres with Z up. A sheet, a wire or an assembly throws. + +```ts +import { + OpenGeometry, + Solid, + OG_PRIMITIVE_CYLINDER, + type AnalyticExchangeBodyV2, + type IfcPreparedValue, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const column = new Solid(OG_PRIMITIVE_CYLINDER, { radius: 0.2, height: 3 }); +const body: AnalyticExchangeBodyV2 = OpenGeometry.exportIfcBody(column); +const first: IfcPreparedValue | undefined = body.entities[0]?.attributes[0]; +console.log(body.schema_version, body.representation_type, first?.kind); +``` + +### AnalyticExchangeBodyV2 + +| Field | Value | +| ----------------------------------------------------------------- | ----------------------------------------------------------------- | +| `schema_version` | `2` | +| `length_unit` | `'metre'` | +| `up_axis` | `'Z'` | +| `coordinate_space` | `'world'` | +| `representation_type` | `'AdvancedBrep'`, or `'CSG'` for a solid with a cavity | +| `quality` | `{ kind: 'Analytic' }`, or `{ kind: 'Approximate', max_error }` | +| `geometric_tolerance`, `exchange_error_bound`, `validation_level` | The accuracy of the body | +| `entities` | `{ id, entity_type, attributes }` for each IFC entity to write | +| `solids` | The ids of the solid entities | +| `faces` | For each face: its `face` id, `key`, `entity` id and `provenance` | + +### IfcPreparedValue + +One attribute value: `Ref`, `List`, `Real`, `Integer`, `Text`, `Enum`, `Bool`, `Null` or `Derived`, as `{ kind, ... }`. + +See [IFC exchange body](/opengeometry/guides/ifc-exchange-body). diff --git a/docs/opengeometry/api/offsets.mdx b/docs/opengeometry/api/offsets.mdx new file mode 100644 index 00000000..3ea4ac4f --- /dev/null +++ b/docs/opengeometry/api/offsets.mdx @@ -0,0 +1,75 @@ +--- +title: Offsets +description: Variable insets of point and curved rings, polyline strokes and one-sided offsets, with the types OffsetHole, OffsetPath2D and OffsetPolylineOptions. +icon: arrows-to-dot +--- + +Rings and paths are flat `[x, y, z, ...]` lists or a `Float64Array`. `y` is ignored. + +## offsetRingVariable + +`static offsetRingVariable(ring, distances, holes?: readonly OffsetHole[]): CurvedRegion2D[]` + +Insets a closed ring by one distance per edge. Each hole grows by its own distances. Inside corners are exact arcs. + +An outer ring that crosses itself, such as a bowtie, throws `InvalidTopology`. + +## offsetCurvedRingVariable + +`static offsetCurvedRingVariable(region: CurvedRegion2D, distances, holeDistances?: (number[] | Float64Array)[]): CurvedRegion2D[]` + +Insets one region of lines and arcs by one distance per edge, with one list per hole ring. + +- Each distance is finite and not negative. A distance of 0 keeps its edge. +- An arc stays on its centre: a convex arc moves to `r − d`, a concave arc or a hole's arc to `r + d`. +- A distance larger than an arc's radius, a wrong count, or a negative or non-finite distance throws `InvalidParameter`. +- A collapsed result is an empty list. + +## offsetPolylineRegions + +`static offsetPolylineRegions(path, width: number, closed: boolean, miterLimit?: number): CurvedRegion2D[]` + +Strokes a path into regions of the given width. Corners are mitred up to `miterLimit`, default 4, and bevelled past it. A width that is not finite throws `InvalidParameter`. + +## offsetPolyline + +`static offsetPolyline(path, distance: number, options?: OffsetPolylineOptions): OffsetPath2D` + +Offsets a path to one side. + +```ts +import { OpenGeometry, type OffsetPath2D, type OffsetPolylineOptions } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const options: OffsetPolylineOptions = { acuteThresholdDegrees: 35, bevel: true }; +const kerb: OffsetPath2D = OpenGeometry.offsetPolyline([0, 0, 0, 10, 0, 0, 10, 0, 6], 0.5, options); +console.log(kerb.edges.length, kerb.bevelled, kerb.closed); +``` + +## Types + +### OffsetHole + +`{ ring: number[] | Float64Array; distances: number[] | Float64Array }` + +### OffsetPolylineOptions + +| Field | Default | Meaning | +| ----------------------- | ------------------------- | -------------------------------------- | +| `acuteThresholdDegrees` | `35` | Corners sharper than this are bevelled | +| `bevel` | `true` | Bevel acute corners | +| `closed` | `true` when the ends meet | Treat the path as closed | + +### OffsetPath2D + +| Field | Type | Meaning | +| ---------- | -------------------- | ----------------------------------- | +| `edges` | `CurvedRegionEdge[]` | The offset edges | +| `bevelled` | `number[]` | The indices of the bevelled corners | +| `closed` | `boolean` | Whether the result is closed | + +See [Regions and offsets](/opengeometry/guides/regions-and-offsets). diff --git a/docs/opengeometry/api/og-error.mdx b/docs/opengeometry/api/og-error.mdx new file mode 100644 index 00000000..35c2f852 --- /dev/null +++ b/docs/opengeometry/api/og-error.mdx @@ -0,0 +1,58 @@ +--- +title: OGError +description: The error class every call throws, with the types ErrorDetails and OperateErrorDetails. +icon: triangle-exclamation +--- + +`class OGError extends Error` + +```ts +import { OGError, OpenGeometry, Solid, OG_PRIMITIVE_CUBOID, type ErrorDetails } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +try { + new Solid(OG_PRIMITIVE_CUBOID, { width: 1, height: 1 }); +} catch (error) { + if (error instanceof OGError) { + const details: ErrorDetails = error.details; + console.log(error.code, error.call, JSON.stringify(error), details); + } +} +``` + +## Fields + +| Field | Type | Meaning | +| --------- | -------------- | ------------------------------------------------- | +| `code` | `string` | A stable name, such as `InvalidParameter` | +| `call` | `string` | The call that failed, such as `Solid.constructor` | +| `message` | `string` | A text for people. Do not parse it | +| `details` | `ErrorDetails` | More data for some codes. `{}` when there is none | +| `name` | `'OGError'` | | + +The codes are listed on [Errors and limits](/opengeometry/concepts/errors#codes). + +## Methods + +- `toJSON()` returns `{ code, call, message, details }`, so `JSON.stringify` keeps every field. +- `OGError.fromJSON(value)` makes an `OGError` from that object, for example after it crossed a worker or a network. + +## ErrorDetails + +`Partial & Record`. + +## OperateErrorDetails + +The details of a refused `operate`: + +| Field | Type | Meaning | +| ----------- | ------------------ | ------------------------------------------------------------- | +| `handlers` | `string[]` | The methods that took part | +| `attempted` | `string[]` | Every method that was tried | +| `families` | `[string, string]` | The pair of surface families that the kernel could not handle | +| `toolIndex` | `number` | The index of the tool that failed | +| `ogIds` | `string[]` | The bodies involved | diff --git a/docs/opengeometry/api/og-mark.mdx b/docs/opengeometry/api/og-mark.mdx new file mode 100644 index 00000000..7b89ad83 --- /dev/null +++ b/docs/opengeometry/api/og-mark.mdx @@ -0,0 +1,45 @@ +--- +title: OGMark +description: A point in the document's history that you can roll back to. +icon: bookmark +--- + +`class OGMark` + +Make a mark with `OpenGeometry.mark()`. Do not call the constructor. + +```ts +import { OpenGeometry, Solid, OG_PRIMITIVE_CUBOID, type OGMark } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const mark: OGMark = OpenGeometry.mark(); +new Solid(OG_PRIMITIVE_CUBOID, { width: 1, height: 1, depth: 1 }); +mark.rollback(); +mark.release(); +console.log(OpenGeometry.markStats()); +``` + +## rollback + +`rollback(): void` + +Takes the document back to the mark. The mark stays live. Marks made after it are released. + +## release + +`release(): void` + +Ends the mark and frees the history that only it kept. + +Both throw `InvalidMark` on a released mark. + +## Related statics + +- `OpenGeometry.markStats()` returns `{ liveMarks, retainedRevisions }`. +- `OpenGeometry.transaction(fn, { dryRun? })` runs `fn` between a mark and its release, and rolls back if `fn` throws. + +See [History](/opengeometry/concepts/history). diff --git a/docs/opengeometry/api/opengeometry.mdx b/docs/opengeometry/api/opengeometry.mdx new file mode 100644 index 00000000..edce4be4 --- /dev/null +++ b/docs/opengeometry/api/opengeometry.mdx @@ -0,0 +1,65 @@ +--- +title: OpenGeometry +description: The runtime statics - start the kernel, listen to events, reset, history, export and the 2D calls. +icon: power-off +--- + +`OpenGeometry` is a class with static methods only. You never make an instance. + +```ts +import { OpenGeometry } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); +const stop = OpenGeometry.on('warning', (event) => console.warn(event)); +stop(); +``` + +## Start and stop + +### create + +`static create(input?: { wasmURL?, wasmModule? }, options?: { workerURL?, tessellation? }): Promise` + +Loads the kernel and starts one document. Await it once, before the first body. + +| Argument | Type | Meaning | +| ---------------------- | ---------------------- | -------------------------------------------------------------------- | +| `input.wasmURL` | `string \| URL` | Where to fetch `opengeometry_bg.wasm`. Default: next to `index.js` | +| `input.wasmModule` | `WebAssembly.Module` | A compiled module. Use it in Node | +| `options.workerURL` | `string \| URL` | Where to fetch `tessellation-worker.js`. Default: next to `index.js` | +| `options.tessellation` | `'worker' \| 'inline'` | Where display meshes are made. Inline when there is no `Worker` | + +### reset + +`static reset(): void` + +Frees every body and leaves an empty document. A body from before the reset throws `Disposed`. Use it after a `'fatal'` event, and between tests. + +### on + +`static on(event, handler): () => boolean` + +Subscribes to `'geometry'`, `'warning'`, `'error'` or `'fatal'`. Returns a function that unsubscribes. See [Errors and limits](/opengeometry/concepts/errors#events). + +## History + +| Method | Returns | See | +| ------------------------------ | ---------------------------------- | ------------------------------------------------------ | +| `mark()` | `OGMark` | [OGMark](/opengeometry/api/og-mark) | +| `markStats()` | `{ liveMarks, retainedRevisions }` | [History](/opengeometry/concepts/history) | +| `transaction(fn, { dryRun? })` | What `fn` returns | [History](/opengeometry/concepts/history#transactions) | + +## Display and picking + +`flush`, `settled`, `markDisplayed`, `setHostDrawn`, `hostGroup`, `setDisplayDeflection`, `releaseIdleGeometry`, `setCameraMotion` and `observeCamera` are on [Display](/opengeometry/api/display). `resolveHit` is on [Picking](/opengeometry/api/picking). + +## Export + +`exportStep` and `exportIfcBody` are on [Export](/opengeometry/api/export). + +## 2D + +`booleanRegions2D`, `booleanCurvedRegions2D` and `insetCurvedRegion2D` are on [Regions](/opengeometry/api/regions). `offsetRingVariable`, `offsetCurvedRingVariable`, `offsetPolylineRegions` and `offsetPolyline` are on [Offsets](/opengeometry/api/offsets). diff --git a/docs/opengeometry/api/overview.mdx b/docs/opengeometry/api/overview.mdx new file mode 100644 index 00000000..02235b3b --- /dev/null +++ b/docs/opengeometry/api/overview.mdx @@ -0,0 +1,46 @@ +--- +title: API reference +description: Every export of the opengeometry 3.0 package, and the page that describes it. +icon: code +--- + +The package has one entry, `opengeometry`. Its types are in `index.d.ts` in the installed package. + +```ts +import { OpenGeometry, Solid, Wire, OG_PRIMITIVE_CUBOID } from 'opengeometry'; +import type { Measure } from 'opengeometry'; +``` + +## Classes and values + +| Export | Page | What it is | +| ---------------- | --------------------------------------------------- | ----------------------------------------------- | +| `OpenGeometry` | [OpenGeometry](/opengeometry/api/opengeometry) | The runtime: start, events, history, export, 2D | +| `Wire` | [Wire](/opengeometry/api/wire) | Lines and arcs | +| `Solid` | [Solid](/opengeometry/api/solid) | Closed faces around a volume | +| `Sheet` | [Sheet](/opengeometry/api/sheet) | Faces that enclose no volume | +| `SystemAssembly` | [SystemAssembly](/opengeometry/api/system-assembly) | A group of nodes | +| `OGMark` | [OGMark](/opengeometry/api/og-mark) | A point in history | +| `OGError` | [OGError](/opengeometry/api/og-error) | The error every call throws | +| `OG_*` constants | [Constants](/opengeometry/api/constants) | Kinds, typed parameter helpers, tolerance | + +The methods that `Wire`, `Solid` and `Sheet` share are on [Body methods](/opengeometry/api/body). The display statics are on [Display](/opengeometry/api/display), and picking on [Picking](/opengeometry/api/picking). + +## Types + +| Type | Page | +| ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | +| `BodyEventMap`, `PointClassification`, `Measure`, `Validity`, `MirrorPlane` | [Body methods](/opengeometry/api/body) | +| `HostGroup` | [Display](/opengeometry/api/display) | +| `ErrorDetails`, `OperateErrorDetails` | [OGError](/opengeometry/api/og-error) | +| `AnalyticExchangeBodyV2`, `IfcPreparedValue` | [Export](/opengeometry/api/export) | +| `OffsetRegion`, `CurvedRegion2D`, `CurvedRegionEdge` | [Regions](/opengeometry/api/regions) | +| `OffsetHole`, `OffsetPath2D`, `OffsetPolylineOptions` | [Offsets](/opengeometry/api/offsets) | +| `ProfileParams`, `ProfileSegment`, `ProfileArc`, `ArcParams`, `CylinderSectorParams`, `PolyhedronParams`, `SphereParams`, `ConeParams`, `TorusParams` | [Constants](/opengeometry/api/constants) | + +## Conventions + +- Points and vectors are `[x, y, z]`. Units are metres. Y is up. +- Kinds are string constants, such as `OG_PRIMITIVE_CUBOID`, which is `'Cuboid'`. +- Every failure throws an `OGError`. +- `index.d.ts` also declares internal members, such as `handle` and `install`. They are not part of the API; do not call them. diff --git a/docs/opengeometry/api/picking.mdx b/docs/opengeometry/api/picking.mdx new file mode 100644 index 00000000..234202d3 --- /dev/null +++ b/docs/opengeometry/api/picking.mdx @@ -0,0 +1,36 @@ +--- +title: Picking +description: resolveHit turns a Three.js raycast hit into a body, a face and an edge. +icon: arrow-pointer +--- + +## resolveHit + +`static resolveHit(hit: THREE.Intersection): { ogId, shapeRevision, faceId?, edgeId? } | undefined` + +| Field | Type | Meaning | +| --------------- | -------- | -------------------------------------------- | +| `ogId` | `string` | The body that was hit | +| `shapeRevision` | `number` | The revision of the shape whose mesh was hit | +| `faceId` | `number` | The B-rep face, for a hit on the surface | +| `edgeId` | `number` | The B-rep edge, for a hit on the outline | + +It returns `undefined` for a hit on an object that is not a body, or on a body with no mesh yet. + +```ts +import * as THREE from 'three'; +import { OpenGeometry } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +function pick(raycaster: THREE.Raycaster, scene: THREE.Scene): string | undefined { + const [hit] = raycaster.intersectObject(scene, true); + return hit ? OpenGeometry.resolveHit(hit)?.ogId : undefined; +} +console.log(pick(new THREE.Raycaster(), new THREE.Scene())); +``` + +See [Picking](/opengeometry/guides/picking). diff --git a/docs/opengeometry/api/regions.mdx b/docs/opengeometry/api/regions.mdx new file mode 100644 index 00000000..84a5081b --- /dev/null +++ b/docs/opengeometry/api/regions.mdx @@ -0,0 +1,70 @@ +--- +title: Regions +description: 2D region booleans and the curved inset, with the types OffsetRegion, CurvedRegion2D and CurvedRegionEdge. +icon: vector-square +--- + +## booleanRegions2D + +`static booleanRegions2D(a: readonly OffsetRegion[], b: readonly OffsetRegion[], operation: 'union' | 'intersection' | 'subtraction'): OffsetRegion[]` + +Booleans of point regions. Results come back at the input height, wound the same way, each ring starting at its smallest x. + +## booleanCurvedRegions2D + +`static booleanCurvedRegions2D(a: readonly CurvedRegion2D[], b: readonly CurvedRegion2D[], operation): CurvedRegion2D[]` + +The same, for regions of line and arc edges. + +## insetCurvedRegion2D + +`static insetCurvedRegion2D(region: CurvedRegion2D, distance: number): CurvedRegion2D[]` + +Insets one region by a distance above zero; holes grow by the same distance. Each arc keeps its centre, and a reflex corner rounds to an arc of the distance. An inset past the half width is an empty list. + +```ts +import { OpenGeometry, type CurvedRegion2D, type CurvedRegionEdge } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const side = (from: [number, number], to: [number, number]): CurvedRegionEdge => ({ + kind: 'line', + from, + to, +}); +const room: CurvedRegion2D = { + outer: [side([0, 0], [0, 4]), side([0, 4], [5, 4]), side([5, 4], [5, 0]), side([5, 0], [0, 0])], + holes: [], +}; +const finish = OpenGeometry.insetCurvedRegion2D(room, 0.1); +console.log(finish.length, finish[0]?.outer.length); +``` + +## Types + +### OffsetRegion + +`{ outer: { x, y, z }[]; holes: { x, y, z }[][] }`. All points are at one height. + +### CurvedRegion2D + +`{ outer: CurvedRegionEdge[]; holes: CurvedRegionEdge[][] }`. + +### CurvedRegionEdge + +| Kind | Fields | Meaning | +| -------- | -------------------------------------------------------- | ------------------------- | +| `'line'` | `from: [x, z]`, `to: [x, z]` | A straight edge | +| `'arc'` | `center: [x, z]`, `radius`, `start_angle`, `sweep_angle` | An arc. Angles in radians | + +## Rules + +- Outer rings run clockwise in XZ, and holes counter-clockwise. +- The tolerance is `OG_REGION_TOLERANCE`, `1e-6` m. +- A plain ring is not a region and throws `InvalidParameter`. +- More than 100 000 points or edges across both operands throws `LimitExceeded`. + +See [Regions and offsets](/opengeometry/guides/regions-and-offsets). diff --git a/docs/opengeometry/api/sheet.mdx b/docs/opengeometry/api/sheet.mdx new file mode 100644 index 00000000..309cfc86 --- /dev/null +++ b/docs/opengeometry/api/sheet.mdx @@ -0,0 +1,46 @@ +--- +title: Sheet +description: A body of faces that enclose no volume, made by an open-ended sweep. +icon: note-sticky +--- + +`class Sheet extends Body` + +```ts +import { + OpenGeometry, + Sheet, + Wire, + OG_OPERATION_SWEEP, + OG_PRIMITIVE_CIRCLE, + OG_PRIMITIVE_POLYLINE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const profile = new Wire(OG_PRIMITIVE_CIRCLE, { radius: 0.1 }); +const path = new Wire(OG_PRIMITIVE_POLYLINE, { + points: [ + [0, 0, 0], + [0, 2, 0], + ], +}); +const sleeve = new Sheet(OG_OPERATION_SWEEP, { profile, path, caps: false }); +console.log(sleeve.validity()); +``` + +## Constructor + +`new Sheet(kind: string, params: Record, options?: BodyOptions)` + +The only kind is `OG_OPERATION_SWEEP` with `{ profile, path, caps: false }`. With caps the sweep makes a solid, so `new Sheet` throws `BodyTypeMismatch`. + +## What a sheet can do + +- It shows its surface, from the front only, and its outline. +- It has the [Body methods](/opengeometry/api/body). `duplicate(options?)` and `instance(options?)` return a `Sheet`. +- It has no `operate`. It is not thickened into a solid. +- `exportStep` and `exportIfcBody` refuse it. `classifyPoint` throws `InvalidOperand`. diff --git a/docs/opengeometry/api/solid.mdx b/docs/opengeometry/api/solid.mdx new file mode 100644 index 00000000..a836ed71 --- /dev/null +++ b/docs/opengeometry/api/solid.mdx @@ -0,0 +1,73 @@ +--- +title: Solid +description: A body of closed faces around a volume, with booleans, shell and the boolean report. +icon: cube +--- + +`class Solid extends Body` + +```ts +import { + OpenGeometry, + Solid, + OG_OPERATION_UNION, + OG_PRIMITIVE_CUBOID, + OG_PRIMITIVE_CYLINDER, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const base = new Solid(OG_PRIMITIVE_CUBOID, { width: 1, height: 0.2, depth: 1 }); +const post = new Solid( + OG_PRIMITIVE_CYLINDER, + { radius: 0.1, height: 1 }, + { plane: { origin: [0, 0.1, 0] } }, +); +base.operate(OG_OPERATION_UNION, { tools: [post] }); +console.log(base.getReport()?.report.operation); +``` + +## Constructor + +`new Solid(kind: string, params: Record, options?: BodyOptions)` + +| `kind` | `params` | +| ------------------------------ | -------------------------------------------- | +| `OG_PRIMITIVE_CUBOID` | `{ width, height, depth }` | +| `OG_PRIMITIVE_CYLINDER` | `{ radius, height }` | +| `OG_PRIMITIVE_CYLINDER_SECTOR` | `{ radius, height, startAngle, sweepAngle }` | +| `OG_PRIMITIVE_SPHERE` | `{ radius }` | +| `OG_PRIMITIVE_CONE` | `{ radiusBottom, radiusTop, height }` | +| `OG_PRIMITIVE_TORUS` | `{ majorRadius, minorRadius }` | +| `OG_PRIMITIVE_POLYHEDRON` | `{ points, faces }` | +| `OG_OPERATION_EXTRUDE` | `{ profile, holes?, distance }` | +| `OG_OPERATION_SWEEP` | `{ profile, path, caps? }` | +| `OG_OPERATION_REVOLVE` | `{ profile, axis? }` | + +`profile`, `holes` and `path` are wires. A sweep with `caps: false` makes a sheet, so `new Solid` throws `BodyTypeMismatch` for it. + +## operate + +`operate(kind, { tools: Solid[]; instances?: 'all' } | { thickness: number; instances?: 'all' }): void` + +| `kind` | Options | See | +| ------------------------ | --------------------------- | ----------------------------------------- | +| `OG_OPERATION_SUBTRACT` | `{ tools, instances? }` | [Booleans](/opengeometry/guides/booleans) | +| `OG_OPERATION_UNION` | `{ tools, instances? }` | [Booleans](/opengeometry/guides/booleans) | +| `OG_OPERATION_INTERSECT` | `{ tools, instances? }` | [Booleans](/opengeometry/guides/booleans) | +| `OG_OPERATION_SHELL` | `{ thickness, instances? }` | [Shell](/opengeometry/guides/shell) | + +Changes the solid in place. A refused call throws and leaves the solid as it was. + +## getReport + +`getReport(): ShapeReport | null` + +The report of the last boolean or shell: `{ report, handlers, revision }`. `report` has `operation`, `quality`, `contacts`, `coincident` and `face_mappings`. It is `null` before the first `operate`, and after a `rebuild` or a `mirror`. + +## Copies + +`duplicate(options?)` and `instance(options?)` return a `Solid`. Everything else is on [Body methods](/opengeometry/api/body). diff --git a/docs/opengeometry/api/system-assembly.mdx b/docs/opengeometry/api/system-assembly.mdx new file mode 100644 index 00000000..084da1a9 --- /dev/null +++ b/docs/opengeometry/api/system-assembly.mdx @@ -0,0 +1,55 @@ +--- +title: SystemAssembly +description: A node that groups bodies and other assemblies, with its own placement. +icon: diagram-project +--- + +`class SystemAssembly` + +A `SystemAssembly` is a node in the document, not a Three.js object. Add its bodies to your scene yourself. + +```ts +import { + OpenGeometry, + Solid, + SystemAssembly, + OG_PRIMITIVE_CUBOID, + OG_TRANSFORM_ROTATE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const shelf = new SystemAssembly({ ogId: 'shelf' }); +new Solid(OG_PRIMITIVE_CUBOID, { width: 1, height: 0.02, depth: 0.3 }, { parent: shelf }); +shelf.transform(OG_TRANSFORM_ROTATE, { axis: [0, 1, 0], degrees: 90 }); +console.log(shelf.getChildren(), shelf.getWorldPlacement().xDirection); +``` + +## Constructor + +`new SystemAssembly(options?: { ogId?: string; parent?: SystemAssembly })` + +## Methods + +| Method | Returns | +| ------------------------------------ | ------------------------------------------------------------------------ | +| `transform(kind, params)` | `void`. Moves the assembly and everything under it | +| `getPlacement()` | `{ origin, xDirection, normal, scale }` relative to the parent | +| `getWorldPlacement()` | The same, in the world | +| `addChild(children, { keepWorld? })` | `void`. `children` are bodies or assemblies | +| `removeChild(child, { keepWorld? })` | `void`. With `keepWorld: true` the child keeps its world position | +| `getChildren()` | `string[]`, the children's `ogId` values | +| `getParent()` | `string \| null` | +| `getBounds()` | `[minX, minY, minZ, maxX, maxY, maxZ]` of everything under it, or `null` | +| `dispose()` | `void` | + +| Field | Type | +| ------ | -------- | +| `ogId` | `string` | + +An `addChild` that would make a node its own ancestor throws `CycleDetected`. A `removeChild` of a node that is not a child throws `NotAChild`. + +See [Transforms and assemblies](/opengeometry/guides/transforms-and-assemblies). diff --git a/docs/opengeometry/api/wire.mdx b/docs/opengeometry/api/wire.mdx new file mode 100644 index 00000000..eb8e0cf9 --- /dev/null +++ b/docs/opengeometry/api/wire.mdx @@ -0,0 +1,45 @@ +--- +title: Wire +description: A body of lines and arcs, open or closed, with no faces. +icon: wave-square +--- + +`class Wire extends Body` + +```ts +import { OpenGeometry, Wire, OG_PRIMITIVE_POLYLINE } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const path = new Wire(OG_PRIMITIVE_POLYLINE, { + points: [ + [0, 0, 0], + [2, 0, 0], + [2, 0, 2], + ], +}); +console.log(path.bodyType, path.validity().closed); +``` + +## Constructor + +`new Wire(kind: string, params: Record, options?: BodyOptions)` + +| `kind` | `params` | +| ------------------------ | ------------------------------------ | +| `OG_PRIMITIVE_RECTANGLE` | `{ width, breadth }` | +| `OG_PRIMITIVE_CIRCLE` | `{ radius }` | +| `OG_PRIMITIVE_POLYLINE` | `{ points, closed? }` | +| `OG_PRIMITIVE_PROFILE` | `{ start, segments, closed }` | +| `OG_PRIMITIVE_ARC` | `{ radius, startAngle, sweepAngle }` | + +A kind that makes another body type throws `BodyTypeMismatch`. See [Primitives](/opengeometry/guides/primitives). + +## Methods + +`duplicate(options?)` and `instance(options?)` return a `Wire`. Everything else is on [Body methods](/opengeometry/api/body). + +A wire is used as the `profile`, a `hole` or the `path` of an operation. `classifyPoint` throws `InvalidOperand` on a wire. diff --git a/docs/opengeometry/changelog.mdx b/docs/opengeometry/changelog.mdx new file mode 100644 index 00000000..19cf3a3a --- /dev/null +++ b/docs/opengeometry/changelog.mdx @@ -0,0 +1,43 @@ +--- +title: Changelog +description: What changed in each OpenGeometry release, newest first. +icon: clock-rotate-left +rss: true +--- + + + +3.0 is a new API. Code written for 2.0 does not run without changes. Follow [Migrate from 2.0](/opengeometry/migrate-from-2-0). + +### Check these when you upgrade + +- **Breaking: three body classes.** Make bodies with `new Wire(kind, params)`, `new Solid(kind, params)` and `new Sheet(OG_OPERATION_SWEEP, params)`. The 2.0 classes such as `Cuboid`, `Polygon`, `Sweep` and `AnalyticSolid` are gone. +- **Breaking: arrays, not `Vector3`.** Points and vectors are `[x, y, z]`. +- **Breaking: move with `transform`.** Setting `position`, `rotation` or `scale` is reverted. +- **Breaking: start the kernel first.** Await `OpenGeometry.create(input, options)` once. `workerURL` goes in the second argument. +- **Breaking: 2D calls are statics.** Use `OpenGeometry.booleanRegions2D`, `OpenGeometry.offsetRingVariable` and the others. Offsets return line and arc edges. +- **Breaking: `OpenGeometry.exportIfcBody(solid)`** replaces `solid.prepareIfcExchange()`. +- **Breaking: `OGError`.** Catch it and branch on `code`. +- **Breaking: the shell hollows in place.** Use `solid.operate(OG_OPERATION_SHELL, { thickness })`. +- **Breaking: display follows drawing.** A body gets its mesh when it is drawn or walked. Its `surface` and `outline` meshes are static: call `updateMatrix()` after you move them yourself. +- **Smooth edges.** Outlines leave out smooth edges, and faceted curves shade smooth. Set `appearance.smoothAngle` to `0` for the 2.0 look. +- **Removed:** IFC file text, STL and PDF export, projection, loft, public triangulation, curves other than lines, circles and arcs, and wedges. + +### Added + +- Solid primitives: cuboid, cylinder, cylinder sector, sphere, cone, torus and polyhedron. Wire primitives: rectangle, circle, polyline, profile and arc. See [Primitives](/opengeometry/guides/primitives). +- [Extrude](/opengeometry/guides/extrude), [sweep](/opengeometry/guides/sweep) and [revolve](/opengeometry/guides/revolve), with exact arcs. +- [Booleans](/opengeometry/guides/booleans) with up to a hundred tools, and [shell](/opengeometry/guides/shell). +- [Rebuild and mirror](/opengeometry/guides/rebuild-and-mirror), [assemblies, copies and instances](/opengeometry/guides/transforms-and-assemblies), and [marks and transactions](/opengeometry/concepts/history). +- [Queries](/opengeometry/guides/measure-and-validate): bounds, B-rep, face normals, point classification, measured volume and area, validity. +- [Display for Three.js](/opengeometry/concepts/display), [picking](/opengeometry/guides/picking) and [host-drawn layers](/opengeometry/guides/use-your-threejs-scene). +- [STEP export](/opengeometry/guides/export-step) and the [IFC exchange body](/opengeometry/guides/ifc-exchange-body). +- Exact curved insets: `OpenGeometry.insetCurvedRegion2D` and `OpenGeometry.offsetCurvedRingVariable`. See [Regions and offsets](/opengeometry/guides/regions-and-offsets). + +### Fixed + +- A circular hole away from the profile centre extrudes. +- Offset corners are exact arcs. +- A point inside one of two touching solids of a body is `Inside`. + + diff --git a/docs/opengeometry/concepts/architecture.mdx b/docs/opengeometry/concepts/architecture.mdx new file mode 100644 index 00000000..fe2f85cd --- /dev/null +++ b/docs/opengeometry/concepts/architecture.mdx @@ -0,0 +1,38 @@ +--- +title: Architecture +description: How the Rust kernel, the TypeScript SDK, the display worker and your Three.js scene fit together. +icon: sitemap +--- + +OpenGeometry has three parts. You call only the SDK. + +| Part | What it does | +| -------------- | ---------------------------------------------------------------------------------------------------------- | +| Kernel | Rust, compiled to WebAssembly. Holds every shape as an exact B-rep and runs the modelling and the exports. | +| SDK | TypeScript. Gives you `Wire`, `Solid`, `Sheet`, `SystemAssembly` and the `OpenGeometry` statics. | +| Display worker | A web worker that turns shapes into Three.js meshes, so the page stays responsive. It can also run inline. | + +## One document + +`OpenGeometry.create` starts one kernel with one document. Every body you make goes into it. `OpenGeometry.reset()` empties it. + +The document is a graph of nodes. A node is a body or an assembly, with a placement and an optional parent. A body points to a shape. Two instances can point to the same shape. + +## Exact shapes, display meshes + +The kernel keeps exact geometry: planes, cylinders, cones, spheres, tori, lines, circles and arcs. Booleans, measurements and STEP export use this exact geometry. + +The meshes that you see are a separate, approximate copy, made for display only. The kernel makes them when the scene asks, at the level of detail that the camera needs. See [Display](/opengeometry/concepts/display). + +## Your scene stays yours + +Every body is a `THREE.Group` with two children: a `surface` mesh and an `outline` line set. You add bodies to your own scene, with your own camera, lights and renderer. OpenGeometry makes no scene, no camera and no controls. + +## Calls are synchronous + +Making and editing bodies is synchronous: a `new Solid(...)` or an `operate(...)` has finished when the call returns. Only `create`, `settled` and `exportStep` return promises. + +## Next + +- [Bodies](/opengeometry/concepts/bodies): wires, sheets, solids, shapes and instances. +- [Coordinates and planes](/opengeometry/concepts/coordinates-and-planes): units, axes and where a profile lands. diff --git a/docs/opengeometry/concepts/bodies.mdx b/docs/opengeometry/concepts/bodies.mdx new file mode 100644 index 00000000..f8111a1c --- /dev/null +++ b/docs/opengeometry/concepts/bodies.mdx @@ -0,0 +1,65 @@ +--- +title: Bodies +description: Wires, sheets and solids, the shapes they hold, and the difference between a copy and an instance. +icon: cube +--- + +A body is a node in the document that holds a shape. There are three kinds. + +| Class | `bodyType` | What it is | Made by | +| ------- | ---------- | ----------------------------------------- | -------------------------------------------------------------------------------- | +| `Wire` | `'Wire'` | Lines and arcs, open or closed. No faces. | Rectangle, circle, polyline, profile, arc | +| `Sheet` | `'Sheet'` | Faces that enclose no volume. | A sweep with `caps: false` | +| `Solid` | `'Solid'` | Closed faces around a volume. | Cuboid, cylinder, sphere and the other solid primitives; extrude, sweep, revolve | + +The constructor takes a kind, its parameters and options: + +```ts +import { OpenGeometry, Solid, Wire, OG_OPERATION_EXTRUDE, OG_PRIMITIVE_CIRCLE } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const circle = new Wire(OG_PRIMITIVE_CIRCLE, { radius: 0.5 }, { ogId: 'post-profile' }); +const post = new Solid(OG_OPERATION_EXTRUDE, { profile: circle, distance: 2.4 }, { ogId: 'post' }); +console.log(circle.bodyType, post.bodyType, post.ogId); +``` + +## Identity + +Each body has an `ogId`. Pass your own in the options, or let the SDK make one. Use it to find the body again, for example in a picking result or a STEP report. + +## Inputs stay separate + +An operation reads its inputs when you call it. The result does not follow them later: + +- The wire that you extruded stays a separate body. Changing it later does not change the solid. +- The tools of an `operate` call stay separate, live solids. Moving or disposing a tool later does not change the target. +- A body is drawn only if you add it to the scene. + +## Shapes, copies and instances + +A body points to a shape. Two ways make a second body from the first: + +| Call | Shape | An edit of one body | +| ------------------ | ---------- | ------------------------------------------------------------ | +| `body.duplicate()` | A new copy | Changes that body only | +| `body.instance()` | Shared | Throws `SharedShape`, unless you pass `{ instances: 'all' }` | + +`getInstanceCount()` gives the number of bodies that share the shape. `makeUnique()` gives a body its own copy, so you can edit it alone. Instances are cheap: the kernel stores the shape and its display mesh once. + +## Edits + +Shape edits change the body in place and give its shape a new revision: + +- `solid.operate(...)`: booleans and shell. +- `body.rebuild(kind, params)`: new parameters. A wire stays a wire and a solid stays a solid. An earlier `operate` result is gone, so call `operate` again after it. +- `body.mirror(plane)`: a reflection across a plane. + +## Dispose + +Call `dispose()` on a body or an assembly that you no longer need. A disposed body throws `Disposed` on every call. If a [mark](/opengeometry/concepts/history) is live, a rollback can bring the body back. + +`clone()` gives a display copy for Three.js only, with no kernel shape. `copy()` throws; use `duplicate()`. diff --git a/docs/opengeometry/concepts/coordinates-and-planes.mdx b/docs/opengeometry/concepts/coordinates-and-planes.mdx new file mode 100644 index 00000000..40043342 --- /dev/null +++ b/docs/opengeometry/concepts/coordinates-and-planes.mdx @@ -0,0 +1,66 @@ +--- +title: Coordinates and planes +description: Units, axes, the plane option of a primitive, and where a profile point lands in the world. +icon: compass +--- + +- Every point and vector is an `[x, y, z]` array. +- Model units are metres. +- Y is up, as in Three.js. +- Angles of primitives are in radians. Angles of transforms are in degrees. + +## The plane of a primitive + +Each primitive is made on a plane. The `plane` option sets it: + +| Field | Default | Meaning | +| ------------ | ----------- | -------------------------------------------- | +| `origin` | `[0, 0, 0]` | Where the primitive's centre or start goes | +| `normal` | `[0, 1, 0]` | The plane's normal; an extrude goes this way | +| `xDirection` | `[1, 0, 0]` | The plane's u axis | + +By default this is the ground plane through the origin. `plane` applies to primitives only, not to operations. + +## Where a profile point lands + +A profile, a polyline in a profile, and the angles of an arc are given in the plane's own `[u, v]` axes. The u axis is `xDirection`. The v axis is `normal × xDirection`. + +On the default ground plane, v runs along −Z. A point `[u, v]` lands at world `(u, 0, −v)`. If you miss the sign, a D-shape comes out the wrong way round. + +With `plane: { normal: [0, 0, 1], xDirection: [1, 0, 0] }`, an upright plane facing +Z, a point `[u, v]` lands at `(u, v, 0)`. + +```ts +import { OpenGeometry, Wire, OG_PRIMITIVE_PROFILE } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const upright = { + normal: [0, 0, 1] as [number, number, number], + xDirection: [1, 0, 0] as [number, number, number], +}; +const triangle = new Wire( + OG_PRIMITIVE_PROFILE, + { start: [0, 0], segments: [{ to: [1, 0] }, { to: [0, 1] }, { to: [0, 0] }], closed: true }, + { plane: upright }, +); +console.log(triangle.getBounds()); +``` + +The bounds are about `[0, 0, 0, 1, 1, 0]`: the triangle stands in the XY plane. + +## Positive angles + +A positive angle turns counter-clockwise, seen from the side that the plane normal points to. On the default ground plane that is seen from above, from +X towards −Z. + +## Placement + +Each node has a placement: `{ origin, xDirection, normal, scale }`. `getPlacement()` reads it relative to the parent. `getWorldPlacement()` reads it in the world. Change it with `transform`. See [Transforms and assemblies](/opengeometry/guides/transforms-and-assemblies). + +A body's own coordinates are those of `getBrep()`, before its placement. `classifyPoint`, `faceNormalAt`, `measure` and `mirror` use them. + +## Tolerances + +The geometric tolerance is `1e-8` m. The 2D region calls use `OG_REGION_TOLERANCE`, `1e-6` m. Sizes must be above four times the geometric tolerance. diff --git a/docs/opengeometry/concepts/display.mdx b/docs/opengeometry/concepts/display.mdx new file mode 100644 index 00000000..6ae56177 --- /dev/null +++ b/docs/opengeometry/concepts/display.mdx @@ -0,0 +1,82 @@ +--- +title: Display +description: How a body gets its mesh, level of detail, smooth edges, appearance, and when to call flush or settled. +icon: display +--- + +A body is a `THREE.Group` with two children: + +- `surface`: a `THREE.Mesh` with a `MeshStandardMaterial`. The scene needs a light. +- `outline`: a `THREE.LineSegments` with the body's edges. + +## Rendering asks for geometry + +The kernel makes a display mesh only for a body that is displayed. A body is displayed when it is drawn, or when `updateMatrixWorld` walks it: + +- **Drawn:** its `surface` or `outline` runs `onBeforeRender`. The new mesh is installed after that render, so the next frame shows it. +- **Walked:** `scene.updateMatrixWorld()` reaches it. The mesh is installed at once. +- **Marked:** you call `OpenGeometry.markDisplayed(bodies)` for bodies that your own layers draw. See [Use your Three.js scene](/opengeometry/guides/use-your-threejs-scene). + +A body that is neither drawn nor walked for a full render pass is not displayed. It gets no new mesh until it is displayed again. + +So render in a loop. Or render once, `await OpenGeometry.settled()`, and render again: + +```ts +import * as THREE from 'three'; +import { OpenGeometry, Solid, OG_PRIMITIVE_SPHERE } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const ball = new Solid(OG_PRIMITIVE_SPHERE, { radius: 1 }); +const scene = new THREE.Scene(); +scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 2), ball); +const camera = new THREE.PerspectiveCamera(50, 1, 0.1, 100); +camera.position.set(3, 2, 3); +camera.lookAt(0, 0, 0); +const renderer = new THREE.WebGLRenderer(); +renderer.render(scene, camera); +const { failed } = await OpenGeometry.settled(); +renderer.render(scene, camera); +console.log(failed.length); +``` + +`settled` resolves when every displayed body has its mesh. `failed` lists the bodies whose mesh failed, with the error. If nothing was rendered, `settled` returns at once. + +## Mesh now + +`OpenGeometry.flush({ geometry: 'sync' })` meshes every displayed body on the calling thread before it returns. Add `bodies` to mesh only those. Use it in tests, in Node, or when one edited body must be current before the next frame. See [`flush`](/opengeometry/api/display#flush). + +## Level of detail + +The kernel picks the mesh detail from the camera. A body that is small on the screen gets a coarser mesh. While the camera moves, the kernel accepts a coarser mesh; when it stops, it refines. + +- `OpenGeometry.observeCamera(renderer, camera)`: tell the kernel which camera draws each frame. +- `OpenGeometry.setCameraMotion(true)`: tell the kernel that the camera moves, for example from your controls. +- `OpenGeometry.setDisplayDeflection(world)`: set a fixed deflection in world metres for every body. Call it with no value to go back to the camera. +- `appearance.deflection`: set a fixed deflection for one body. + +Deflection is the largest distance between the mesh and the exact surface. + +## Smooth edges + +The outline leaves out smooth edges. An edge is smooth when its two faces are tangent-continuous, or when two planes fold by less than the smooth angle. The default smooth angle is 20°. Planar faces average their normals across smooth edges, so a polygon that approximates a curve shades as one curve. + +Set `appearance.smoothAngle` to change the angle for one body, in degrees from 0 up to but not including 90. `0` keeps every fold line. + +## Appearance + +Pass `appearance` in the options, or call `setAppearance` later: + +| Field | Default | Meaning | +| ------------- | ------------------------------------------- | ------------------------------------- | +| `color` | `0x2563eb` for a wire, `0x6699dd` otherwise | A number, as in Three.js | +| `opacity` | `1` | 0 to 1 | +| `outline` | `false` for a solid, `true` otherwise | Show the outline | +| `pickOutline` | `true` for a wire, `false` otherwise | Raycasts hit the outline | +| `deflection` | none | A fixed mesh deflection for this body | +| `smoothAngle` | 20 | The smooth-edge angle in degrees | + +Do not change a body's materials yourself. Use `setAppearance`. diff --git a/docs/opengeometry/concepts/errors.mdx b/docs/opengeometry/concepts/errors.mdx new file mode 100644 index 00000000..d50f91ac --- /dev/null +++ b/docs/opengeometry/concepts/errors.mdx @@ -0,0 +1,86 @@ +--- +title: Errors and limits +description: The OGError codes, the events the runtime sends, what a fatal error means, and the limits of 3.0. +icon: triangle-exclamation +--- + +Every failure throws an `OGError`. Catch it and branch on `code`: + +```ts +import { OGError, OpenGeometry, Solid, OG_PRIMITIVE_SPHERE } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +try { + new Solid(OG_PRIMITIVE_SPHERE, { radius: 0 }); +} catch (error) { + if (error instanceof OGError && error.code === 'InvalidParameter') + console.log(error.call, error.message); +} +``` + +An `OGError` has: + +- `code`: a stable name, such as `InvalidParameter`. +- `call`: the call that failed, such as `Solid.constructor`. +- `message`: a text for people. Do not parse it. +- `details`: an object with more data for some codes. For a failed `operate` it has `handlers`, `attempted`, `families`, `toolIndex` and `ogIds`. + +A call that throws leaves the document as it was. + +## Codes + +| Code | When | +| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | +| `NotInitialised` | A call before `OpenGeometry.create` finished | +| `InvalidParameter` | A parameter is missing, has the wrong type, or is out of range | +| `InvalidGeometry` | The input geometry cannot make a valid shape | +| `InvalidOperand` | The call does not apply to this body, for example `classifyPoint` on a wire, a wire in `exportStep`, or `copy()` | +| `BodyTypeMismatch` | The kind makes another body type than the class, such as `new Wire(OG_PRIMITIVE_CUBOID, ...)`, or a rebuild would change the body type | +| `InvalidTransform` | A transform cannot be held in a placement, for example a negative scale | +| `SharedShape` | An edit of a shape that instances share, without `{ instances: 'all' }` | +| `ToolSharesTargetShape` | A tool of `operate` is the target, or has the target's shape | +| `DuplicateNode` | An `ogId` that is already used, or a tool listed twice | +| `UnknownNode` | An `ogId` that is not in the document | +| `CycleDetected` | An `addChild` that would make a node its own ancestor | +| `NotAChild` | A `removeChild` of a node that is not a child | +| `EmptyResult` | A boolean that leaves nothing, or a STEP selection with no solid in it | +| `Disposed` | A call on a disposed body or on a body from a reset runtime | +| `InvalidMark` | A call on a released mark | +| `CoverageGap` | The kernel has no method for this pair of surfaces yet. `details.families` names the pair | +| `UnresolvedIntersection` | The kernel could not trace an intersection | +| `InvalidTopology` | The result would not be a valid B-rep | +| `UnsupportedGeometry` | The call needs exact geometry, and the body has approximate geometry | +| `SweepSelfIntersection` | A sweep would cut through itself | +| `LimitExceeded` | A size limit was reached, such as the 2 000 000 triangle cap of `measure` | +| `UnresolvedTessellation` | The kernel could not mesh a face | +| `WorkerFailure` | The display worker failed | +| `Cancelled` | A display request was replaced by a newer one, or a body had no mesh when `settled` resolved | +| `RevisionConflict` | An internal revision check failed. Report it as a bug | +| `KernelPanic` | The kernel stopped. See below | + +## Events + +`OpenGeometry.on(event, handler)` subscribes to the runtime. It returns a function that unsubscribes. + +| Event | When | +| ------------ | ------------------------------------------------------------------------------------------- | +| `'geometry'` | A display mesh was made | +| `'warning'` | Something was corrected, such as a `PlacementOverwritten` when code set `position` directly | +| `'error'` | A background failure, such as a failed mesh or a listener that threw | +| `'fatal'` | The kernel panicked | + +## A fatal error + +After a `KernelPanic`, the runtime sends `'fatal'` and refuses every kernel call with `KernelPanic`. Call `OpenGeometry.reset()`, then make your bodies again. + +## Limits + +- One to a hundred tool solids in one `operate` call. +- `measure` caps its mesh at 2 000 000 triangles. +- A 2D region boolean takes at most 100 000 points or edges across both operands. +- Sizes must be above four times the geometric tolerance, `4e-8` m. +- Some pairs of curved surfaces are not covered yet and throw `CoverageGap`. Some refused booleans take seconds, because the kernel tries several methods before it refuses. diff --git a/docs/opengeometry/concepts/history.mdx b/docs/opengeometry/concepts/history.mdx new file mode 100644 index 00000000..f88a3650 --- /dev/null +++ b/docs/opengeometry/concepts/history.mdx @@ -0,0 +1,70 @@ +--- +title: History +description: Undo a group of edits with a mark, and run edits as a transaction that rolls back if it throws. +icon: clock-rotate-left +--- + +The kernel keeps the document's history. A mark is a point in that history that you can go back to. + +## Marks + +```ts +import { OpenGeometry, Solid, OG_PRIMITIVE_CUBOID, OG_TRANSFORM_TRANSLATE } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const box = new Solid(OG_PRIMITIVE_CUBOID, { width: 1, height: 1, depth: 1 }); +const mark = OpenGeometry.mark(); +box.transform(OG_TRANSFORM_TRANSLATE, { offset: [2, 0, 0] }); +const extra = new Solid(OG_PRIMITIVE_CUBOID, { width: 0.5, height: 0.5, depth: 0.5 }); +mark.rollback(); +console.log(box.getWorldPlacement().origin, extra.ogId); +mark.release(); +``` + +After `rollback`, the box is back at the origin and `extra` is gone from the document. + +- `rollback()` takes the document back to the mark: shapes, placements, the tree, and bodies made or disposed after it. The mark stays live, so you can roll back to it again. Later marks are released. +- `release()` ends the mark. Release every mark that you no longer need: a live mark keeps old revisions in memory. +- A released mark throws `InvalidMark`. +- `OpenGeometry.markStats()` returns `{ liveMarks, retainedRevisions }`. + +A body that is disposed while a mark is live is hidden, not freed, so a rollback can bring it back. It is freed when no mark can bring it back. + +## Transactions + +`OpenGeometry.transaction(fn)` runs `fn` between a mark and its release. If `fn` throws, it rolls back first, then throws again: + +```ts +import { + OGError, + OpenGeometry, + Solid, + OG_OPERATION_SUBTRACT, + OG_PRIMITIVE_CUBOID, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const slab = new Solid(OG_PRIMITIVE_CUBOID, { width: 4, height: 0.2, depth: 4 }); +const hole = new Solid(OG_PRIMITIVE_CUBOID, { width: 1, height: 1, depth: 1 }); +try { + OpenGeometry.transaction(() => { + slab.operate(OG_OPERATION_SUBTRACT, { tools: [hole] }); + slab.rebuild(OG_PRIMITIVE_CUBOID, { width: -1, height: 0.2, depth: 4 }); + }); +} catch (error) { + if (error instanceof OGError) console.log(error.code, slab.getReport() === null); +} +``` + +The rebuild throws `InvalidParameter`, so the subtraction is rolled back too. + +- `fn` must be synchronous. A function that returns a promise throws `InvalidParameter`. +- `{ dryRun: true }` always rolls back. Use it to test whether a group of edits works, and to read values on the way. diff --git a/docs/opengeometry/examples.mdx b/docs/opengeometry/examples.mdx new file mode 100644 index 00000000..4e53cf25 --- /dev/null +++ b/docs/opengeometry/examples.mdx @@ -0,0 +1,37 @@ +--- +title: Examples +description: Runnable example pages for OpenGeometry 3.0, and how to run them from a clone of the repository. +icon: play +--- + +The examples are working 3.0 code. They are in [`main/opengeometry-three/examples-vite/`](https://github.com/OpenGeometry-io/OpenGeometry/tree/main/main/opengeometry-three/examples-vite) in the repository. Hosted demos are at [demos.opengeometry.io](https://demos.opengeometry.io). + +| Page | What it shows | +| --------------------------------------------- | ----------------------------------------------------------------------------------------- | +| `index.html` | A showcase: walls, an opening, a sweep and booleans in one scene, with STEP export | +| `sweep.html` | Three open sweep frames along polyline paths | +| `boolean.html` | Union, subtract and intersect of two cuboids, with the boolean report | +| `opening.html` | A cutter subtracted from a wall on each change | +| `operations/analytic-boolean-operations.html` | Booleans of two cylinders, with exact curved faces | +| `operations/curved-meets-straight.html` | A curved profile united with a straight one, where a side runs on along an arc's tangent | +| `operations/sweep-arc-path.html` | A profile swept along a path with an arc bend, with the bend radius and angle as controls | +| `operations/step-export.html` | One cuboid exported as a STEP file, with the export report | +| `shapes/cuboid.html` | A cuboid with width, height, depth and an outline toggle | +| `shapes/cylinder.html` | An exact cylinder. Click a face to inspect it | +| `shapes/rounded-profile.html` | A section with rounded corners, extruded from a line-and-arc profile | + +## Run them + +You need Node.js, Rust with the `wasm32-unknown-unknown` target, and `wasm-pack`: + +```bash +git clone https://github.com/OpenGeometry-io/OpenGeometry.git +cd OpenGeometry +npm --prefix main ci +npm run build +npm run dev-example +``` + +Open the address that Vite prints. + +The examples import the built package by path, `../../../dist/index.js`. In your app, import from `'opengeometry'`. diff --git a/docs/opengeometry/guides/booleans.mdx b/docs/opengeometry/guides/booleans.mdx new file mode 100644 index 00000000..e8879fa3 --- /dev/null +++ b/docs/opengeometry/guides/booleans.mdx @@ -0,0 +1,146 @@ +--- +title: Booleans +description: Subtract, unite and intersect solids, read the boolean report, and handle refused cuts. +icon: object-subtract +--- + +`solid.operate(kind, { tools, instances? })` changes the target solid once: + +| Kind | Result | +| ------------------------ | ----------------------------------- | +| `OG_OPERATION_SUBTRACT` | The target minus every tool | +| `OG_OPERATION_UNION` | The target joined with every tool | +| `OG_OPERATION_INTERSECT` | What the target and the tools share | + +`tools` is one to a hundred solids. The tools stay separate, live solids. Moving or disposing a tool later does not change the target. A tool is drawn only if you add it to the scene. + +## Cut openings into a wall + +```ts +import { + OpenGeometry, + Solid, + Wire, + OG_OPERATION_EXTRUDE, + OG_OPERATION_SUBTRACT, + OG_PRIMITIVE_CUBOID, + OG_PRIMITIVE_RECTANGLE, + OG_TRANSFORM_TRANSLATE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const wall = new Solid(OG_OPERATION_EXTRUDE, { + profile: new Wire(OG_PRIMITIVE_RECTANGLE, { width: 6, breadth: 0.2 }), + distance: 3, +}); +const door = new Solid(OG_PRIMITIVE_CUBOID, { width: 0.9, height: 2.1, depth: 0.4 }); +door.transform(OG_TRANSFORM_TRANSLATE, { offset: [-1.5, 0, 0] }); +const pane = new Solid(OG_PRIMITIVE_CUBOID, { width: 1.2, height: 1.2, depth: 0.4 }); +pane.transform(OG_TRANSFORM_TRANSLATE, { offset: [1.2, 0.9, 0] }); +wall.operate(OG_OPERATION_SUBTRACT, { tools: [door, pane] }); +console.log(wall.getReport()?.report.operation, wall.validity().valid); +``` + +## An arched opening + +Make an arch as one closed profile, a straight sill, two jambs and a half-circle head, and extrude it through the wall. This works through a straight or a curved wall: + +```ts +import { + OpenGeometry, + Solid, + Wire, + OG_OPERATION_EXTRUDE, + OG_OPERATION_SUBTRACT, + OG_PRIMITIVE_PROFILE, + OG_PRIMITIVE_RECTANGLE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const wall = new Solid(OG_OPERATION_EXTRUDE, { + profile: new Wire(OG_PRIMITIVE_RECTANGLE, { width: 4, breadth: 0.3 }), + distance: 3, +}); +const arch = new Wire( + OG_PRIMITIVE_PROFILE, + { + start: [-0.3, 0.4], + segments: [ + { to: [0.3, 0.4] }, + { to: [0.3, 1.5] }, + { to: [-0.3, 1.5], arc: { center: [0, 1.5], counterClockwise: true } }, + { to: [-0.3, 0.4] }, + ], + closed: true, + }, + { plane: { origin: [0, 0, -0.5], normal: [0, 0, 1], xDirection: [1, 0, 0] } }, +); +const cutter = new Solid(OG_OPERATION_EXTRUDE, { profile: arch, distance: 1 }); +wall.operate(OG_OPERATION_SUBTRACT, { tools: [cutter] }); +console.log(wall.getReport()?.handlers); +``` + +Use one arch-profile prism. A rectangle prism plus a half-cylinder, whose sides touch along the cylinder, can fail through a curved wall. + +## The report + +`solid.getReport()` returns the report of the last boolean, or `null`: + +- `report.operation`: `'union'`, `'intersection'` or `'subtraction'`. +- `report.face_mappings`: for each face of the inputs, the faces of the result that came from it. +- `report.contacts` and `report.coincident`: where the inputs touch. +- `handlers`: the kernel methods that made the result. +- `revision`: the shape revision of the result. + +A `rebuild` or a `mirror` clears the report. + +## When a boolean is refused + +A refused call throws an `OGError` and leaves the target as it was. `details` says which methods were tried: + +```ts +import { + OGError, + OpenGeometry, + Solid, + OG_OPERATION_SUBTRACT, + OG_PRIMITIVE_CONE, + OG_PRIMITIVE_CUBOID, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const cone = new Solid(OG_PRIMITIVE_CONE, { radiusBottom: 1, radiusTop: 0, height: 1 }); +const box = new Solid( + OG_PRIMITIVE_CUBOID, + { width: 0.5, height: 0.5, depth: 0.5 }, + { plane: { origin: [0, 0.8, 0] } }, +); +try { + cone.operate(OG_OPERATION_SUBTRACT, { tools: [box] }); +} catch (error) { + if (error instanceof OGError) + console.log(error.code, error.details.families, error.details.attempted); +} +``` + +- `CoverageGap`: the kernel has no method for this pair yet. `details.families` names the pair, such as `['cone or frustum', 'cuboid']`. +- `UnresolvedIntersection`: the kernel could not trace the intersection. +- `toolIndex` and `ogIds` name the tool that failed. + +Some refused cuts are slow, because the kernel tries several methods before it refuses. + +## Instances + +If the target's shape is shared, pass `{ instances: 'all' }` to cut every instance, or call `makeUnique()` first. Otherwise the call throws `SharedShape`. A tool may not be the target or have the target's shape. diff --git a/docs/opengeometry/guides/export-step.mdx b/docs/opengeometry/guides/export-step.mdx new file mode 100644 index 00000000..7af0c84c --- /dev/null +++ b/docs/opengeometry/guides/export-step.mdx @@ -0,0 +1,75 @@ +--- +title: Export STEP +description: Write bodies and assemblies to a STEP file in millimetres or metres, with Y or Z up, and read the export report. +icon: file-export +--- + +`OpenGeometry.exportStep(options)` writes a STEP file. It returns a promise of `{ text, report }`. + +| Option | Default | Meaning | +| ----------- | ---------------- | -------------------------------------------------------------- | +| `nodes` | required | Bodies, assemblies, or `ogId` strings | +| `unit` | `'millimetre'` | `'millimetre'` or `'metre'` | +| `upAxis` | `'Z'` | `'Z'` or `'Y'`. The model is Y up; the file is Z up by default | +| `name` | none | The product name in the file | +| `timestamp` | the current time | The time in the file header, for files that must not change | + +```ts +import { + OpenGeometry, + Solid, + SystemAssembly, + OG_PRIMITIVE_CUBOID, + OG_PRIMITIVE_CYLINDER, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const stool = new SystemAssembly({ ogId: 'stool' }); +new Solid( + OG_PRIMITIVE_CYLINDER, + { radius: 0.18, height: 0.04 }, + { parent: stool, plane: { origin: [0, 0.45, 0] } }, +); +new Solid(OG_PRIMITIVE_CUBOID, { width: 0.04, height: 0.45, depth: 0.04 }, { parent: stool }); + +const { text, report } = await OpenGeometry.exportStep({ + nodes: [stool], + unit: 'millimetre', + upAxis: 'Z', + name: 'Stool', + timestamp: '2026-01-01T00:00:00', +}); +console.log(report.products, report.solids, text.startsWith('ISO-10303-21;')); +``` + +## Save the file in a browser + +```ts +import { OpenGeometry, Solid, OG_PRIMITIVE_CUBOID } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const box = new Solid(OG_PRIMITIVE_CUBOID, { width: 1, height: 1, depth: 1 }); +const { text } = await OpenGeometry.exportStep({ nodes: [box] }); +const link = document.createElement('a'); +link.href = URL.createObjectURL(new Blob([text], { type: 'model/step' })); +link.download = 'box.step'; +link.click(); +``` + +## The report + +`report` counts what was written: `products`, `solids`, `faces`, `edges`, `cavityShells`, `entities` and `bytes`. It also gives the `exchangeErrorBound` and the `geometricTolerance`, and one entry per body in `bodies`. `skipped` lists the nodes that were not written, with a reason. + +## Rules + +- A wire or a sheet cannot be exported on its own. It throws `InvalidOperand`. +- A selection with no solid in it throws `EmptyResult`. +- Planes, cylinders, cones, spheres and tori are written as exact STEP surfaces. `report.fittedCurves` counts the curves that had to be fitted. diff --git a/docs/opengeometry/guides/extrude.mdx b/docs/opengeometry/guides/extrude.mdx new file mode 100644 index 00000000..1afb2832 --- /dev/null +++ b/docs/opengeometry/guides/extrude.mdx @@ -0,0 +1,77 @@ +--- +title: Extrude +description: Raise a closed wire along its plane normal into a solid, with holes. +icon: arrow-up-from-bracket +--- + +`OG_OPERATION_EXTRUDE` raises a closed wire into a solid. The parameters are `{ profile, holes?, distance }`: + +- `profile`: a closed wire, such as a rectangle, a circle, a closed polyline or a closed profile. +- `holes`: closed wires inside the profile, on the same plane. +- `distance`: the height, along the profile's plane normal. + +```ts +import { + OpenGeometry, + Solid, + Wire, + OG_OPERATION_EXTRUDE, + OG_OPERATION_PARAMS_EXTRUDE, + OG_PRIMITIVE_CIRCLE, + OG_PRIMITIVE_RECTANGLE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const plate = new Wire(OG_PRIMITIVE_RECTANGLE, { width: 2, breadth: 1 }); +const bolt = new Wire(OG_PRIMITIVE_CIRCLE, { radius: 0.1 }, { plane: { origin: [0.6, 0, 0] } }); +const slab = new Solid( + OG_OPERATION_EXTRUDE, + OG_OPERATION_PARAMS_EXTRUDE({ profile: plate, holes: [bolt], distance: 0.05 }), +); +console.log(slab.getBrep().topology.faces.length); +``` + +## A line-and-arc profile + +A closed `OG_PRIMITIVE_PROFILE` extrudes into exact planes and cylinders. This is a quarter ring sector, 3 m high: + +```ts +import { + OpenGeometry, + Solid, + Wire, + OG_OPERATION_EXTRUDE, + OG_PRIMITIVE_PROFILE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const profile = new Wire(OG_PRIMITIVE_PROFILE, { + start: [1, 0], + segments: [ + { to: [2, 0] }, + { to: [0, 2], arc: { center: [0, 0], counterClockwise: true } }, + { to: [0, 1] }, + { to: [1, 0], arc: { center: [0, 0], counterClockwise: false } }, + ], + closed: true, +}); +const sector = new Solid(OG_OPERATION_EXTRUDE, { profile, distance: 3 }); +console.log(sector.validity().valid); +``` + +A curved wall is the same kind of profile, extruded up. Openings in it are booleans. See [Booleans](/opengeometry/guides/booleans). + +## Rules + +- The profile must be closed. An open wire throws `InvalidParameter`. +- A hole that encloses the whole profile throws `InvalidParameter`. +- The extrude goes along the profile's plane normal. On the default ground plane that is +Y. +- The wires stay separate bodies. Changing one later does not change the solid. diff --git a/docs/opengeometry/guides/ifc-exchange-body.mdx b/docs/opengeometry/guides/ifc-exchange-body.mdx new file mode 100644 index 00000000..4a983bb7 --- /dev/null +++ b/docs/opengeometry/guides/ifc-exchange-body.mdx @@ -0,0 +1,44 @@ +--- +title: IFC exchange body +description: Read a solid's exact geometry as an IFC exchange body, in world metres with Z up, for your IFC writer. +icon: building +--- + +OpenGeometry does not write IFC files. It gives the exact geometry of a solid in a form that an IFC writer can turn into an `IfcAdvancedBrep` or a CSG body. + +```ts +import { + OpenGeometry, + Solid, + OG_PRIMITIVE_CUBOID, + OG_TRANSFORM_TRANSLATE, + type AnalyticExchangeBodyV2, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const solid = new Solid(OG_PRIMITIVE_CUBOID, { width: 2, height: 3, depth: 0.2 }); +solid.transform(OG_TRANSFORM_TRANSLATE, { offset: [4, 0, 1] }); +const body: AnalyticExchangeBodyV2 = OpenGeometry.exportIfcBody(solid); +console.log(body.representation_type, body.up_axis, body.solids.length, body.faces.length); +``` + +This prints `AdvancedBrep Z 1 6`. + +## What you get + +`AnalyticExchangeBodyV2` is a read-only object: + +- `schema_version`: `2`. +- World metres, with Z up. +- `representation_type`: `'AdvancedBrep'`, or `'CSG'` for a solid with a cavity. +- `entities`, `solids` and `faces`: the geometry and topology for the writer. Values are of type `IfcPreparedValue`. + +It is the same version 2 object as `prepareIfcExchange()` gave in 2.0.18. + +## Rules + +`exportIfcBody` takes one solid. A sheet, a wire or an assembly throws. diff --git a/docs/opengeometry/guides/measure-and-validate.mdx b/docs/opengeometry/guides/measure-and-validate.mdx new file mode 100644 index 00000000..26cff78c --- /dev/null +++ b/docs/opengeometry/guides/measure-and-validate.mdx @@ -0,0 +1,88 @@ +--- +title: Measure and validate +description: Read volume and area within a stated error bound, classify points, read bounds and the B-rep, and check that a body is valid. +icon: ruler-combined +--- + +## Volume and area + +`body.measure({ deflection? })` returns `{ volume, area, errorBound, areaErrorBound, deflection }`, in the body's own coordinates. A scale in the placement is not applied. + +```ts +import { OpenGeometry, Solid, OG_PRIMITIVE_CYLINDER, type Measure } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const leg = new Solid(OG_PRIMITIVE_CYLINDER, { radius: 0.1, height: 0.7 }); +const size: Measure = leg.measure({ deflection: 0.001 }); +const exact = Math.PI * 0.1 * 0.1 * 0.7; +console.log(Math.abs(size.volume - exact) <= size.errorBound); +``` + +The values are approximate, with a stated bound: + +- `|volume − exact| ≤ errorBound`. +- `|area − exact| ≤ areaErrorBound`. +- A body with only flat faces measures exactly, within `1e-10` of its size. +- A smaller `deflection` gives a smaller bound and a slower call. The default is `0.01`. +- A bound is `Infinity` when a triangle is too coarse to bound. `JSON.stringify` writes it as `null`. + +A `deflection` that is not a positive finite number throws `InvalidParameter`. A mesh of more than 2 000 000 triangles throws `LimitExceeded`. The call does not change the document. + +## Validity + +`body.validity()` returns `{ valid, closed, bodyType }`, and `error: { code, message }` when the body is not valid. + +```ts +import { OpenGeometry, Solid, OG_PRIMITIVE_CUBOID, type Validity } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const box = new Solid(OG_PRIMITIVE_CUBOID, { width: 1, height: 1, depth: 1 }); +const check: Validity = box.validity(); +console.log(check); +``` + +A valid closed solid gives `{ valid: true, closed: true, bodyType: 'Solid' }`. `closed` is true when every shell of a sheet or a solid is closed, and when every wire of a wire body is closed. + +## Point classification + +`body.classifyPoint([x, y, z])` says where a point is, in the body's own coordinates: `'Inside'`, `'Outside'`, `'Boundary'` or `'Unknown'`. + +```ts +import { OpenGeometry, Solid, OG_PRIMITIVE_CYLINDER, type PointClassification } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const leg = new Solid(OG_PRIMITIVE_CYLINDER, { radius: 0.1, height: 0.7 }); +const middle: PointClassification = leg.classifyPoint([0, 0.35, 0]); +const top: PointClassification = leg.classifyPoint([0, 0.7, 0]); +console.log(middle, top); +``` + +- A point within `1e-8` of the surface is `'Boundary'`. +- A body is `'Inside'` if any of its solids holds the point. +- A wire or a sheet throws `InvalidOperand`. +- Known limit: on a cylinder, cone or frustum that was mirrored, a point outside the body can read `'Inside'`. +- For a world point, first call `OpenGeometry.flush()`, then `body.worldToLocal(new THREE.Vector3(x, y, z))`. + +## Other queries + +| Call | Returns | +| ----------------------------- | ---------------------------------------------------------------------------------- | +| `getBounds()` | `[minX, minY, minZ, maxX, maxY, maxZ]` in the world, or `null` | +| `getBrep()` | The B-rep in the body's own coordinates: `topology` with faces, edges and vertices | +| `getWorldBrep()` | The same B-rep, placed in the world. It makes no body | +| `faceNormalAt(faceId, point)` | The face's unit normal at a point, in the body's own coordinates | +| `solid.getReport()` | The report of the last boolean, or `null` | + +To turn a normal into the world, call `OpenGeometry.flush()`, then use `new THREE.Vector3(...normal).transformDirection(body.matrixWorld)`. diff --git a/docs/opengeometry/guides/picking.mdx b/docs/opengeometry/guides/picking.mdx new file mode 100644 index 00000000..fedf5515 --- /dev/null +++ b/docs/opengeometry/guides/picking.mdx @@ -0,0 +1,42 @@ +--- +title: Picking +description: Turn a Three.js raycast hit into a body, a face and an edge of the kernel. +icon: arrow-pointer +--- + +Raycast your scene with Three.js as usual. Then pass the hit to `OpenGeometry.resolveHit`: + +```ts +import * as THREE from 'three'; +import { OpenGeometry, Solid, OG_PRIMITIVE_CUBOID } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const box = new Solid(OG_PRIMITIVE_CUBOID, { width: 1, height: 1, depth: 1 }, { ogId: 'box' }); +const scene = new THREE.Scene(); +scene.add(box); +scene.updateMatrixWorld(); +OpenGeometry.flush({ geometry: 'sync' }); + +const raycaster = new THREE.Raycaster(new THREE.Vector3(0, 0.5, 5), new THREE.Vector3(0, 0, -1)); +const [hit] = raycaster.intersectObject(scene, true); +const picked = hit ? OpenGeometry.resolveHit(hit) : undefined; +console.log(picked); +``` + +`resolveHit` returns `{ ogId, shapeRevision, faceId?, edgeId? }`, or `undefined` when the hit is not on a body. + +- `faceId` is set for a hit on the surface. Find the face with `body.getBrep().topology.faces`. +- `edgeId` is set for a hit on the outline. +- `shapeRevision` tells you which revision of the shape was hit. After an edit, the ids can refer to other faces. + +## Outlines + +A raycast hits a body's outline only when `pickOutline` is on. It is on for wires and off for sheets and solids. Turn it on with `body.setAppearance({ pickOutline: true })`. Set `raycaster.params.Line.threshold` to the pick width that you want. + +## Copies of the display + +`body.clone()` makes a display copy for Three.js only. It is not a body, so `resolveHit` returns `undefined` for a hit on it. Call its `dispose()` when you take it out of the scene. diff --git a/docs/opengeometry/guides/primitives.mdx b/docs/opengeometry/guides/primitives.mdx new file mode 100644 index 00000000..b714b70c --- /dev/null +++ b/docs/opengeometry/guides/primitives.mdx @@ -0,0 +1,128 @@ +--- +title: Primitives +description: Make wires and solids from parameters, on the default plane or on a plane of your own. +icon: shapes +--- + +A primitive is a body made from a few parameters. Pass the kind as the first argument of `new Wire` or `new Solid`. + +## Wires + +| Kind | Parameters | Notes | +| ------------------------ | ------------------------------------ | ----------------------------------------------------------------------- | +| `OG_PRIMITIVE_RECTANGLE` | `{ width, breadth }` | Centred on the plane origin. `width` along u, `breadth` along v | +| `OG_PRIMITIVE_CIRCLE` | `{ radius }` | Centred on the plane origin | +| `OG_PRIMITIVE_POLYLINE` | `{ points, closed? }` | `points` are `[x, y, z]` in the body's own space | +| `OG_PRIMITIVE_PROFILE` | `{ start, segments, closed }` | Lines and arcs, points as `[u, v]` in the plane | +| `OG_PRIMITIVE_ARC` | `{ radius, startAngle, sweepAngle }` | Centred on the plane origin. The sweep is not zero and less than a turn | + +### Profile + +A profile starts at `start`. Each segment goes to its `to` point: + +- `{ to }` is a line. +- `{ to, arc: { center, counterClockwise } }` is an arc about `center`. `to` must be on the arc's circle. + +A closed profile must end at its start. Use it as an extrude profile or hole, a sweep profile, or a revolve profile. + +```ts +import { + OpenGeometry, + Wire, + OG_PRIMITIVE_PARAMS_PROFILE, + OG_PRIMITIVE_PROFILE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const slot = new Wire( + OG_PRIMITIVE_PROFILE, + OG_PRIMITIVE_PARAMS_PROFILE({ + start: [0, 0], + segments: [ + { to: [2, 0] }, + { to: [2, 1], arc: { center: [2, 0.5], counterClockwise: true } }, + { to: [0, 1] }, + { to: [0, 0], arc: { center: [0, 0.5], counterClockwise: true } }, + ], + closed: true, + }), +); +console.log(slot.validity().closed); +``` + +A profile refuses repeated points, an arc whose end is not on its circle, segments that cross, and a closed profile that does not end at its start. Each throws `InvalidParameter`. + +## Solids + +| Kind | Parameters | Notes | +| ------------------------------ | -------------------------------------------- | ---------------------------------------------------------------------------------- | +| `OG_PRIMITIVE_CUBOID` | `{ width, height, depth }` | Standing on the plane, centred on the origin in u and v. `height` along the normal | +| `OG_PRIMITIVE_CYLINDER` | `{ radius, height }` | Standing on the plane, axis along the normal | +| `OG_PRIMITIVE_CYLINDER_SECTOR` | `{ radius, height, startAngle, sweepAngle }` | Angles in radians from the plane's x direction | +| `OG_PRIMITIVE_SPHERE` | `{ radius }` | Centred on the plane origin | +| `OG_PRIMITIVE_CONE` | `{ radiusBottom, radiusTop, height }` | A cone or frustum. One radius may be 0. Nearly equal radii make a cylinder | +| `OG_PRIMITIVE_TORUS` | `{ majorRadius, minorRadius }` | A ring torus lying on the plane. The minor radius must be below the major one | +| `OG_PRIMITIVE_POLYHEDRON` | `{ points, faces }` | Planar faces as rings of point indices, counter-clockwise seen from outside | + +```ts +import { + OpenGeometry, + Solid, + OG_PRIMITIVE_CONE, + OG_PRIMITIVE_PARAMS_CONE, + OG_PRIMITIVE_PARAMS_SPHERE, + OG_PRIMITIVE_PARAMS_TORUS, + OG_PRIMITIVE_SPHERE, + OG_PRIMITIVE_TORUS, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const knob = new Solid(OG_PRIMITIVE_SPHERE, OG_PRIMITIVE_PARAMS_SPHERE({ radius: 0.03 })); +const pedestal = new Solid( + OG_PRIMITIVE_CONE, + OG_PRIMITIVE_PARAMS_CONE({ radiusBottom: 0.25, radiusTop: 0.15, height: 0.7 }), +); +const ring = new Solid( + OG_PRIMITIVE_TORUS, + OG_PRIMITIVE_PARAMS_TORUS({ majorRadius: 0.2, minorRadius: 0.02 }), +); +console.log(knob.ogId, pedestal.ogId, ring.ogId); +``` + +A size that is not finite, or not above four times the geometric tolerance, throws `InvalidParameter`. + +Not built: horn, spindle and lemon tori, whose minor radius is equal to or above the major one. + +## Typed parameters + +`OG_PRIMITIVE_PARAMS_(params)` returns its argument unchanged. It only gives the object a type, so your editor checks the field names. The entry exports the types too, such as `ProfileParams`, `ArcParams`, `SphereParams`, `ConeParams` and `TorusParams`. + +## On another plane + +Pass `plane` in the options. A cylinder on an upright plane lies along Z: + +```ts +import { OpenGeometry, Solid, OG_PRIMITIVE_CYLINDER } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const pipe = new Solid( + OG_PRIMITIVE_CYLINDER, + { radius: 0.05, height: 2 }, + { plane: { origin: [0, 1, 0], normal: [0, 0, 1], xDirection: [1, 0, 0] } }, +); +console.log(pipe.getBounds()); +``` + +See [Coordinates and planes](/opengeometry/concepts/coordinates-and-planes). diff --git a/docs/opengeometry/guides/rebuild-and-mirror.mdx b/docs/opengeometry/guides/rebuild-and-mirror.mdx new file mode 100644 index 00000000..6ea733cf --- /dev/null +++ b/docs/opengeometry/guides/rebuild-and-mirror.mdx @@ -0,0 +1,71 @@ +--- +title: Rebuild and mirror +description: Give a body new parameters in place, or rebuild it as its reflection across a plane. +icon: arrows-left-right +--- + +## Rebuild + +`body.rebuild(kind, params, { instances? })` gives an existing body new parameters. The body keeps its `ogId`, its placement, its parent and its place in your scene. Its shape gets a new revision. + +```ts +import { OpenGeometry, Solid, OG_PRIMITIVE_CUBOID } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const table = new Solid(OG_PRIMITIVE_CUBOID, { width: 1.6, height: 0.75, depth: 0.8 }); +table.rebuild(OG_PRIMITIVE_CUBOID, { width: 2, height: 0.75, depth: 0.9 }); +console.log(table.getBounds()); +``` + +- The kind may change, but a wire stays a wire and a solid a solid. A change of body type throws `BodyTypeMismatch`. +- `rebuild` replaces the shape, so an earlier `operate` result is gone. Call `operate` again after it. +- A shape shared by instances needs `{ instances: 'all' }`, or `makeUnique()` first. + +## Mirror + +`body.mirror({ origin, normal }, { instances? })` rebuilds the shape as its reflection across the plane through `origin` with normal `normal`. Both are in the body's own coordinates. The normal does not need unit length. + +This makes a right chair arm from a copy of the left arm: + +```ts +import { + OpenGeometry, + Solid, + Wire, + OG_OPERATION_EXTRUDE, + OG_PRIMITIVE_PROFILE, + type MirrorPlane, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const outline = new Wire(OG_PRIMITIVE_PROFILE, { + start: [0, 0], + segments: [ + { to: [0.55, 0] }, + { to: [0.55, 0.08], arc: { center: [0.55, 0.04], counterClockwise: true } }, + { to: [0, 0.08] }, + { to: [0, 0] }, + ], + closed: true, +}); +const left = new Solid(OG_OPERATION_EXTRUDE, { profile: outline, distance: 0.06 }); +const right = left.duplicate(); +const across: MirrorPlane = { origin: [0.3, 0, 0], normal: [1, 0, 0] }; +right.mirror(across); +console.log(Math.abs(right.measure().volume - left.measure().volume) < 1e-9); +``` + +- It works on a wire, a sheet or a solid. +- The placement does not change. +- The boolean report is cleared, so `getReport()` gives `null`. +- A zero normal or a coordinate that is not finite throws `InvalidParameter`. + +A placement cannot hold a reflection: a negative scale throws `InvalidTransform`. Use `mirror`. diff --git a/docs/opengeometry/guides/regions-and-offsets.mdx b/docs/opengeometry/guides/regions-and-offsets.mdx new file mode 100644 index 00000000..d7f401ef --- /dev/null +++ b/docs/opengeometry/guides/regions-and-offsets.mdx @@ -0,0 +1,146 @@ +--- +title: Regions and offsets +description: 2D booleans on point and line-and-arc regions, exact insets with one distance per edge, and polyline strokes. +icon: vector-square +--- + +The 2D calls work in the XZ plane, the ground plane seen from above. They are statics of `OpenGeometry` and need no body. + +## Region shapes + +A region is an outer ring and a list of hole rings. There are two kinds: + +| Type | A ring is | +| ---------------- | --------------------------------------------------------------------------------------------------------------------- | +| `OffsetRegion` | `{ x, y, z }` points, all at one height | +| `CurvedRegion2D` | `CurvedRegionEdge` items: `{ kind: 'line', from, to }` or `{ kind: 'arc', center, radius, start_angle, sweep_angle }` | + +Edge points are `[x, z]`. Arc angles are in radians. Outer rings run clockwise in XZ and holes counter-clockwise. + +```ts +import { OpenGeometry, type CurvedRegion2D } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const plot: CurvedRegion2D = { + outer: [ + { kind: 'line', from: [0, 0], to: [0, 2] }, + { kind: 'line', from: [0, 2], to: [2, 2] }, + { kind: 'arc', center: [2, 1], radius: 1, start_angle: Math.PI / 2, sweep_angle: -Math.PI }, + { kind: 'line', from: [2, 0], to: [0, 0] }, + ], + holes: [], +}; +const setback = OpenGeometry.offsetCurvedRingVariable(plot, [0.1, 0.25, 0.25, 0.25]); +const arc = setback[0]?.outer.find((edge) => edge.kind === 'arc'); +console.log(setback.length, arc?.kind === 'arc' ? arc.radius : 0); +``` + +This prints `1 0.75`. The west side moves in 0.1 m and the other edges 0.25 m. The arc keeps its centre, so its radius goes from 1 to 0.75. + +## Booleans + +`OpenGeometry.booleanRegions2D(a, b, operation)` and `OpenGeometry.booleanCurvedRegions2D(a, b, operation)` take two lists of regions. `operation` is `'union'`, `'intersection'` or `'subtraction'`. + +```ts +import { OpenGeometry, OG_REGION_TOLERANCE, type OffsetRegion } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const square = (x: number): OffsetRegion => ({ + outer: [ + { x, y: 0, z: 0 }, + { x, y: 0, z: 1 }, + { x: x + 1, y: 0, z: 1 }, + { x: x + 1, y: 0, z: 0 }, + ], + holes: [], +}); +const left: OffsetRegion[] = OpenGeometry.booleanRegions2D( + [square(0)], + [square(0.5)], + 'subtraction', +); +console.log(left.length, left[0]?.outer.length, OG_REGION_TOLERANCE); +``` + +- Results come back at the input height, wound the same way. Each planar ring starts at its smallest x. +- The tolerance is fixed at `OG_REGION_TOLERANCE`, `1e-6` m. +- A plain ring is not a region and throws `InvalidParameter`. +- More than 100 000 points or edges across both operands throws `LimitExceeded`. + +## Insets and offsets + +| Call | What it does | +| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `offsetRingVariable(ring, distances, holes?)` | Insets a closed point ring by one distance per edge. Each hole `{ ring, distances }` grows by its own | +| `offsetCurvedRingVariable(region, distances, holeDistances?)` | Insets one `CurvedRegion2D` by one distance per edge, with one list per hole | +| `insetCurvedRegion2D(region, distance)` | Insets one `CurvedRegion2D` by one distance, holes grown by the same | +| `offsetPolylineRegions(path, width, closed, miterLimit?)` | Strokes a path into regions. Mitres up to `miterLimit`, default 4, and bevels past it | +| `offsetPolyline(path, distance, options?)` | Offsets a path to one side. Returns `{ edges, bevelled, closed }` | + +Rings and paths are flat `[x, y, z, ...]` lists or a `Float64Array`; `y` is ignored. The region calls return `CurvedRegion2D[]` with exact lines and arcs. An inside corner of an inset is one arc of the setback. + +```ts +import { OpenGeometry, type CurvedRegion2D, type OffsetPath2D } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const flat = (points: [number, number][]): number[] => points.flatMap(([x, z]) => [x, 0, z]); +const lot = flat([ + [0, 0], + [10, 0], + [10, 5], + [5, 5], + [5, 10], + [0, 10], +]); +const inset: CurvedRegion2D[] = OpenGeometry.offsetRingVariable(lot, [2, 2, 2, 2, 2, 2]); +const corner = inset[0]?.outer.find((edge) => edge.kind === 'arc'); +const duct: CurvedRegion2D[] = OpenGeometry.offsetPolylineRegions( + flat([ + [0, 0], + [4, 0], + [4, 3], + ]), + 0.3, + false, +); +const side: OffsetPath2D = OpenGeometry.offsetPolyline( + flat([ + [0, 0], + [5, 0], + ]), + 1, +); +console.log( + inset.length, + corner?.kind === 'arc' ? corner.radius : 0, + duct.length, + side.edges.length, +); +``` + +This prints `1 2 1 1`. + +## Rules for `offsetCurvedRingVariable` + +- One distance per edge, finite and not negative. A distance of 0 keeps its edge. +- Where two edges meet tangentially and get different distances, the inset joins them with an extra arc. +- An arc stays on its centre. A convex arc moves to `r − d`; a concave arc, or an arc of a hole, to `r + d`. +- A distance larger than an arc's radius, a wrong count, or a negative or non-finite distance throws `InvalidParameter`. +- A result that collapses is an empty list. + +## Rules for `offsetPolyline` + +- `acuteThresholdDegrees` defaults to 35 and `bevel` to `true`. +- When `closed` is left out, a path whose ends meet is closed. diff --git a/docs/opengeometry/guides/revolve.mdx b/docs/opengeometry/guides/revolve.mdx new file mode 100644 index 00000000..88a2c755 --- /dev/null +++ b/docs/opengeometry/guides/revolve.mdx @@ -0,0 +1,65 @@ +--- +title: Revolve +description: Turn a closed line-and-arc profile a full turn about an axis in its plane. +icon: rotate +--- + +`OG_OPERATION_REVOLVE` turns a closed profile a full turn into a solid. The parameters are `{ profile, axis? }`: + +- `profile`: a closed `OG_PRIMITIVE_PROFILE` wire. +- `axis`: `{ point: [u, v], direction: [du, dv] }` in the profile's own `[u, v]`. By default it is `{ point: [0, 0], direction: [0, 1] }`, the profile plane's v axis. + +Each profile edge off the axis becomes one plane, cylinder, cone, sphere or ring torus face. An edge on the axis makes no face. + +## A bowl + +On the default ground plane, the v axis runs along −Z, so the solid would lie on its side. Draw the profile on an upright plane instead, with u as the radius and v as the height. The bowl then stands upright about the Y axis: + +```ts +import { + OpenGeometry, + Solid, + Wire, + OG_OPERATION_PARAMS_REVOLVE, + OG_OPERATION_REVOLVE, + OG_PRIMITIVE_PARAMS_PROFILE, + OG_PRIMITIVE_PROFILE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const section = OG_PRIMITIVE_PARAMS_PROFILE({ + start: [0, 0], + segments: [ + { to: [0.12, 0] }, + { to: [0.19, 0.3] }, + { to: [0.19, 0.34], arc: { center: [0.19, 0.32], counterClockwise: true } }, + { to: [0.16, 0.34] }, + { to: [0, 0.18], arc: { center: [0, 0.34], counterClockwise: false } }, + { to: [0, 0] }, + ], + closed: true, +}); +const profile = new Wire(OG_PRIMITIVE_PROFILE, section, { + plane: { normal: [0, 0, 1], xDirection: [1, 0, 0] }, +}); +const bowl = new Solid(OG_OPERATION_REVOLVE, OG_OPERATION_PARAMS_REVOLVE({ profile })); +console.log(bowl.validity().valid); +``` + +## Rules + +These throw `InvalidParameter`: + +- A profile that crosses the axis, touches it at a single point, or meets it along two separate stretches. +- An arc whose circle meets the axis. +- A zero `direction`. + +Not built: + +- A partial turn. There is no sweep angle; every revolve is a full turn. +- A profile with holes. `OG_OPERATION_REVOLVE` takes no `holes`. +- The shell of a full-turn revolve throws `CoverageGap`. diff --git a/docs/opengeometry/guides/run-in-node.mdx b/docs/opengeometry/guides/run-in-node.mdx new file mode 100644 index 00000000..fd74dbc9 --- /dev/null +++ b/docs/opengeometry/guides/run-in-node.mdx @@ -0,0 +1,57 @@ +--- +title: Run in Node +description: Load the kernel in Node, mesh bodies without a renderer, and write STEP files from a script or a test. +icon: terminal +--- + +Node has no `Worker` and cannot fetch a `file:` address. Pass the compiled module to `create`. Tessellation then runs inline. + +```js +import { readFileSync } from 'node:fs'; +import { OpenGeometry } from 'opengeometry'; + +const wasm = readFileSync(new URL(import.meta.resolve('opengeometry/opengeometry_bg.wasm'))); +await OpenGeometry.create({ wasmModule: new WebAssembly.Module(wasm) }); +``` + +## Write a STEP file + +Modelling, queries and export need no display: + +```js +import { readFileSync, writeFileSync } from 'node:fs'; +import { OpenGeometry, Solid, OG_PRIMITIVE_CYLINDER } from 'opengeometry'; + +const wasm = readFileSync(new URL(import.meta.resolve('opengeometry/opengeometry_bg.wasm'))); +await OpenGeometry.create({ wasmModule: new WebAssembly.Module(wasm) }); + +const post = new Solid(OG_PRIMITIVE_CYLINDER, { radius: 0.1, height: 2.4 }); +const { text } = await OpenGeometry.exportStep({ nodes: [post] }); +writeFileSync('post.step', text); +``` + +## Get a mesh + +In Node nothing renders, so nothing asks for geometry. Walk the scene, then flush: + +```js +import { readFileSync } from 'node:fs'; +import * as THREE from 'three'; +import { OpenGeometry, Solid, OG_PRIMITIVE_SPHERE } from 'opengeometry'; + +const wasm = readFileSync(new URL(import.meta.resolve('opengeometry/opengeometry_bg.wasm'))); +await OpenGeometry.create({ wasmModule: new WebAssembly.Module(wasm) }); + +const ball = new Solid(OG_PRIMITIVE_SPHERE, { radius: 1 }); +const scene = new THREE.Scene(); +scene.add(ball); +scene.updateMatrixWorld(); +OpenGeometry.flush({ geometry: 'sync' }); +console.log(ball.surface.geometry.getAttribute('position').count); +``` + +The mesh is in `body.surface.geometry`. After an edit, `OpenGeometry.flush({ geometry: 'sync', bodies: [body] })` meshes only that body. + +## Tests + +Call `OpenGeometry.reset()` between tests. It frees every body and leaves an empty document. A body from before the reset throws `Disposed`. diff --git a/docs/opengeometry/guides/shell.mdx b/docs/opengeometry/guides/shell.mdx new file mode 100644 index 00000000..57416514 --- /dev/null +++ b/docs/opengeometry/guides/shell.mdx @@ -0,0 +1,59 @@ +--- +title: Shell +description: Hollow a solid in place, with walls of one thickness inside every face. +icon: box-open +--- + +`solid.operate(OG_OPERATION_SHELL, { thickness, instances? })` hollows a solid in place. It leaves one closed void, `thickness` inside every face. + +```ts +import { + OpenGeometry, + Solid, + Wire, + OG_OPERATION_EXTRUDE, + OG_OPERATION_SHELL, + OG_PRIMITIVE_PROFILE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const dShape = new Wire(OG_PRIMITIVE_PROFILE, { + start: [0, 0], + segments: [ + { to: [0.36, 0] }, + { to: [0.36, 0.38], arc: { center: [0.36, 0.19], counterClockwise: true } }, + { to: [0, 0.38] }, + { to: [0, 0] }, + ], + closed: true, +}); +const cistern = new Solid(OG_OPERATION_EXTRUDE, { profile: dShape, distance: 0.3 }); +cistern.operate(OG_OPERATION_SHELL, { thickness: 0.01 }); +console.log(cistern.validity().valid); +``` + +## What it takes + +A cuboid, a cylinder, a sphere, a ring torus, a cone or frustum, a planar profile extrusion, or an extrusion of a line-and-arc profile with or without holes. + +The inner walls of a line-and-arc extrusion are its exact inset: lines parallel to the sides, arcs on the same centres, and arcs of radius `thickness` at inward corners. + +## Errors + +| Code | When | +| ------------------------ | ---------------------------------------------------------------------------------------- | +| `InvalidParameter` | `thickness` is not finite, or not above four times the geometric tolerance | +| `UnresolvedIntersection` | The cavity would vanish, the inset is empty or splits, or two inset edges come too close | +| `SharedShape` | The shape is shared and `instances: 'all'` is not given | +| `CoverageGap` | A solid of another kind, such as a full-turn revolve | +| `UnsupportedGeometry` | A solid with approximate geometry | + +Not built: a sheet is not thickened into a solid. `Sheet` has no `operate`. + +## Keep the original + +The shell changes the solid in place. To keep the solid too, shell a copy: `solid.duplicate()`. diff --git a/docs/opengeometry/guides/sweep.mdx b/docs/opengeometry/guides/sweep.mdx new file mode 100644 index 00000000..ecca874c --- /dev/null +++ b/docs/opengeometry/guides/sweep.mdx @@ -0,0 +1,94 @@ +--- +title: Sweep +description: Move a profile along a path of lines and arcs into a solid, an open sheet, or a closed ring. +icon: bezier-curve +--- + +`OG_OPERATION_SWEEP` moves a closed profile along a path. The parameters are `{ profile, path, caps? }`. Both are wires. + +| Path | Result | +| -------------------------------------------------------- | -------------------------------- | +| Open polyline | Straight runs with mitred joints | +| `OG_PRIMITIVE_ARC`, or an open profile with arc segments | One exact bend per arc | +| Closed polyline, closed profile, or circle | A closed ring with no end faces | + +Place the profile across the start of the path. Its plane normal should point along the path. + +## A bend + +The profile is a rectangle at the start of a quarter arc. The arc gives one exact bend with two cylindrical walls: + +```ts +import { + OpenGeometry, + Solid, + Wire, + OG_OPERATION_SWEEP, + OG_PRIMITIVE_ARC, + OG_PRIMITIVE_PARAMS_ARC, + OG_PRIMITIVE_RECTANGLE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const path = new Wire( + OG_PRIMITIVE_ARC, + OG_PRIMITIVE_PARAMS_ARC({ radius: 0.6, startAngle: 0, sweepAngle: Math.PI / 2 }), +); +const profile = new Wire( + OG_PRIMITIVE_RECTANGLE, + { width: 0.4, breadth: 0.25 }, + { plane: { origin: [0.6, 0, 0], normal: [0, 0, -1], xDirection: [1, 0, 0] } }, +); +const duct = new Solid(OG_OPERATION_SWEEP, { profile, path }); +console.log(duct.getBrep().topology.faces.length); +``` + +This prints `6`. A circle profile on the same path gives torus faces: a pipe elbow. + +## An open sheet + +With `caps: false` the ends stay open. The result has no volume, so it is a `Sheet`: + +```ts +import { + OpenGeometry, + Sheet, + Wire, + OG_OPERATION_PARAMS_SWEEP, + OG_OPERATION_SWEEP, + OG_PRIMITIVE_POLYLINE, + OG_PRIMITIVE_RECTANGLE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const profile = new Wire(OG_PRIMITIVE_RECTANGLE, { width: 0.7, breadth: 0.4 }); +const path = new Wire(OG_PRIMITIVE_POLYLINE, { + points: [ + [0, 0, 0], + [0, 3, 0], + [3, 3, 0], + ], +}); +const duct = new Sheet( + OG_OPERATION_SWEEP, + OG_OPERATION_PARAMS_SWEEP({ profile, path, caps: false }), +); +console.log(duct.bodyType, duct.getBrep().topology.faces.length); +``` + +This prints `Sheet 8`: eight side faces and no end faces. A sheet shows its surface from the front only. STEP export refuses it, and `Sheet` has no `operate`. + +## Rules + +- `caps` is `true` when you leave it out. +- An arc in an open profile path should meet its lines tangentially. +- A sweep that would cut through itself throws `SweepSelfIntersection`. +- `new Solid` with `caps: false`, or `new Sheet` without it, throws `BodyTypeMismatch`. diff --git a/docs/opengeometry/guides/transforms-and-assemblies.mdx b/docs/opengeometry/guides/transforms-and-assemblies.mdx new file mode 100644 index 00000000..70037b0f --- /dev/null +++ b/docs/opengeometry/guides/transforms-and-assemblies.mdx @@ -0,0 +1,106 @@ +--- +title: Transforms and assemblies +description: Move, turn, scale and place bodies, group them in assemblies, and make copies and instances. +icon: diagram-project +--- + +## Transforms + +`node.transform(kind, params)` moves a body or an assembly. It changes the node's placement, not its shape. + +| Kind | Parameters | +| ------------------------ | ------------------------------------------- | +| `OG_TRANSFORM_TRANSLATE` | `{ offset }` | +| `OG_TRANSFORM_ROTATE` | `{ axis, degrees, pivot? }` | +| `OG_TRANSFORM_SCALE` | `{ factor, pivot? }` | +| `OG_TRANSFORM_PLACE` | `{ origin?, xDirection?, normal?, scale? }` | + +Translate, rotate and scale add to the current placement. Place sets it. + +```ts +import { + OpenGeometry, + Solid, + OG_PRIMITIVE_CUBOID, + OG_TRANSFORM_ROTATE, + OG_TRANSFORM_TRANSLATE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const box = new Solid(OG_PRIMITIVE_CUBOID, { width: 1, height: 1, depth: 1 }); +box.transform(OG_TRANSFORM_TRANSLATE, { offset: [2, 0, 0] }); +box.transform(OG_TRANSFORM_ROTATE, { axis: [0, 1, 0], degrees: 90, pivot: [2, 0, 0] }); +console.log(box.getPlacement()); +``` + +`getPlacement()` returns `{ origin, xDirection, normal, scale }` relative to the parent. `getWorldPlacement()` returns it in the world. + +Do not set `position`, `rotation` or `scale` on a body. The kernel puts the placement back and sends a `PlacementOverwritten` warning. + +A negative scale throws `InvalidTransform`. Use [mirror](/opengeometry/guides/rebuild-and-mirror#mirror). + +## Assemblies + +A `SystemAssembly` groups nodes. Its children follow its placement. + +```ts +import { + OpenGeometry, + Solid, + SystemAssembly, + OG_PRIMITIVE_CUBOID, + OG_TRANSFORM_TRANSLATE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const desk = new SystemAssembly({ ogId: 'desk' }); +const top = new Solid( + OG_PRIMITIVE_CUBOID, + { width: 1.6, height: 0.04, depth: 0.8 }, + { parent: desk }, +); +const leg = new Solid(OG_PRIMITIVE_CUBOID, { width: 0.05, height: 0.71, depth: 0.05 }); +desk.addChild([leg]); +top.transform(OG_TRANSFORM_TRANSLATE, { offset: [0, 0.71, 0] }); +desk.transform(OG_TRANSFORM_TRANSLATE, { offset: [3, 0, 0] }); +console.log(desk.getChildren(), desk.getBounds()); +``` + +- Pass `parent` in the options, or call `addChild(children, { keepWorld? })`. +- `removeChild(child, { keepWorld? })` takes a node out. With `keepWorld: true` the node keeps its world position; otherwise it keeps its local placement. +- `getChildren()` returns the children's `ogId` values. `getParent()` returns the parent's `ogId`, or `null`. +- Bodies have the same tree methods, so a body can be the parent of another body. +- A `SystemAssembly` is not a Three.js object. Add its bodies to the scene yourself. +- `assembly.dispose()` disposes the assembly. + +## Copies and instances + +| Call | Shape | Use it for | +| ------------------------------------ | -------- | --------------------------------------- | +| `body.duplicate({ ogId?, parent? })` | Own copy | A body that you will edit on its own | +| `body.instance({ ogId?, parent? })` | Shared | Many copies of one part, such as chairs | + +```ts +import { OpenGeometry, Solid, OG_PRIMITIVE_CUBOID, OG_TRANSFORM_TRANSLATE } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const chair = new Solid(OG_PRIMITIVE_CUBOID, { width: 0.5, height: 0.9, depth: 0.5 }); +const second = chair.instance(); +second.transform(OG_TRANSFORM_TRANSLATE, { offset: [1, 0, 0] }); +chair.rebuild(OG_PRIMITIVE_CUBOID, { width: 0.55, height: 0.9, depth: 0.5 }, { instances: 'all' }); +console.log(chair.getInstanceCount(), second.getBounds()); +``` + +An instance has its own placement and shares the shape. An edit of a shared shape needs `{ instances: 'all' }`, or `makeUnique()` on the body that should change alone. diff --git a/docs/opengeometry/guides/use-your-threejs-scene.mdx b/docs/opengeometry/guides/use-your-threejs-scene.mdx new file mode 100644 index 00000000..182d40e2 --- /dev/null +++ b/docs/opengeometry/guides/use-your-threejs-scene.mdx @@ -0,0 +1,106 @@ +--- +title: Use your Three.js scene +description: Put bodies in your own scene, connect your camera for level of detail, and draw bodies through your own instanced or batched layers. +icon: cubes +--- + +OpenGeometry makes no scene, camera, renderer or controls. Your app owns them. Bodies are `THREE.Group` objects that you add like any other. + +## Connect the camera + +Tell the kernel which camera draws each frame, and when it moves. Level of detail then follows the camera: + +```ts +import * as THREE from 'three'; +import { OpenGeometry, Solid, OG_PRIMITIVE_TORUS } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const ring = new Solid(OG_PRIMITIVE_TORUS, { majorRadius: 1, minorRadius: 0.2 }); +const scene = new THREE.Scene(); +scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 2), ring); +const camera = new THREE.PerspectiveCamera(50, innerWidth / innerHeight, 0.1, 100); +camera.position.set(3, 3, 3); +camera.lookAt(0, 0, 0); +const renderer = new THREE.WebGLRenderer({ antialias: true }); +renderer.setSize(innerWidth, innerHeight); +document.body.append(renderer.domElement); + +renderer.domElement.addEventListener('pointermove', (event) => { + if (event.buttons !== 0) OpenGeometry.setCameraMotion(true); +}); +renderer.setAnimationLoop(() => { + OpenGeometry.observeCamera(renderer, camera); + renderer.render(scene, camera); +}); +``` + +- `observeCamera(renderer, camera)` uses the first camera seen per renderer frame. +- `setCameraMotion(true)` lets the kernel use coarser meshes while the camera moves. Call it from your controls' change event. + +## Draw bodies through your own layers + +Large scenes often draw many bodies through one `InstancedMesh` or `BatchedMesh`. The kernel must still know which bodies are on screen, because it makes meshes only for displayed bodies. + +1. Hand the drawing to your layer: `OpenGeometry.setHostDrawn(bodies, true)`. Each body's `visible` becomes `false`, so Three.js skips it and everything under it. The kernel keeps the body's own visibility apart. +2. Make a group of those bodies: `const group = OpenGeometry.hostGroup(bodies)`. +3. In the layer's `onBeforeRender`, call `group.drawn()`. It counts every member as displayed for this render pass, at a cost that does not grow with the number of members. +4. After each body's `geometrychanged` event, build your layer from `body.surface.geometry` and `body.surface.matrixWorld`. +5. When a body leaves the layer, call `OpenGeometry.setHostDrawn([body], false)`. Its `visible` goes back to its own visibility. + +```ts +import * as THREE from 'three'; +import { OpenGeometry, Solid, OG_PRIMITIVE_CUBOID } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const chairs = [0, 1, 2].map( + (index) => + new Solid( + OG_PRIMITIVE_CUBOID, + { width: 0.5, height: 0.9, depth: 0.5 }, + { ogId: `chair-${index}` }, + ), +); +const scene = new THREE.Scene(); +scene.add(...chairs); +OpenGeometry.setHostDrawn(chairs, true); +const group = OpenGeometry.hostGroup(chairs); + +const layer = new THREE.InstancedMesh( + new THREE.BufferGeometry(), + new THREE.MeshStandardMaterial(), + chairs.length, +); +layer.onBeforeRender = () => group.drawn(); +scene.add(layer); +scene.updateMatrixWorld(); +OpenGeometry.flush({ geometry: 'sync', bodies: chairs }); +console.log( + chairs.map((chair) => chair.visible), + chairs[0]?.surface.geometry.getAttribute('position').count, +); +``` + +- `group.set(bodies)` replaces the members. `group.dispose()` ends the group. +- For a few bodies, `OpenGeometry.markDisplayed(bodies)` does the same as `group.drawn()` without a group. +- Do not set `visible` on a host-drawn body. A dispose, a rollback or a reset changes its own visibility instead. +- `markDisplayed` skips a body with `visible = false` that is not host-drawn. + +## Placement events + +Each body dispatches `placementchanged` when a flush moves it. A layer that copies world matrices listens to it. + +## Moving a surface mesh yourself + +A body's `surface` and `outline` meshes are static: their `matrixAutoUpdate` is `false`. If your code writes their `position`, `rotation`, `quaternion` or `scale`, call `updateMatrix()` on that mesh after the write. To move a body, use `transform`. + +## Free memory + +`OpenGeometry.releaseIdleGeometry()` frees cached display meshes of bodies that do not show them. Call it after a large part of the model leaves the view. diff --git a/docs/opengeometry/installation.mdx b/docs/opengeometry/installation.mdx new file mode 100644 index 00000000..edd28046 --- /dev/null +++ b/docs/opengeometry/installation.mdx @@ -0,0 +1,77 @@ +--- +title: Installation +description: Install opengeometry and three, and serve the WebAssembly kernel and the display worker. +icon: download +--- + +```bash +npm install opengeometry three +``` + +- `three` is a peer dependency. Versions `>=0.168.0 <0.185.0` are supported. +- The package is ES modules only. Its TypeScript types are included. + +## Serve the two files + +The package ships two files that your page must fetch at run time: + +| File | What it is | +| ------------------------ | -------------------------------------------- | +| `opengeometry_bg.wasm` | The kernel, compiled to WebAssembly | +| `tessellation-worker.js` | The web worker that makes the display meshes | + +With no arguments, `OpenGeometry.create()` looks for both files next to the package's own `index.js`. A bundler that moves or rewrites `index.js` breaks that lookup. The dependable way is to copy both files into the folder that your site serves at its root, and pass their addresses to `create`. + +In Vite, that folder is `public/`: + +```bash +cp node_modules/opengeometry/opengeometry_bg.wasm node_modules/opengeometry/tessellation-worker.js public/ +``` + +Then start the kernel once, before you make a body: + +```ts +import { OpenGeometry } from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); +``` + +`workerURL` goes in the second argument, not the first. + +## Vite settings + +Vite pre-bundles dependencies. Keep `opengeometry` out of that step, and allow top-level `await` in the build: + +```js +import { defineConfig } from 'vite'; + +export default defineConfig({ + optimizeDeps: { exclude: ['opengeometry'] }, + build: { target: 'esnext' }, +}); +``` + +If your build cannot use top-level `await`, put the code after the imports in an `async` function and call it. + +## Without a worker + +Pass `{ tessellation: 'inline' }` to make the display meshes on the main thread. You then need no worker file: + +```ts +import { OpenGeometry } from 'opengeometry'; + +await OpenGeometry.create({ wasmURL: '/opengeometry_bg.wasm' }, { tessellation: 'inline' }); +``` + +For Node, see [Run in Node](/opengeometry/guides/run-in-node). + +## Check the installed line + +```bash +npm ls opengeometry +``` + +The 2.0 line has a different API. Code that uses `Cuboid`, `Vector3` or `setPlacement` is written for 2.0. diff --git a/docs/opengeometry/migrate-from-2-0.mdx b/docs/opengeometry/migrate-from-2-0.mdx new file mode 100644 index 00000000..ca0f4eab --- /dev/null +++ b/docs/opengeometry/migrate-from-2-0.mdx @@ -0,0 +1,35 @@ +--- +title: Migrate from 2.0 +description: What changed between OpenGeometry 2.0 and 3.0, and where the full step-by-step guide is. +icon: arrow-right-arrow-left +--- + +OpenGeometry 3.0 has a new API. Code written for 2.0 does not run on 3.0 without changes. Version 2.5 was not published: from 2.0, move straight to 3.0. + +The full guide is [MIGRATION.md](https://github.com/OpenGeometry-io/OpenGeometry/blob/main/MIGRATION.md) in the repository. It gives each change with code before and after, a table of replacements, every change of behaviour, and the checks to run at the end. + +## The main changes + +| 2.0 | 3.0 | +| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| One class per shape: `Cuboid`, `Cylinder`, `Polygon`, … | Three body classes: `new Wire(kind, params)`, `new Solid(kind, params)`, `new Sheet(kind, params)` | +| `Vector3` objects | `[x, y, z]` arrays | +| `setPlacement`, positions on the object | `body.transform(kind, params)` | +| Free functions such as `booleanRegions2D` | Statics: `OpenGeometry.booleanRegions2D`, `OpenGeometry.offsetRingVariable`, … | +| `solid.prepareIfcExchange()` | `OpenGeometry.exportIfcBody(solid)` | +| `new Sweep({ capStart: false, capEnd: false })` | `new Sheet(OG_OPERATION_SWEEP, { profile, path, caps: false })` | +| `AnalyticSolid({ kind: 'arcEdgedExtrusion' })` | An `OG_PRIMITIVE_PROFILE` wire, then `OG_OPERATION_EXTRUDE` | +| `solid.shell(thickness)` returned a new solid | `solid.operate(OG_OPERATION_SHELL, { thickness })` hollows in place | + +## Removed + +These 2.0 features are not in 3.0, and have no replacement: IFC file text, STL and PDF export, projection, loft, triangulation as a public call, curves other than lines, circles and arcs, and wedges. Take that code out, or stay on 2.0. + +## How to move + +1. Install 3.0 and run your type check. A call to a 2.0 class or function fails at compile time. +2. For each failure, find the call in MIGRATION.md under "Replace this with that". +3. Read "Different behaviour", because some calls keep their name and change what they return. +4. Run the "Check your result" steps. + +The [API reference](/opengeometry/api/overview) lists every 3.0 export. diff --git a/docs/opengeometry/quickstart.mdx b/docs/opengeometry/quickstart.mdx new file mode 100644 index 00000000..873b3c04 --- /dev/null +++ b/docs/opengeometry/quickstart.mdx @@ -0,0 +1,117 @@ +--- +title: Quickstart +description: Make a Vite app, cut a door opening into a wall, show it in Three.js and export it as STEP. +icon: rocket +--- + +In this quickstart you make a wall from a rectangle, cut a door opening into it, show it in a Three.js scene and write it as a STEP file. + +Use a modern browser and a Node.js version that [Vite](https://vite.dev/guide/) supports. + + + + +```bash +npm create vite@latest og-app -- --template vanilla-ts --no-interactive +cd og-app +npm install opengeometry three +npm install --save-dev @types/three +``` + + + + +Copy the kernel and the display worker into `public/`, so the page can fetch them from the site root: + +```bash +cp node_modules/opengeometry/opengeometry_bg.wasm node_modules/opengeometry/tessellation-worker.js public/ +``` + + + + +Put this in `vite.config.ts`: + +```js +import { defineConfig } from 'vite'; + +export default defineConfig({ + optimizeDeps: { exclude: ['opengeometry'] }, + build: { target: 'esnext' }, +}); +``` + + + + +Replace `src/main.ts` with this: + +```ts +import * as THREE from 'three'; +import { + OpenGeometry, + Solid, + Wire, + OG_OPERATION_EXTRUDE, + OG_OPERATION_SUBTRACT, + OG_PRIMITIVE_CUBOID, + OG_PRIMITIVE_RECTANGLE, + OG_TRANSFORM_TRANSLATE, +} from 'opengeometry'; + +await OpenGeometry.create( + { wasmURL: '/opengeometry_bg.wasm' }, + { workerURL: '/tessellation-worker.js' }, +); + +const profile = new Wire(OG_PRIMITIVE_RECTANGLE, { width: 6, breadth: 0.2 }); +const wall = new Solid(OG_OPERATION_EXTRUDE, { profile, distance: 3 }); +const door = new Solid(OG_PRIMITIVE_CUBOID, { width: 0.9, height: 2.1, depth: 0.4 }); +door.transform(OG_TRANSFORM_TRANSLATE, { offset: [2, 0, 0] }); +wall.operate(OG_OPERATION_SUBTRACT, { tools: [door] }); + +const scene = new THREE.Scene(); +scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 2), wall); +const camera = new THREE.PerspectiveCamera(50, innerWidth / innerHeight, 0.1, 100); +camera.position.set(6, 5, 8); +camera.lookAt(0, 1.5, 0); +const renderer = new THREE.WebGLRenderer({ antialias: true }); +renderer.setSize(innerWidth, innerHeight); +document.body.replaceChildren(renderer.domElement); +renderer.setAnimationLoop(() => renderer.render(scene, camera)); + +const { text, report } = await OpenGeometry.exportStep({ + nodes: [wall], + unit: 'millimetre', + upAxis: 'Z', +}); +console.log(report.solids, text.length); +``` + + + + +```bash +npm run dev +``` + +Open the address that Vite prints. You see a blue wall with a door opening at x = 2. The console prints `1` and the length of the STEP text. + + + + +## What the code does + +- `OpenGeometry.create` loads the kernel. Await it once, before you make a body. +- The rectangle wire lies on the ground plane. The extrude raises it 3 m along +Y into a wall. +- `operate` cuts the cuboid out of the wall. The cuboid stays a separate, live solid. It is not drawn, because it is not in the scene. +- The wall is a `THREE.Group`, so it goes into the scene like any other object. Rendering asks the kernel for its mesh. +- `exportStep` returns the STEP file as `text` and counts what it wrote in `report`. + +Model units are metres and Y is up. See [Coordinates and planes](/opengeometry/concepts/coordinates-and-planes). + +## Next steps + +- Make other shapes: [Primitives](/opengeometry/guides/primitives), [Sweep](/opengeometry/guides/sweep), [Revolve](/opengeometry/guides/revolve). +- Learn how display works: [Display](/opengeometry/concepts/display). +- Look at the runnable [examples](/opengeometry/examples). diff --git a/docs/opengeometry/troubleshooting.mdx b/docs/opengeometry/troubleshooting.mdx new file mode 100644 index 00000000..2aacb8dd --- /dev/null +++ b/docs/opengeometry/troubleshooting.mdx @@ -0,0 +1,64 @@ +--- +title: Troubleshooting +description: The common problems when you start with OpenGeometry 3.0, what causes them and how to fix them. +icon: wrench +--- + +## The kernel does not load + +**What you see:** `OpenGeometry.create` rejects, or the network panel shows a 404 for `opengeometry_bg.wasm` or `tessellation-worker.js`. + +**Cause:** the page cannot fetch the two files. A bundler moved `index.js` without them. + +**Fix:** copy both files into the folder your site serves at its root and pass their addresses. See [Installation](/opengeometry/installation#serve-the-two-files). + +## A call throws `NotInitialised` + +**Cause:** a body was made before `OpenGeometry.create` finished. + +**Fix:** await `create` once, before the first body. + +## The body is black + +**Cause:** surfaces use `MeshStandardMaterial`, and the scene has no light. + +**Fix:** add a light, for example `new THREE.HemisphereLight(0xffffff, 0x444444, 2)`. + +## The body does not show + +- Add the body to the scene. A body is not drawn on its own, and a `SystemAssembly` is not a Three.js object. +- Render. Rendering is what asks the kernel for the mesh. Render in a loop, or render once, `await OpenGeometry.settled()`, and render again. + +## A move is undone, with a `PlacementOverwritten` warning + +**Cause:** the code set `body.position`, `rotation` or `scale`. + +**Fix:** move bodies with `transform`. See [Transforms and assemblies](/opengeometry/guides/transforms-and-assemblies). + +## An edit throws `SharedShape` + +**Cause:** the body is an instance, and its shape is shared with other instances. + +**Fix:** pass `{ instances: 'all' }` to change every instance, or call `makeUnique()` first to change only this one. + +## The profile comes out mirrored + +**Cause:** on the default ground plane, a profile point `[u, v]` lands at world `(u, 0, −v)`. The v axis runs along −Z. + +**Fix:** flip the sign of v, or draw on another plane. See [Coordinates and planes](/opengeometry/concepts/coordinates-and-planes). + +## STEP export refuses the selection + +**Cause:** a wire or a sheet cannot be exported on its own. It throws `InvalidOperand`. A selection with no solid in it throws `EmptyResult`. + +**Fix:** export solids. An assembly may also hold wires and sheets: they are left out and listed in `report.skipped`. + +## Every call throws after a `fatal` event + +**Cause:** the kernel stopped after an internal failure. + +**Fix:** call `OpenGeometry.reset()`, then make the bodies again. See [Errors and limits](/opengeometry/concepts/errors). + +## The code uses `Cuboid` or `Vector3` + +That code is for 2.0. Follow [Migrate from 2.0](/opengeometry/migrate-from-2-0). diff --git a/docs/opengeometry/what-is-opengeometry.mdx b/docs/opengeometry/what-is-opengeometry.mdx new file mode 100644 index 00000000..1e8aed0f --- /dev/null +++ b/docs/opengeometry/what-is-opengeometry.mdx @@ -0,0 +1,50 @@ +--- +title: What is OpenGeometry? +description: An open-source CAD kernel for the browser, written in Rust, compiled to WebAssembly, with a TypeScript SDK for Three.js. +icon: circle-info +--- + +OpenGeometry is an open-source CAD kernel for the browser. It models B-rep solids, runs boolean operations, builds solids by extrude, sweep and revolve, and writes STEP files. The kernel is written in Rust and compiled to WebAssembly. A TypeScript SDK puts every body straight into a Three.js scene. + +These pages describe OpenGeometry 3.0. The npm package is `opengeometry`. + +## What you can build + +Use OpenGeometry for browser CAD, configurators and geometry-heavy web tools: a parametric modeller, a solid modelling workflow, a geometry viewer or a custom Three.js modelling tool. It is the geometry engine, not a full CAD application. + +It also fits AI-assisted CAD. An assistant or an agent proposes the modelling steps. OpenGeometry runs the geometry, the booleans and the exports, and gives the same result for the same input. + +## What 3.0 has + +| Area | What you get | +| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Primitives | Wires: rectangle, circle, polyline, line-and-arc profile, arc. Solids: cuboid, cylinder, cylinder sector, sphere, cone or frustum, ring torus, planar polyhedron. Each goes on any plane. | +| Operations | Extrude with holes. Sweep along lines and arcs into a solid, an open sheet or a closed ring. Revolve a full turn. Shell a solid. Union, subtract and intersect with one to a hundred tools. | +| Parametric edits | `rebuild` gives a body new parameters in place. `mirror` reflects a body across a plane. | +| Assemblies | Parent and child placement, translate, rotate, scale and place, independent copies and shared instances. | +| History | Marks with rollback and release, and transactions with a dry run. | +| Display for Three.js | Every body is a `THREE.Group`. Level of detail that follows the camera, tessellation in a web worker or inline, picking down to a face or an edge, outlines, smooth edges, colour and opacity. | +| Queries | Bounds, placements, the B-rep, the normal of a face at a point, point classification, volume and area within a stated error bound, validity, and the report of the last boolean. | +| Export | STEP in millimetres or metres with Y or Z up, with a report. The IFC exchange body of a solid, for an IFC writer. | +| 2D | Region booleans on point or line-and-arc regions, exact insets and offsets, and polyline strokes. | + +## What 3.0 does not have + +IFC file text, STL and PDF export, projection, loft, triangulation as a public call, curves other than lines, circles and arcs, wedges, and the 2.0 classes such as `Cuboid`, `Polygon`, `Opening` and `Vector3`. Code that uses them is written for 2.0. See [Migrate from 2.0](/opengeometry/migrate-from-2-0). + +## Next steps + + + + Add the package and serve its two files. + + + Cut a door into a wall and export it as STEP. + + + How the kernel, the SDK and your scene fit together. + + + Give an assistant the rules that matter. + + diff --git a/docs/package-lock.json b/docs/package-lock.json new file mode 100644 index 00000000..931688aa --- /dev/null +++ b/docs/package-lock.json @@ -0,0 +1,14075 @@ +{ + "name": "opengeometry-docs", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "opengeometry-docs", + "devDependencies": { + "front-matter": "4.0.2", + "mint": "4.2.981", + "prettier": "3.8.3" + }, + "engines": { + "node": ">=22.6.0" + } + }, + "node_modules/@alcalzone/ansi-tokenize": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@alcalzone/ansi-tokenize/-/ansi-tokenize-0.2.5.tgz", + "integrity": "sha512-3NX/MpTdroi0aKz134A6RC2Gb2iXVECN4QaAXnvCIxxIm3C3AVB1mkUe8NaaiyvOpDfsrqWhYtj+Q6a62RrTsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.3.0.tgz", + "integrity": "sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@anthropic-ai/claude-agent-sdk": { + "version": "0.3.241", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.241.tgz", + "integrity": "sha512-pIHdCSTywFe30H0oWDCKZzC4ipBLtF5YMDRKjf6PHyARg57O4l/72v3b6QKnnefwtKKMe6uWJ1Y9lUJg/sKWyA==", + "dev": true, + "license": "SEE LICENSE IN README.md", + "optional": true, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.241", + "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.241", + "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.241", + "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.241", + "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.241", + "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.241", + "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.241", + "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.241" + }, + "peerDependencies": { + "@anthropic-ai/sdk": ">=0.93.0", + "@modelcontextprotocol/sdk": "^1.29.0", + "zod": "^4.0.0" + } + }, + "node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": { + "version": "0.3.241", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.241.tgz", + "integrity": "sha512-v26ta54lKFMFEZzbOE+6p3YhKERWnDiEA6OmkSAg+3fAQHOa1+aLTKw222cfgzxgiVixwFtHMk8c63zsDd8aXQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": { + "version": "0.3.241", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.241.tgz", + "integrity": "sha512-5jweT0vft1ZCaGSoxZHF9vJlHbx8Yxx4+x5aHAIXTd4lx7ZbT4o5buEF8kpmTeHUB+Fw9jtFIm4QDsRiBXgf+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": { + "version": "0.3.241", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.241.tgz", + "integrity": "sha512-SxszQGffXiLzMEnAv+pJXEmQbA8haijKyRjjH/jOt1CLeMIfpjKcO9WQDv8dEA8nREWS3zJ103zjgecAF7oOQQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": { + "version": "0.3.241", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.241.tgz", + "integrity": "sha512-GslvPvSzehfCZyzOaJAt4lgodznm5zpl/LMXN8ygD12z5qnpM+I9/eFnmAaISJ0L8/vyohtlAP1jjaeR2jz1AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": { + "version": "0.3.241", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.241.tgz", + "integrity": "sha512-gJRa922Qcm7loumHcXMDFEFg//tz1aOi7Nx0sQa9I9lC1JSN8yL6i7/idzOU5Hp193tEDFOgqIMFL/yRiXg+rw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": { + "version": "0.3.241", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.241.tgz", + "integrity": "sha512-kZigJ5Ug2I2G/n7Cunmwy4TGr0lOGnWrz6TkzyWiDcUmJOodoTH6GZECNarWAtETfN03AAeLfrpiz8z3hOEDqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": { + "version": "0.3.241", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.241.tgz", + "integrity": "sha512-/3yA9jQuCvHDVlILzhtslH6kFYOvydXyMZiKwnzqM8ZfvFTNO41w8TpiFpBLseyM+4A4E8QMeTKu3L01Xyb5IQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": { + "version": "0.3.241", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.241.tgz", + "integrity": "sha512-cHYdAgORl9kynujMeYXyV1uj/hbmsBjRw9dRVkIW4/4sF7S6L4u/qDSzn1/wiNP7g2yWSJ4KbsvHDH2WWDnCBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.120.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.120.0.tgz", + "integrity": "sha512-ZlvmNFT/iIF6JD13rxbbMWD8nvGR0RaUp6yMQnoc+4Af0YjVVe/bIdW1XSQQsoxXAtg1NaT6Vak0LKFlJ4d37Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "json-schema-to-ts": "^3.1.1", + "standardwebhooks": "^1.0.0" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@ark/schema": { + "version": "0.56.6", + "resolved": "https://registry.npmjs.org/@ark/schema/-/schema-0.56.6.tgz", + "integrity": "sha512-OmLv80BCF2ib+zjecrXDosip/CSnZSYBGjblhqWYZWFOzdLQka6QymHToE9u7Z/HZW2KA8Hwc8MCNXoI3uGSIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ark/util": "0.56.6" + } + }, + "node_modules/@ark/util": { + "version": "0.56.6", + "resolved": "https://registry.npmjs.org/@ark/util/-/util-0.56.6.tgz", + "integrity": "sha512-mHqq0f0HyDd9YadpFl25w0QECAP7d8HGIUpEC85duD+L+xr4i/CwfOid/Z7zJFFF/47oLt6+pZB9RbqWpBYTYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@asyncapi/parser": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-3.4.0.tgz", + "integrity": "sha512-Sxn74oHiZSU6+cVeZy62iPZMFMvKp4jupMFHelSICCMw1qELmUHPvuZSr+ZHDmNGgHcEpzJM5HN02kR7T4g+PQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@asyncapi/specs": "^6.8.0", + "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", + "@stoplight/json": "3.21.0", + "@stoplight/json-ref-readers": "^1.2.2", + "@stoplight/json-ref-resolver": "^3.1.5", + "@stoplight/spectral-core": "^1.18.3", + "@stoplight/spectral-functions": "^1.7.2", + "@stoplight/spectral-parsers": "^1.0.2", + "@stoplight/spectral-ref-resolver": "^1.0.3", + "@stoplight/types": "^13.12.0", + "@types/json-schema": "^7.0.11", + "@types/urijs": "^1.19.19", + "ajv": "^8.17.1", + "ajv-errors": "^3.0.0", + "ajv-formats": "^2.1.1", + "avsc": "^5.7.5", + "js-yaml": "^4.1.0", + "jsonpath-plus": "^10.0.0", + "node-fetch": "2.6.7" + } + }, + "node_modules/@asyncapi/parser/node_modules/argparse": { + "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, + "license": "Python-2.0" + }, + "node_modules/@asyncapi/parser/node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@asyncapi/specs": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-6.11.1.tgz", + "integrity": "sha512-A3WBLqAKGoJ2+6FWFtpjBlCQ1oFCcs4GxF7zsIGvNqp/klGUHjlA3aAcZ9XMMpLGE8zPeYDz2x9FmO6DSuKraQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.11" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@canvas/image-data": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@canvas/image-data/-/image-data-1.1.0.tgz", + "integrity": "sha512-QdObRRjRbcXGmM1tmJ+MrHcaz1MftF2+W7YI+MsphnsCrmtyfS0d5qJbk0MeSbUeyM/jCb0hmnkXPsy026L7dA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/@floating-ui/core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz", + "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz", + "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@floating-ui/core": "^1.8.0", + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz", + "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@hono/node-server": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-2.1.3.tgz", + "integrity": "sha512-TA//nWMqPhbfdfneACk6t5a9eqbS9lABEPyKn0/xZTah3H3U2XaVg85rJFl0/Fyit0I552YDHgXGVSf3GwqbUw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.5.tgz", + "integrity": "sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.5.tgz", + "integrity": "sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.4" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.5.tgz", + "integrity": "sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.4.tgz", + "integrity": "sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.4.tgz", + "integrity": "sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.4.tgz", + "integrity": "sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.4.tgz", + "integrity": "sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.4.tgz", + "integrity": "sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.4.tgz", + "integrity": "sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.4.tgz", + "integrity": "sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.4.tgz", + "integrity": "sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.4.tgz", + "integrity": "sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.4.tgz", + "integrity": "sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.5.tgz", + "integrity": "sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.5.tgz", + "integrity": "sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.5.tgz", + "integrity": "sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.5.tgz", + "integrity": "sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.5.tgz", + "integrity": "sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.5.tgz", + "integrity": "sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.5.tgz", + "integrity": "sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.5.tgz", + "integrity": "sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.5.tgz", + "integrity": "sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==", + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.5.tgz", + "integrity": "sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.5.tgz", + "integrity": "sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.5.tgz", + "integrity": "sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.5.tgz", + "integrity": "sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@inquirer/ansi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", + "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", + "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.21", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", + "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/editor": { + "version": "4.2.23", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", + "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/external-editor": "^1.0.3", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/expand": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", + "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/external-editor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", + "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", + "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/number": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", + "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/password": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", + "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/prompts": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.9.0.tgz", + "integrity": "sha512-X7/+dG9SLpSzRkwgG5/xiIzW0oMrV3C0HOa7YHG1WnrLK+vCQHfte4k/T80059YBdei29RBC3s+pSMvPJDU9/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^4.3.0", + "@inquirer/confirm": "^5.1.19", + "@inquirer/editor": "^4.2.21", + "@inquirer/expand": "^4.0.21", + "@inquirer/input": "^4.2.5", + "@inquirer/number": "^3.0.21", + "@inquirer/password": "^4.0.21", + "@inquirer/rawlist": "^4.1.9", + "@inquirer/search": "^3.2.0", + "@inquirer/select": "^4.4.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/rawlist": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", + "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/search": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", + "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", + "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", + "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "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" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsep-plugin/assignment": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz", + "integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.16.0" + }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@jsep-plugin/regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz", + "integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.16.0" + }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@jsep-plugin/ternary": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@jsep-plugin/ternary/-/ternary-1.1.4.tgz", + "integrity": "sha512-ck5wiqIbqdMX6WRQztBL7ASDty9YLgJ3sSAK5ZpBzXeySvFGCzIvM6UiAI4hTZ22fEcYQVV/zhUbNscggW+Ukg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.16.0" + }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", + "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", + "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@mintlify/cli": { + "version": "4.0.1584", + "resolved": "https://registry.npmjs.org/@mintlify/cli/-/cli-4.0.1584.tgz", + "integrity": "sha512-2qX2Ulfes1LqCiu96dtYWJhDp1vLpC3ZAH6arQTN36HgLl7+ngdYJivFArFOuHJuDuYHNKKLYyxzvq/lQZEoFg==", + "dev": true, + "license": "Elastic-2.0", + "dependencies": { + "@inquirer/prompts": "7.9.0", + "@mintlify/common": "1.0.1206", + "@mintlify/link-rot": "3.0.1414", + "@mintlify/models": "0.0.365", + "@mintlify/prebuild": "1.0.1365", + "@mintlify/previewing": "4.0.1437", + "@mintlify/validation": "0.1.890", + "adm-zip": "0.6.0", + "chalk": "5.2.0", + "color": "4.2.3", + "detect-port": "1.5.1", + "fs-extra": "11.2.0", + "ink": "6.3.0", + "inquirer": "12.3.0", + "js-yaml": "4.3.1", + "jsonc-parser": "3.3.1", + "mdast-util-mdx-jsx": "3.2.0", + "open": "8.4.2", + "openid-client": "6.8.2", + "posthog-node": "5.17.2", + "prosemirror-model": "1.25.4", + "react": "19.2.3", + "remark": "15.0.1", + "remark-frontmatter": "5.0.0", + "remark-gfm": "4.0.1", + "remark-math": "6.0.0", + "remark-mdx": "3.1.1", + "remark-stringify": "11.0.0", + "unified": "11.0.5", + "unist-util-visit": "5.0.0", + "yaml": "2.8.3", + "yargs": "17.7.1", + "zod": "4.3.6" + }, + "bin": { + "mint": "bin/index.js", + "mintlify": "bin/index.js" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "@anthropic-ai/claude-agent-sdk": "0.3.241", + "@anthropic-ai/sdk": "0.120.0", + "@modelcontextprotocol/sdk": "1.30.0", + "@openai/codex-sdk": "0.149.1", + "keytar": "7.9.0" + } + }, + "node_modules/@mintlify/cli/node_modules/argparse": { + "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, + "license": "Python-2.0" + }, + "node_modules/@mintlify/cli/node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@mintlify/common": { + "version": "1.0.1206", + "resolved": "https://registry.npmjs.org/@mintlify/common/-/common-1.0.1206.tgz", + "integrity": "sha512-Qh9qXvfAvZZTBqfPIfJHL6nZwohPiEqzFYeFCJauwR5CXj5NK5t87Zop+tl0xpa9PQFJmvxy391Qsa6PyBtvMg==", + "dev": true, + "license": "ISC", + "dependencies": { + "@asyncapi/parser": "3.4.0", + "@mintlify/mdx": "4.0.7", + "@mintlify/models": "0.0.365", + "@mintlify/openapi-parser": "0.0.9", + "@mintlify/validation": "0.1.890", + "@sindresorhus/slugify": "2.2.0", + "@types/mdast": "4.0.4", + "acorn": "8.11.2", + "acorn-jsx": "5.3.2", + "estree-util-to-js": "2.0.0", + "estree-walker": "3.0.3", + "front-matter": "4.0.2", + "hast-util-from-html": "2.0.3", + "hast-util-to-estree": "3.1.0", + "hast-util-to-html": "9.0.4", + "ignore": "7.0.5", + "iregexp-check": "0.1.2", + "js-yaml": "4.3.1", + "json-p3": "2.2.2", + "lodash": "4.18.1", + "mdast-util-from-markdown": "2.0.2", + "mdast-util-gfm": "3.0.0", + "mdast-util-mdx": "3.0.0", + "mdast-util-mdx-jsx": "3.1.3", + "micromark-extension-gfm": "3.0.0", + "micromark-extension-mdxjs": "3.0.0", + "openapi-types": "12.1.3", + "postcss": "8.5.23", + "re2js": "2.8.6", + "rehype-katex": "7.0.1", + "rehype-stringify": "10.0.1", + "remark": "15.0.1", + "remark-frontmatter": "5.0.0", + "remark-gfm": "4.0.0", + "remark-math": "6.0.0", + "remark-mdx": "3.1.0", + "remark-parse": "11.0.0", + "remark-rehype": "11.1.1", + "remark-smartypants": "3.0.2", + "remark-stringify": "11.0.0", + "sucrase": "3.34.0", + "tailwindcss-v3": "npm:tailwindcss@3.4.17", + "unified": "11.0.5", + "unist-builder": "4.0.0", + "unist-util-map": "4.0.0", + "unist-util-remove": "4.0.0", + "unist-util-remove-position": "5.0.0", + "unist-util-visit": "5.0.0", + "unist-util-visit-parents": "6.0.1", + "valibot": "1.5.0", + "vfile": "6.0.3", + "xss": "1.0.15" + } + }, + "node_modules/@mintlify/common/node_modules/@base-ui/react": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@base-ui/react/-/react-1.8.0.tgz", + "integrity": "sha512-P0/1sxo6SBVZOklKMIedvTWqw2s2IQzi9x5bIVsXu980cuSOD4NeuRSs+/L7LZQfDkZP/uRZyGPyfFl/B1oH+Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.29.7", + "@base-ui/utils": "0.4.0", + "@floating-ui/react-dom": "^2.1.9", + "@floating-ui/utils": "^0.2.12", + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@date-fns/tz": "^1.2.0", + "@types/react": "^17 || ^18 || ^19", + "date-fns": "^4.0.0", + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@date-fns/tz": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "date-fns": { + "optional": true + } + } + }, + "node_modules/@mintlify/common/node_modules/@base-ui/utils": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@base-ui/utils/-/utils-0.4.0.tgz", + "integrity": "sha512-bO9fz25kKtPf+aZVyfQrC0PDmJdmVni31W2hCS5/Owb+inwdIL3XU26pCPRPlt4LSxZrBgLwubXQXQlKaFEZzw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.29.7", + "@floating-ui/utils": "^0.2.12", + "reselect": "^5.2.0", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "@types/react": "^17 || ^18 || ^19", + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mintlify/common/node_modules/@floating-ui/react-dom": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz", + "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@floating-ui/dom": "^1.8.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@mintlify/common/node_modules/@mintlify/mdx": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@mintlify/mdx/-/mdx-4.0.7.tgz", + "integrity": "sha512-/kOnIHvjM4jwF7WoXjPRp1nDLjgW8YFyApw5JQiXU6cEdXJdqpWH1xW+0rgGD4adi6yXY+Re9cfNRMftJzCo5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/transformers": "^3.23.0", + "@shikijs/twoslash": "^3.23.0", + "arktype": "^2.1.26", + "hast-util-to-string": "^3.0.1", + "mdast-util-from-markdown": "^2.0.2", + "mdast-util-gfm": "^3.1.0", + "mdast-util-mdx-jsx": "^3.2.0", + "mdast-util-to-hast": "^13.2.0", + "next-mdx-remote-client": "^2.1.11", + "rehype-katex": "^7.0.1", + "remark-gfm": "^4.0.0", + "remark-math": "^6.0.0", + "remark-smartypants": "^3.0.2", + "shiki": "^3.23.0", + "twoslash": "^0.3.4", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0" + }, + "peerDependencies": { + "@base-ui/react": "^1.6.0", + "react": "^19.2.1", + "react-dom": "^19.2.1" + } + }, + "node_modules/@mintlify/common/node_modules/@mintlify/mdx/node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/common/node_modules/@mintlify/mdx/node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/common/node_modules/argparse": { + "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, + "license": "Python-2.0" + }, + "node_modules/@mintlify/common/node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@mintlify/common/node_modules/mdast-util-mdx-jsx": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz", + "integrity": "sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/common/node_modules/next-mdx-remote-client": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/next-mdx-remote-client/-/next-mdx-remote-client-2.1.12.tgz", + "integrity": "sha512-KDfhIk5aEM0kkZ0xQ8XBkmo4O5xmJeGWUomm40Ac/xhkt5sIDOTmTU/QFfmJGLJUJipD5o0BAHqVSIZKuXgNEw==", + "dev": true, + "license": "MPL 2.0", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@mdx-js/mdx": "^3.1.1", + "@mdx-js/react": "^3.1.1", + "@types/mdx": "^2.0.14", + "remark-mdx-remove-esm": "^1.3.2", + "serialize-error": "^13.0.1", + "vfile": "^6.0.3", + "vfile-matter": "^5.0.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "peerDependencies": { + "react": ">= 19.1.0", + "react-dom": ">= 19.1.0" + } + }, + "node_modules/@mintlify/common/node_modules/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz", + "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@mintlify/common/node_modules/react-dom": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.28.0" + }, + "peerDependencies": { + "react": "^19.3.0" + } + }, + "node_modules/@mintlify/common/node_modules/remark-gfm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/common/node_modules/remark-mdx": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz", + "integrity": "sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/common/node_modules/scheduler": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz", + "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@mintlify/link-rot": { + "version": "3.0.1414", + "resolved": "https://registry.npmjs.org/@mintlify/link-rot/-/link-rot-3.0.1414.tgz", + "integrity": "sha512-gKWgqPpeJECi7fy16XLwkoKypxut6J7EHgNJSaynMJLEvt42DWZMB5qu6TausvDVy+UnpjVuwYKtrSQKiRaEog==", + "dev": true, + "license": "Elastic-2.0", + "dependencies": { + "@mintlify/common": "1.0.1206", + "@mintlify/models": "0.0.365", + "@mintlify/prebuild": "1.0.1365", + "@mintlify/previewing": "4.0.1437", + "@mintlify/scraping": "4.0.1076", + "@mintlify/validation": "0.1.890", + "fs-extra": "11.1.0", + "remark-smartypants": "3.0.2", + "unist-util-visit": "4.1.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@mintlify/link-rot/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@mintlify/link-rot/node_modules/fs-extra": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", + "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@mintlify/link-rot/node_modules/unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/link-rot/node_modules/unist-util-visit": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", + "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.1.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/link-rot/node_modules/unist-util-visit-parents": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", + "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/models": { + "version": "0.0.365", + "resolved": "https://registry.npmjs.org/@mintlify/models/-/models-0.0.365.tgz", + "integrity": "sha512-nZVV7AEtCpovxp7Ynmj4O/auTyERcI3fIL2PECvevPtpnXAuDQF2u0t2GRzBS7Oan/Afkqjy9E6MvVA6TzL/GA==", + "dev": true, + "license": "Elastic-2.0", + "dependencies": { + "axios": "1.18.0", + "openapi-types": "12.1.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@mintlify/openapi-parser": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@mintlify/openapi-parser/-/openapi-parser-0.0.9.tgz", + "integrity": "sha512-PHNRY+K6c5lsEqxfLHH1NghO34PTmhtBSFSw5KOx8DyUYe5LTn7k4U3hp7i1qvJuUTC+x0bU4unFmkM1Hc4OGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.17.1", + "ajv-draft-04": "^1.0.0", + "ajv-formats": "^3.0.1", + "jsonpointer": "^5.0.1", + "leven": "^4.0.0", + "yaml": "^2.4.5" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@mintlify/openapi-parser/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@mintlify/prebuild": { + "version": "1.0.1365", + "resolved": "https://registry.npmjs.org/@mintlify/prebuild/-/prebuild-1.0.1365.tgz", + "integrity": "sha512-b9qseRLBwcsdFmL5ZgO4l+ffOiaX5tV1GCf0EGZzSMM7b5o5zPx48HG5VW+wN3dd6fBbJJJqtyYd4riEgQ8K5g==", + "dev": true, + "license": "Elastic-2.0", + "dependencies": { + "@mintlify/common": "1.0.1206", + "@mintlify/scraping": "4.0.1076", + "@mintlify/validation": "0.1.890", + "chalk": "5.3.0", + "favicons": "7.2.0", + "fflate": "0.8.2", + "fs-extra": "11.1.0", + "js-yaml": "4.3.1", + "openapi-types": "12.1.3", + "sharp": "0.33.5", + "sharp-ico": "0.1.5", + "uuid": "11.1.1" + } + }, + "node_modules/@mintlify/prebuild/node_modules/argparse": { + "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, + "license": "Python-2.0" + }, + "node_modules/@mintlify/prebuild/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@mintlify/prebuild/node_modules/fs-extra": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", + "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@mintlify/prebuild/node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@mintlify/previewing": { + "version": "4.0.1437", + "resolved": "https://registry.npmjs.org/@mintlify/previewing/-/previewing-4.0.1437.tgz", + "integrity": "sha512-Bv0eKD0r74KJmdmjSaIaYxmredN6xd2tQbnOKOuke4KYrwteAiWbDu+tco8/v4r5r0AolleGyJWDOrVw3o51Qg==", + "dev": true, + "license": "Elastic-2.0", + "dependencies": { + "@mintlify/common": "1.0.1206", + "@mintlify/prebuild": "1.0.1365", + "@mintlify/validation": "0.1.890", + "adm-zip": "0.6.0", + "better-opn": "3.0.2", + "chalk": "5.2.0", + "chokidar": "3.5.3", + "express": "4.22.0", + "fs-extra": "11.1.0", + "got": "13.0.0", + "ink": "6.3.0", + "ink-spinner": "5.0.0", + "is-online": "10.0.0", + "js-yaml": "4.3.1", + "react": "19.2.3", + "socket.io": "4.8.0", + "tar": "7.5.21", + "yargs": "17.7.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@mintlify/previewing/node_modules/argparse": { + "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, + "license": "Python-2.0" + }, + "node_modules/@mintlify/previewing/node_modules/fs-extra": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", + "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@mintlify/previewing/node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@mintlify/scraping": { + "version": "4.0.1076", + "resolved": "https://registry.npmjs.org/@mintlify/scraping/-/scraping-4.0.1076.tgz", + "integrity": "sha512-8g60+ECGA4MB3T3AJ/G0U5BOMjuWJjTa2qSo7EISmuyxPBXb1adAdCWe74R7iwJkEH9HNk8uZgifRN0nTHboAA==", + "dev": true, + "license": "Elastic-2.0", + "dependencies": { + "@mintlify/common": "1.0.1206", + "fast-xml-parser": "5.7.3", + "fs-extra": "11.1.1", + "graphql": "16.11.0", + "hast-util-to-mdast": "10.1.0", + "js-yaml": "4.3.1", + "mdast-util-mdx-jsx": "3.1.3", + "neotraverse": "0.6.18", + "rehype-parse": "9.0.1", + "remark-gfm": "4.0.0", + "remark-mdx": "3.0.1", + "remark-parse": "11.0.0", + "remark-stringify": "11.0.0", + "unified": "11.0.5", + "unist-util-visit": "5.0.0", + "yargs": "17.7.1", + "zod": "3.24.0" + }, + "bin": { + "mintlify-scrape": "bin/cli.js" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "puppeteer": "24.3.1" + }, + "peerDependenciesMeta": { + "puppeteer": { + "optional": true + } + } + }, + "node_modules/@mintlify/scraping/node_modules/argparse": { + "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, + "license": "Python-2.0" + }, + "node_modules/@mintlify/scraping/node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@mintlify/scraping/node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@mintlify/scraping/node_modules/mdast-util-mdx-jsx": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz", + "integrity": "sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/scraping/node_modules/remark-gfm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/scraping/node_modules/remark-mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", + "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/scraping/node_modules/zod": { + "version": "3.24.0", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.0.tgz", + "integrity": "sha512-Hz+wiY8yD0VLA2k/+nsg2Abez674dDGTai33SwNvMPuf9uIrBC9eFgIMQxBBbHFxVXi8W+5nX9DcAh9YNSQm/w==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@mintlify/validation": { + "version": "0.1.890", + "resolved": "https://registry.npmjs.org/@mintlify/validation/-/validation-0.1.890.tgz", + "integrity": "sha512-8yoDXzIM+zPiFtjmDfcWGPxory1GyNw/pyS9erMe3ZpkkrXljDeJaWJGkBqnYlHUjR3hOBc9hyQQib0zM53mQw==", + "dev": true, + "license": "Elastic-2.0", + "dependencies": { + "@mintlify/mdx": "4.0.7", + "@mintlify/models": "0.0.365", + "fractional-indexing": "3.2.0", + "js-yaml": "4.3.1", + "lcm": "0.0.3", + "lodash": "4.18.1", + "neotraverse": "0.6.18", + "object-hash": "3.0.0", + "openapi-types": "12.1.3", + "uuid": "11.1.1", + "zod": "3.24.0", + "zod-to-json-schema": "3.20.4" + } + }, + "node_modules/@mintlify/validation/node_modules/@base-ui/react": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@base-ui/react/-/react-1.8.0.tgz", + "integrity": "sha512-P0/1sxo6SBVZOklKMIedvTWqw2s2IQzi9x5bIVsXu980cuSOD4NeuRSs+/L7LZQfDkZP/uRZyGPyfFl/B1oH+Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.29.7", + "@base-ui/utils": "0.4.0", + "@floating-ui/react-dom": "^2.1.9", + "@floating-ui/utils": "^0.2.12", + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@date-fns/tz": "^1.2.0", + "@types/react": "^17 || ^18 || ^19", + "date-fns": "^4.0.0", + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@date-fns/tz": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "date-fns": { + "optional": true + } + } + }, + "node_modules/@mintlify/validation/node_modules/@base-ui/utils": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@base-ui/utils/-/utils-0.4.0.tgz", + "integrity": "sha512-bO9fz25kKtPf+aZVyfQrC0PDmJdmVni31W2hCS5/Owb+inwdIL3XU26pCPRPlt4LSxZrBgLwubXQXQlKaFEZzw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.29.7", + "@floating-ui/utils": "^0.2.12", + "reselect": "^5.2.0", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "@types/react": "^17 || ^18 || ^19", + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mintlify/validation/node_modules/@floating-ui/react-dom": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz", + "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@floating-ui/dom": "^1.8.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@mintlify/validation/node_modules/@mintlify/mdx": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@mintlify/mdx/-/mdx-4.0.7.tgz", + "integrity": "sha512-/kOnIHvjM4jwF7WoXjPRp1nDLjgW8YFyApw5JQiXU6cEdXJdqpWH1xW+0rgGD4adi6yXY+Re9cfNRMftJzCo5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/transformers": "^3.23.0", + "@shikijs/twoslash": "^3.23.0", + "arktype": "^2.1.26", + "hast-util-to-string": "^3.0.1", + "mdast-util-from-markdown": "^2.0.2", + "mdast-util-gfm": "^3.1.0", + "mdast-util-mdx-jsx": "^3.2.0", + "mdast-util-to-hast": "^13.2.0", + "next-mdx-remote-client": "^2.1.11", + "rehype-katex": "^7.0.1", + "remark-gfm": "^4.0.0", + "remark-math": "^6.0.0", + "remark-smartypants": "^3.0.2", + "shiki": "^3.23.0", + "twoslash": "^0.3.4", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0" + }, + "peerDependencies": { + "@base-ui/react": "^1.6.0", + "react": "^19.2.1", + "react-dom": "^19.2.1" + } + }, + "node_modules/@mintlify/validation/node_modules/argparse": { + "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, + "license": "Python-2.0" + }, + "node_modules/@mintlify/validation/node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@mintlify/validation/node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mintlify/validation/node_modules/next-mdx-remote-client": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/next-mdx-remote-client/-/next-mdx-remote-client-2.1.12.tgz", + "integrity": "sha512-KDfhIk5aEM0kkZ0xQ8XBkmo4O5xmJeGWUomm40Ac/xhkt5sIDOTmTU/QFfmJGLJUJipD5o0BAHqVSIZKuXgNEw==", + "dev": true, + "license": "MPL 2.0", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@mdx-js/mdx": "^3.1.1", + "@mdx-js/react": "^3.1.1", + "@types/mdx": "^2.0.14", + "remark-mdx-remove-esm": "^1.3.2", + "serialize-error": "^13.0.1", + "vfile": "^6.0.3", + "vfile-matter": "^5.0.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "peerDependencies": { + "react": ">= 19.1.0", + "react-dom": ">= 19.1.0" + } + }, + "node_modules/@mintlify/validation/node_modules/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz", + "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@mintlify/validation/node_modules/react-dom": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.28.0" + }, + "peerDependencies": { + "react": "^19.3.0" + } + }, + "node_modules/@mintlify/validation/node_modules/scheduler": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz", + "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@mintlify/validation/node_modules/zod": { + "version": "3.24.0", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.0.tgz", + "integrity": "sha512-Hz+wiY8yD0VLA2k/+nsg2Abez674dDGTai33SwNvMPuf9uIrBC9eFgIMQxBBbHFxVXi8W+5nX9DcAh9YNSQm/w==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@mintlify/validation/node_modules/zod-to-json-schema": { + "version": "3.20.4", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.20.4.tgz", + "integrity": "sha512-Un9+kInJ2Zt63n6Z7mLqBifzzPcOyX+b+Exuzf7L1+xqck9Q2EPByyTRduV3kmSPaXaRer1JCsucubpgL1fipg==", + "dev": true, + "license": "ISC", + "peerDependencies": { + "zod": "^3.20.0" + } + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.0.tgz", + "integrity": "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@hono/node-server": "^1.19.9 || ^2.0.5", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "hono": "^4.11.4", + "jose": "^6.1.3", + "json-schema-typed": "^8.0.2", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.25 || ^4.0", + "zod-to-json-schema": "^3.25.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@cfworker/json-schema": "^4.1.1", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "@cfworker/json-schema": { + "optional": true + }, + "zod": { + "optional": false + } + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", + "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^2.0.0", + "debug": "^4.4.3", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", + "on-finished": "^2.4.1", + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser/node_modules/content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", + "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/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", + "optional": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.1.tgz", + "integrity": "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.1.0.tgz", + "integrity": "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "content-type": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator/node_modules/content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", + "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "content-type": "^2.0.0", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/type-is/node_modules/content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@nodable/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-9uGyhaQavEUMC8AIddIjau4NsnsXhou+j5sBAGojCM1oxmQpVKTWR/9JxABD6UAv12vpIms55fPZKFQEhG6uBg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@openai/codex": { + "version": "0.149.1", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.149.1.tgz", + "integrity": "sha512-6q5pbcpFbJbqOpkubSDBwXmktQ55aD8eUzGzBF1zASob2DjwhBKDSNGtdZKalfrNJUdTDTPDMmzCXEXs5tMBYA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "bin": { + "codex": "bin/codex.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@openai/codex-darwin-arm64": "npm:@openai/codex@0.149.1-darwin-arm64", + "@openai/codex-darwin-x64": "npm:@openai/codex@0.149.1-darwin-x64", + "@openai/codex-linux-arm64": "npm:@openai/codex@0.149.1-linux-arm64", + "@openai/codex-linux-x64": "npm:@openai/codex@0.149.1-linux-x64", + "@openai/codex-win32-arm64": "npm:@openai/codex@0.149.1-win32-arm64", + "@openai/codex-win32-x64": "npm:@openai/codex@0.149.1-win32-x64" + } + }, + "node_modules/@openai/codex-darwin-arm64": { + "name": "@openai/codex", + "version": "0.149.1-darwin-arm64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.149.1-darwin-arm64.tgz", + "integrity": "sha512-6X84kTCbnTgPIJ2EdcPsrvwS0Wxsqpa+bCswGmRf4BjhcQ5nPMnBC6yCAaCMj+vrbXQHj+L6sa9FaR4QkmA1qw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@openai/codex-darwin-x64": { + "name": "@openai/codex", + "version": "0.149.1-darwin-x64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.149.1-darwin-x64.tgz", + "integrity": "sha512-MfLBQLfcElJL9tvj6y45qVHHMGSXCPnQOixuD3/Zq0g1BW/eFizkrGLdn48cFpc+l8cK+gt5nYG5pQYwVs6g4A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@openai/codex-linux-arm64": { + "name": "@openai/codex", + "version": "0.149.1-linux-arm64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.149.1-linux-arm64.tgz", + "integrity": "sha512-OqxUfZ1TVvHd18zHPKK/8ZRlpk8Vy11mg5CMHaLxNWldTbwVImDKtSLWT+m8m4NM5Sz4PbjtZMrVT/RfpBW/mQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@openai/codex-linux-x64": { + "name": "@openai/codex", + "version": "0.149.1-linux-x64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.149.1-linux-x64.tgz", + "integrity": "sha512-Of5fGYgr7tAMsyj6vhXb4/RM/UoA3Zq8BLegUBDC09UNy1XTLGYP/2XD+UX8z3qh0NDwxYdCjFIWdDNijKZggQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@openai/codex-sdk": { + "version": "0.149.1", + "resolved": "https://registry.npmjs.org/@openai/codex-sdk/-/codex-sdk-0.149.1.tgz", + "integrity": "sha512-R00Rz5327LefZggAxl28r7vFQq1vxa91OxtjZJOsQfAM/MyH8InW5qwwRu6pzUmRGp1E29XrOzm7u1TeV5Yz2A==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@openai/codex": "0.149.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@openai/codex-win32-arm64": { + "name": "@openai/codex", + "version": "0.149.1-win32-arm64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.149.1-win32-arm64.tgz", + "integrity": "sha512-5K0DmOKGK9Bos627p8sK8ATHjovPK0sDyT6h9Cb+4v+5CW5SGw1HLgjGxoLfJ8g3cg6mtg/pRCXXo2L/j71UVA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@openai/codex-win32-x64": { + "name": "@openai/codex", + "version": "0.149.1-win32-x64", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.149.1-win32-x64.tgz", + "integrity": "sha512-G3QXGAg7nyyhqOeooAMUekBCeHd8a1QByhKcVAFyzNBaI06t6Ft7nsF+1SzFS0spuIdU4YyMi5YD26ukADBQUQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@openapi-contrib/openapi-schema-to-json-schema": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@openapi-contrib/openapi-schema-to-json-schema/-/openapi-schema-to-json-schema-3.2.0.tgz", + "integrity": "sha512-Gj6C0JwCr8arj0sYuslWXUBSP/KnUlEGnPW4qxlXvAl543oaNQgMgIgkQUA6vs5BCCvwTEiL8m/wdWzfl4UvSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + } + }, + "node_modules/@posthog/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.7.1.tgz", + "integrity": "sha512-kjK0eFMIpKo9GXIbts8VtAknsoZ18oZorANdtuTj1CbgS28t4ZVq//HAWhnxEuXRTrtkd+SUJ6Ux3j2Af8NCuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.6" + } + }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/@shikijs/core": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.23.0.tgz", + "integrity": "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + } + }, + "node_modules/@shikijs/core/node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.23.0.tgz", + "integrity": "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.4" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz", + "integrity": "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.23.0.tgz", + "integrity": "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.23.0.tgz", + "integrity": "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@shikijs/transformers": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-3.23.0.tgz", + "integrity": "sha512-F9msZVxdF+krQNSdQ4V+Ja5QemeAoTQ2jxt7nJCwhDsdF1JWS3KxIQXA3lQbyKwS3J61oHRUSv4jYWv3CkaKTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "3.23.0", + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@shikijs/twoslash": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/twoslash/-/twoslash-3.23.0.tgz", + "integrity": "sha512-pNaLJWMA3LU7PhT8tm9OQBZ1epy0jmdgeJzntBtr1EVXLbHxGzTj3mnf9vOdcl84l96qnlJXkJ/NGXZYBpXl5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "3.23.0", + "@shikijs/types": "3.23.0", + "twoslash": "^0.3.6" + }, + "peerDependencies": { + "typescript": ">=5.5.0" + } + }, + "node_modules/@shikijs/types": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", + "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "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, + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sindresorhus/slugify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.0.tgz", + "integrity": "sha512-9Vybc/qX8Kj6pxJaapjkFbiUJPk7MAkCh/GFCxIBnnsuYCFPIXKvnLidG8xlepht3i24L5XemUmGtrJ3UWrl6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/transliterate": "^1.0.0", + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sindresorhus/transliterate": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-1.6.0.tgz", + "integrity": "sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@stablelib/base64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz", + "integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@stoplight/better-ajv-errors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@stoplight/better-ajv-errors/-/better-ajv-errors-1.0.3.tgz", + "integrity": "sha512-0p9uXkuB22qGdNfy3VeEhxkU5uwvp/KrBTAbrLBURv6ilxIVwanKwjMc41lQfIVgPGcOkmLbTolfFrSsueu7zA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": "^12.20 || >= 14.13" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, + "node_modules/@stoplight/better-ajv-errors/node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@stoplight/json": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/@stoplight/json/-/json-3.21.0.tgz", + "integrity": "sha512-5O0apqJ/t4sIevXCO3SBN9AHCEKKR/Zb4gaj7wYe5863jme9g02Q0n/GhM7ZCALkL+vGPTe4ZzTETP8TFtsw3g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@stoplight/ordered-object-literal": "^1.0.3", + "@stoplight/path": "^1.3.2", + "@stoplight/types": "^13.6.0", + "jsonc-parser": "~2.2.1", + "lodash": "^4.17.21", + "safe-stable-stringify": "^1.1" + }, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/@stoplight/json-ref-readers": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@stoplight/json-ref-readers/-/json-ref-readers-1.2.2.tgz", + "integrity": "sha512-nty0tHUq2f1IKuFYsLM4CXLZGHdMn+X/IwEUIpeSOXt0QjMUbL0Em57iJUDzz+2MkWG83smIigNZ3fauGjqgdQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-fetch": "^2.6.0", + "tslib": "^1.14.1" + }, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/@stoplight/json-ref-resolver": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@stoplight/json-ref-resolver/-/json-ref-resolver-3.1.6.tgz", + "integrity": "sha512-YNcWv3R3n3U6iQYBsFOiWSuRGE5su1tJSiX6pAPRVk7dP0L7lqCteXGzuVRQ0gMZqUl8v1P0+fAKxF6PLo9B5A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@stoplight/json": "^3.21.0", + "@stoplight/path": "^1.3.2", + "@stoplight/types": "^12.3.0 || ^13.0.0", + "@types/urijs": "^1.19.19", + "dependency-graph": "~0.11.0", + "fast-memoize": "^2.5.2", + "immer": "^9.0.6", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "urijs": "^1.19.11" + }, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/@stoplight/json-ref-resolver/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@stoplight/json/node_modules/jsonc-parser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", + "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@stoplight/ordered-object-literal": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@stoplight/ordered-object-literal/-/ordered-object-literal-1.0.5.tgz", + "integrity": "sha512-COTiuCU5bgMUtbIFBuyyh2/yVVzlr5Om0v5utQDgBCuQUOPgU1DwoffkTfg4UBQOvByi5foF4w4T+H9CoRe5wg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/@stoplight/path": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@stoplight/path/-/path-1.3.2.tgz", + "integrity": "sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/@stoplight/spectral-core": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.24.0.tgz", + "integrity": "sha512-abKt++GFFaqwKiGTfPZ5O3nIv8s+1V7J5awCjWPBtCXn7ZKTEPzEF8tBYsM3ne+RMrQ8ORkHzKFu9QZhenmkPw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "^1.4.0", + "@stoplight/better-ajv-errors": "1.0.3", + "@stoplight/json": "~3.21.0", + "@stoplight/path": "1.3.2", + "@stoplight/spectral-parsers": "^1.0.0", + "@stoplight/spectral-ref-resolver": "^1.0.4", + "@stoplight/spectral-runtime": "^1.1.2", + "@stoplight/types": "~13.6.0", + "@types/es-aggregate-error": "^1.0.2", + "@types/json-schema": "^7.0.11", + "ajv": "^8.18.0", + "ajv-errors": "~3.0.0", + "ajv-formats": "~2.1.1", + "es-aggregate-error": "^1.0.7", + "expr-eval-fork": "^3.0.1", + "jsonpath-plus": "^10.3.0", + "lodash": "^4.18.1", + "lodash.topath": "^4.5.2", + "minimatch": "^3.1.4", + "nimma": "0.2.3", + "pony-cause": "^1.1.1", + "tslib": "^2.8.1" + }, + "engines": { + "node": "^16.20 || ^18.18 || >= 20.17" + } + }, + "node_modules/@stoplight/spectral-core/node_modules/@stoplight/types": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.6.0.tgz", + "integrity": "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" + }, + "engines": { + "node": "^12.20 || >=14.13" + } + }, + "node_modules/@stoplight/spectral-core/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@stoplight/spectral-formats": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-formats/-/spectral-formats-1.9.0.tgz", + "integrity": "sha512-OmHZpeBdlWbDxAI43HR08vyVXY2D++YHBx9AWMQ6S2DH8aWWCvk64BJOJk161XsHJQuy/vnC8tRBIIKwSQPAsA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "^1.4.0", + "@stoplight/json": "^3.17.0", + "@stoplight/spectral-core": "^1.23.0", + "@types/json-schema": "^7.0.7", + "tslib": "^2.8.1" + }, + "engines": { + "node": "^16.20 || ^18.18 || >= 20.17" + } + }, + "node_modules/@stoplight/spectral-formats/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@stoplight/spectral-functions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-functions/-/spectral-functions-1.11.0.tgz", + "integrity": "sha512-HFlFhI+q13GqG8pphY4nNGYq9+5L14dhR9xLqx+/H2/FmAouHTfNaqE4SygIhSmtMxfNDJ8G4qnjxiQRv1kPWA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "^1.4.0", + "@stoplight/better-ajv-errors": "1.0.3", + "@stoplight/json": "^3.17.1", + "@stoplight/spectral-core": "^1.23.0", + "@stoplight/spectral-formats": "^1.8.1", + "@stoplight/spectral-runtime": "^1.1.2", + "ajv": "^8.18.0", + "ajv-draft-04": "~1.0.0", + "ajv-errors": "~3.0.0", + "ajv-formats": "~2.1.1", + "lodash": "^4.18.1", + "tslib": "^2.8.1" + }, + "engines": { + "node": "^16.20 || ^18.18 || >= 20.17" + } + }, + "node_modules/@stoplight/spectral-functions/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@stoplight/spectral-parsers": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-parsers/-/spectral-parsers-1.0.5.tgz", + "integrity": "sha512-ANDTp2IHWGvsQDAY85/jQi9ZrF4mRrA5bciNHX+PUxPr4DwS6iv4h+FVWJMVwcEYdpyoIdyL+SRmHdJfQEPmwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@stoplight/json": "~3.21.0", + "@stoplight/types": "^14.1.1", + "@stoplight/yaml": "~4.3.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": "^16.20 || ^18.18 || >= 20.17" + } + }, + "node_modules/@stoplight/spectral-parsers/node_modules/@stoplight/types": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-14.1.1.tgz", + "integrity": "sha512-/kjtr+0t0tjKr+heVfviO9FrU/uGLc+QNX3fHJc19xsCNYqU7lVhaXxDmEID9BZTjG+/r9pK9xP/xU02XGg65g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" + }, + "engines": { + "node": "^12.20 || >=14.13" + } + }, + "node_modules/@stoplight/spectral-parsers/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@stoplight/spectral-ref-resolver": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ref-resolver/-/spectral-ref-resolver-1.0.5.tgz", + "integrity": "sha512-gj3TieX5a9zMW29z3mBlAtDOCgN3GEc1VgZnCVlr5irmR4Qi5LuECuFItAq4pTn5Zu+sW5bqutsCH7D4PkpyAA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@stoplight/json-ref-readers": "1.2.2", + "@stoplight/json-ref-resolver": "~3.1.6", + "@stoplight/spectral-runtime": "^1.1.2", + "dependency-graph": "0.11.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": "^16.20 || ^18.18 || >= 20.17" + } + }, + "node_modules/@stoplight/spectral-ref-resolver/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@stoplight/spectral-runtime": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-runtime/-/spectral-runtime-1.1.6.tgz", + "integrity": "sha512-Y8rEDyMN4bSMJCrDs2shdcVHYyCnH3FvXRP4dBhha4Z8iJv+JPp7KqOV/hwVB/hWFC209upiwj2oDmLfR0qCDg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@stoplight/json": "^3.20.1", + "@stoplight/path": "^1.3.2", + "@stoplight/types": "^13.6.0", + "lodash": "^4.18.1", + "node-fetch": "^2.7.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": "^16.20 || ^18.18 || >= 20.17" + } + }, + "node_modules/@stoplight/spectral-runtime/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@stoplight/spectral-runtime/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@stoplight/types": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-13.20.0.tgz", + "integrity": "sha512-2FNTv05If7ib79VPDA/r9eUet76jewXFH2y2K5vuge6SXbRHtWBhcaRmu+6QpF4/WRNoJj5XYRSwLGXDxysBGA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" + }, + "engines": { + "node": "^12.20 || >=14.13" + } + }, + "node_modules/@stoplight/yaml": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@stoplight/yaml/-/yaml-4.3.0.tgz", + "integrity": "sha512-JZlVFE6/dYpP9tQmV0/ADfn32L9uFarHWxfcRhReKUnljz1ZiUM5zpX+PH8h5CJs6lao3TuFqnPm9IJJCEkE2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@stoplight/ordered-object-literal": "^1.0.5", + "@stoplight/types": "^14.1.1", + "@stoplight/yaml-ast-parser": "0.0.50", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=10.8" + } + }, + "node_modules/@stoplight/yaml-ast-parser": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@stoplight/yaml-ast-parser/-/yaml-ast-parser-0.0.50.tgz", + "integrity": "sha512-Pb6M8TDO9DtSVla9yXSTAxmo9GVEouq5P40DWXdOie69bXogZTkgvopCq+yEvTMA0F6PEvdJmbtTV3ccIp11VQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@stoplight/yaml/node_modules/@stoplight/types": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@stoplight/types/-/types-14.1.1.tgz", + "integrity": "sha512-/kjtr+0t0tjKr+heVfviO9FrU/uGLc+QNX3fHJc19xsCNYqU7lVhaXxDmEID9BZTjG+/r9pK9xP/xU02XGg65g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.4", + "utility-types": "^3.10.0" + }, + "engines": { + "node": "^12.20 || >=14.13" + } + }, + "node_modules/@stoplight/yaml/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/es-aggregate-error": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/es-aggregate-error/-/es-aggregate-error-1.0.6.tgz", + "integrity": "sha512-qJ7LIFp06h1QE1aVxbVd+zJP2wdaugYXYfd6JxsyRMrYHaxb6itXPogW2tz+ylUJ1n1b+JF1PHyYCfYHm0dvUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz", + "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "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, + "license": "MIT" + }, + "node_modules/@types/katex": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz", + "integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.14.tgz", + "integrity": "sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/nlcst": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", + "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/node": { + "version": "26.6.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.4.tgz", + "integrity": "sha512-ldVPDCzj7fsaGZrLB0NuHuTvJcsNasysBAqMolr/cgxrLd1xbqxIr3XJiPnHHJUCxj5sNF1vnRj9aWnrVh5Jcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~8.9.0" + } + }, + "node_modules/@types/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz", + "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/unist": { + "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, + "license": "MIT" + }, + "node_modules/@types/urijs": { + "version": "1.19.26", + "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.26.tgz", + "integrity": "sha512-wkXrVzX5yoqLnndOwFsieJA7oKM8cNkOKJtf/3vVGSUFkWDKZvFHpIl9Pvqb/T9UsawBBFMTTD8xu7sK5MWuvg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-67MQl+fpWKVTT1NYdnmo3U4sc/xPo/zQBncVnI74qmQa0z/b+1g6iYqNmGCPbxO+zz2aklb08a0oHfegiVd0/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript/vfs": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.5.tgz", + "integrity": "sha512-gobLHQLmvQGJInFk31NvgMd1uYzRXsd8qgnOssyLD055R2QPnw1ubRbBQ4+T+5qC7IQVuYXdvNDE2G7tMDVHgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.3" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.4.0.tgz", + "integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/adm-zip": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.6.1.tgz", + "integrity": "sha512-Xwrja8nx9e5o2N1my4DsKCeKpdrnACyr1wtbPxBDgGzKzKyE9kRtBFA8mWldI+RVlD7CBZNWY/wQ2+ydwOR6kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "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/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", + "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^8.0.1" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "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" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.4.0.tgz", + "integrity": "sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anynum": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.1.tgz", + "integrity": "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/arkregex": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/arkregex/-/arkregex-0.0.12.tgz", + "integrity": "sha512-sOxL0eX50pnRYO4OyajKZChGuuj/iHwC5tysiAaGOPBu+zJwJQckWn7/DRH2++ol5uaKpyRn7N0hKT7nDqGmgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ark/util": "0.56.6" + } + }, + "node_modules/arktype": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/arktype/-/arktype-2.2.7.tgz", + "integrity": "sha512-AbgM5SQvwCTURSR+ENfPtOG7cL5VZ0hqOVtoWyXKw2SviFddZhCBEUAjjVJYKCNFlPPR1VX5LGUKxsSqqc4Kdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ark/schema": "0.56.6", + "@ark/util": "0.56.6", + "arkregex": "0.0.12" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-iterate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", + "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "dev": true, + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/auto-bind": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-5.0.1.tgz", + "integrity": "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/avsc": { + "version": "5.7.9", + "resolved": "https://registry.npmjs.org/avsc/-/avsc-5.7.9.tgz", + "integrity": "sha512-yOA4wFeI7ET3v32Di/sUybQ+ttP20JHSW3mxLuNGeO0uD6PPcvLrIQXSvy/rhJOWU5JrYh7U4OHplWMmtAtjMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.11" + } + }, + "node_modules/axios": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.20.0.tgz", + "integrity": "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.6", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "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/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/better-opn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", + "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "open": "^8.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.8", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.8.tgz", + "integrity": "sha512-JNcyFQ64OiijEkPzUBTCe+hyPXUD/3LEldGQ6iF5LR1w00mx9o7xtDWHXBY2iItjdCFGoilOLNQbH943ut7pHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.16.0", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chardet": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz", + "integrity": "sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==", + "dev": true, + "license": "MIT" + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "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/cliui/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/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "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" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/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/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "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" + } + }, + "node_modules/cliui/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/cliui/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/cliui/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/code-excerpt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "convert-to-spaces": "^2.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "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" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-to-spaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "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", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssfilter": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", + "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-bmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/decode-bmp/-/decode-bmp-0.2.1.tgz", + "integrity": "sha512-NiOaGe+GN0KJqi2STf24hfMkFitDUaIoUU3eKvP/wAbLe8o6FuW5n/x7MHPR0HKvBokp6MQY/j7w8lewEeVCIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@canvas/image-data": "^1.0.0", + "to-data-view": "^1.1.0" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/decode-ico": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/decode-ico/-/decode-ico-0.4.1.tgz", + "integrity": "sha512-69NZfbKIzux1vBOd31al3XnMnH+2mqDhEgLdpygErm4d60N+UwA5Sq5WFjmEDQzumgB9fElojGwWG0vybVfFmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@canvas/image-data": "^1.0.0", + "decode-bmp": "^0.2.0", + "to-data-view": "^1.1.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "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" + } + }, + "node_modules/dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-port": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", + "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dns-socket": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/dns-socket/-/dns-socket-4.2.2.tgz", + "integrity": "sha512-BDeBd8najI4/lS00HSKpdFia+OvUMytaVjfzR9n5Lq8MlZRSvtbI+uLtx1+XmQFls5wFU9dssccTmQQ6nfpjdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.4" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.6.11", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.11.tgz", + "integrity": "sha512-z34mGpLoY/82ZbkX1LqGMIaf3wjVMPL6gVC681QDqnmzJ26synI8qAE32P+a7UazmpJZ8UGrFIeAavgRfXzYrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "@types/ws": "^8.5.12", + "accepts": "~1.3.4", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.4.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.21.0" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-aggregate-error": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.14.tgz", + "integrity": "sha512-3YxX6rVb07B5TV11AV5wsL7nQCHXNwoHPsQC8S4AmBiqYhyNCJ5BRKXkXyDJvs8QzXN20NgRtxe3dEEQD9NLHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "globalthis": "^1.0.4", + "has-property-descriptors": "^1.0.2", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-toolkit": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.52.0.tgz", + "integrity": "sha512-XTNEJQh1tY1ZJVcf6ayP/2n4ZPyaHlW2FWs7xvw5ddPuhUVjLD3olQVQS7kf58JbAB48iL0uL/jerTrjtV3lDA==", + "dev": true, + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks", + "tests/types", + "tests/browser-compat" + ] + }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "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" + } + }, + "node_modules/escape-html": { + "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, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.1.tgz", + "integrity": "sha512-B0np3dcdxqILX5e9nEi5/Fr4K7gL4oYFVPV1zRa2e9wRCbQoZZNWOZFYyoInvXUPJXBXjss+QXlWLJChDEHDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.1.tgz", + "integrity": "sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "license": "(MIT OR WTFPL)", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/expr-eval-fork": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/expr-eval-fork/-/expr-eval-fork-3.0.3.tgz", + "integrity": "sha512-BhC+hbc5lIVjygr840n5DEkW3MQq7H9o+mc1/N7Z5uIiCFVyESLL5DIE7LNq4CYUNxy+XjA+3jRrL/h0Kt2xcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/express": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.0.tgz", + "integrity": "sha512-c2iPh3xp5vvCLgaHK03+mWLFPhox7j1LwyxcZwFVApEv5i0X+IjPpbT50SJJwwLpdBVfp45AkK/v+AFgv/XlfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.7.0.tgz", + "integrity": "sha512-hOwV7WOxXfjRpAM1DSJWZDXx3GhplwD8IfwuwvogD8i1Qnkgosw/H45s4ZnFAUHDAhPjlY9hLBvJhKmGMyY26g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "^4.4.3", + "ip-address": "^10.2.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-memoize": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", + "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-sha256": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz", + "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==", + "dev": true, + "license": "Unlicense", + "optional": true + }, + "node_modules/fast-uri": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz", + "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fast-xml-builder": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.3.1.tgz", + "integrity": "sha512-pIM/1n3ntFXKYrUZwW7QCK0gAW7XY+wzj1YMIV3tLDvPj/V+zTGJK5e3/4WJfwj0qWw2ElNXiTixda/R+3YSug==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.6.2", + "xml-naming": "^0.3.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.3.tgz", + "integrity": "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^2.1.0", + "fast-xml-builder": "^1.1.7", + "path-expression-matcher": "^1.5.0", + "strnum": "^2.2.3" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz", + "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/favicons": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/favicons/-/favicons-7.2.0.tgz", + "integrity": "sha512-k/2rVBRIRzOeom3wI9jBPaSEvoTSQEW4iM0EveBmBBKFxO8mSyyRWtDlfC3VnEfu0avmjrMzy8/ZFPSe6F71Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-html": "^1.0.3", + "sharp": "^0.33.1", + "xml2js": "^0.6.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/fflate": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/follow-redirects": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.1.tgz", + "integrity": "sha512-FNvFGzoMLWmE6Yj9spb/zjd7yiNCHiAW9/Tg9CXrQ8wuu32HtlJOwWO11OJafl5FfY3DxTdQ0vj42zU1kvv5jg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fractional-indexing": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fractional-indexing/-/fractional-indexing-3.2.0.tgz", + "integrity": "sha512-PcOxmqwYCW7O2ovKRU8OoQQj2yqTfEB/yeTYk4gPid6dN5ODRfU1hXd9tTVZzax/0NkO7AxpHykvZnT1aYp/BQ==", + "dev": true, + "license": "CC0-1.0", + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/front-matter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", + "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "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/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gcd": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/gcd/-/gcd-0.0.1.tgz", + "integrity": "sha512-VNx3UEGr+ILJTiMs1+xc5SX1cMgJCrXezKPa003APUWNqQqaF6n25W8VcR7nHN6yRWbvvUTwCpZCFJeWC2kXlw==", + "dev": true, + "license": "MIT" + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "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.7.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.7.0.tgz", + "integrity": "sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", + "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "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, + "license": "ISC" + }, + "node_modules/graphql": { + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz", + "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-embedded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz", + "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-dom": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz", + "integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "@types/hast": "^3.0.0", + "hastscript": "^9.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html-isomorphic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz", + "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-dom": "^5.0.0", + "hast-util-from-html": "^2.0.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-has-property": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", + "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-body-ok-link": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz", + "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-minify-whitespace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz", + "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-is-body-ok-link": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz", + "integrity": "sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^0.4.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree/node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.4.tgz", + "integrity": "sha512-wxQzXtdbhiwGAUKrnQJXlOPmHnEehzphwkK7aluUPQ+lEc1xefC8pblMgpp2w5ldBTEfveRIrADcrhGIWrlTDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html/node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-mdast": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-mdast/-/hast-util-to-mdast-10.1.0.tgz", + "integrity": "sha512-DsL/SvCK9V7+vfc6SLQ+vKIyBDXTk2KLSbfBYkH4zeF/uR1yBajHRhkzuaUSGOB1WJSTieJBdHwxlC+HLKvZZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-phrasing": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "hast-util-to-text": "^4.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-minify-whitespace": "^6.0.0", + "trim-trailing-lines": "^2.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-string": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", + "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hono": { + "version": "4.13.13", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.13.tgz", + "integrity": "sha512-CQ46U0ZkAGmbT/4UxdzzGJpacP2IeKgY4a5/tOI9AABbpOMfK739wfDXmv1usCk+3RkKj1hQy4/fjhiwa2xlrA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.3.0.tgz", + "integrity": "sha512-M5t5LlJpS1UHMjvwRQVdFHvPISGeLAxNcrWuJkeGh0KxsqCHZ1O3NXZU/8x7cD0BDcGW8kapxMKTvwlqrNkHkA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ico-endec": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ico-endec/-/ico-endec-0.1.6.tgz", + "integrity": "sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ==", + "dev": true, + "license": "MPL-2.0" + }, + "node_modules/iconv-lite": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/ink": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ink/-/ink-6.3.0.tgz", + "integrity": "sha512-2CbJAa7XeziZYe6pDS5RVLirRY28iSGMQuEV8jRU5NQsONQNfcR/BZHHc9vkMg2lGYTHTM2pskxC1YmY28p6bQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alcalzone/ansi-tokenize": "^0.2.0", + "ansi-escapes": "^7.0.0", + "ansi-styles": "^6.2.1", + "auto-bind": "^5.0.1", + "chalk": "^5.6.0", + "cli-boxes": "^3.0.0", + "cli-cursor": "^4.0.0", + "cli-truncate": "^4.0.0", + "code-excerpt": "^4.0.0", + "es-toolkit": "^1.39.10", + "indent-string": "^5.0.0", + "is-in-ci": "^2.0.0", + "patch-console": "^2.0.0", + "react-reconciler": "^0.32.0", + "signal-exit": "^3.0.7", + "slice-ansi": "^7.1.0", + "stack-utils": "^2.0.6", + "string-width": "^7.2.0", + "type-fest": "^4.27.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0", + "ws": "^8.18.0", + "yoga-layout": "~3.2.1" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@types/react": ">=19.0.0", + "react": ">=19.0.0", + "react-devtools-core": "^4.19.1" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react-devtools-core": { + "optional": true + } + } + }, + "node_modules/ink-spinner": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ink-spinner/-/ink-spinner-5.0.0.tgz", + "integrity": "sha512-EYEasbEjkqLGyPOUc8hBJZNuC5GvXGMLu0w5gdTNskPc7Izc5vO3tdQEYnzvshucyGCBXc86ig0ujXPMWaQCdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-spinners": "^2.7.0" + }, + "engines": { + "node": ">=14.16" + }, + "peerDependencies": { + "ink": ">=4.0.0", + "react": ">=18.0.0" + } + }, + "node_modules/ink/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ink/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ink/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "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/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/inquirer": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.3.0.tgz", + "integrity": "sha512-3NixUXq+hM8ezj2wc7wC37b32/rHq1MwNZDYdvx+d6jokOD+r+i8Q4Pkylh9tISYP114A128LCX8RKhopC5RfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.2", + "@inquirer/prompts": "^7.2.1", + "@inquirer/type": "^3.0.2", + "ansi-escapes": "^4.3.2", + "mute-stream": "^2.0.0", + "run-async": "^3.0.0", + "rxjs": "^7.8.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/inquirer/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ip-address": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.3.tgz", + "integrity": "sha512-A1kdq/tSb5QjvKvAMgIoEvDBIgL7qaqVP/jkvSwYYRZ9iEzvPpopxp2wQfu3SuZRHtpHNxMn8Fs0bS+gf5Xmwg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/iregexp-check": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/iregexp-check/-/iregexp-check-0.1.2.tgz", + "integrity": "sha512-RCcV2SFO5JKh+DdmWiY7yVyiZzzk6XZiHEJvTKbzVs8Z0u404gnoSqDtFqg6C5qJBEG4QseWBQz9zhI68zskEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.17.0.tgz", + "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-in-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-in-ci/-/is-in-ci-2.0.0.tgz", + "integrity": "sha512-cFeerHriAnhrQSbpAxL37W1wcJKUUX07HyLWZCW1URJT/ra3GyUTzBgUnh24TMVfNTV2Hij2HLxkPHFZfOZy5w==", + "dev": true, + "license": "MIT", + "bin": { + "is-in-ci": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-ip": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz", + "integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-regex": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-online": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/is-online/-/is-online-10.0.0.tgz", + "integrity": "sha512-WCPdKwNDjXJJmUubf2VHLMDBkUZEtuOvpXUfUnUFbEnM6In9ByiScL4f4jKACz/fsb2qDkesFerW3snf/AYz3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "got": "^12.1.0", + "p-any": "^4.0.0", + "p-timeout": "^5.1.0", + "public-ip": "^5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-online/node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/jose": { + "version": "6.2.12", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.12.tgz", + "integrity": "sha512-9NiFmJEex0sy2Dk58j2UGBSHgUs2ypF9eZSu4L6vjOX3Dp96Sw1F3uL+H+D1sx02jZZdzUT0HgvCy59CuvXcWw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.2.tgz", + "integrity": "sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsep": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", + "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-p3": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/json-p3/-/json-p3-2.2.2.tgz", + "integrity": "sha512-TmTgkx+C1ne8Wdm9dFQ4/jCeYYbSoeYJAkRpvTz6O+zWN1Dc3cKW8Mt52sa8mSRXy/+JykA5I6rmM+k8h+JRRg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "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/json-schema-typed": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", + "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpath-plus": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.4.0.tgz", + "integrity": "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jsep-plugin/assignment": "^1.3.0", + "@jsep-plugin/regex": "^1.0.4", + "jsep": "^1.4.0" + }, + "bin": { + "jsonpath": "bin/jsonpath-cli.js", + "jsonpath-plus": "bin/jsonpath-cli.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/katex": { + "version": "0.16.47", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz", + "integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==", + "dev": true, + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lcm": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/lcm/-/lcm-0.0.3.tgz", + "integrity": "sha512-TB+ZjoillV6B26Vspf9l2L/vKaRY/4ep3hahcyVkCGFgsTNRUQdc24bQeNFiZeoxH0vr5+7SfNRMQuPHv/1IrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "gcd": "^0.0.1" + } + }, + "node_modules/leven": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-4.1.0.tgz", + "integrity": "sha512-KZ9W9nWDT7rF7Dazg8xyLHGLrmpgq2nVNFUckhqdW3szVP6YhCpp/RAnpmVExA9JvrMynjwSLVrEj3AepHR6ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.topath": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz", + "integrity": "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==", + "dev": true, + "license": "MIT" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.3.tgz", + "integrity": "sha512-xPgpDNl0/OXHsI7TlaIs22lWnH3KlpvZdXG1ET/m/YT2Hhdkx8lJV4kLphE6l9simyM4KPDFBwas08BgEob6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", + "integrity": "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "escape-string-regexp": "^5.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.1.tgz", + "integrity": "sha512-OuJHqvr455pwu2OaOrir7dbzqs4jlWKOtlu9L6GjcIjjQwNyw02VntQsr/Ek6/A13vgnXfUhBekWRUP1OkNivw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-math": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", + "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "longest-streak": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.1.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.2.0.tgz", + "integrity": "sha512-2Jn/ADrHFFyyniBMi0bncTbJqU78K3/TEYvzvwrWWzD9MYPUa/Gm4r3nOeKFQg/PDM5BsbDYdc8ackW4NTY6NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.3.tgz", + "integrity": "sha512-oGYfQzHSG5dOMovQcJ3fyTmZlWAWpi0XA0sJwJs+i6OT88o1+Jtw/8z0CmdowSLxGhhFK89rQ/oXph/wN02PNw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-edit-map": "^1.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.4.tgz", + "integrity": "sha512-wxEeE8v8XVvOrxn1TZj74qYhAtTQsSqufHVS3uNVyT1MupXxhyaHk8/9xDNPh9BmL77QNDgWTkZ3RsYHB2ry7w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.1.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-edit-map": "^1.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.3" + } + }, + "node_modules/micromark-extension-frontmatter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", + "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.2.tgz", + "integrity": "sha512-pRzm4kDTu0MjlmBkxmS9yYhw60nncfcEwu9NNdPFSQEFXS95ZKyIIyTSHu/o3ReBUrLKYEq+7YaXCRn/bPB4MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.1.0.tgz", + "integrity": "sha512-fS8hnLIjnjvdQIj39Geug8wWsR0HrYZ43KShKxNfwT7t2LOHo/LbWZEzEaSOjwtjdCsjoE6syHhonEzW0zv0+Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-edit-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-edit-map/-/micromark-util-edit-map-1.0.0.tgz", + "integrity": "sha512-Pa2ljlsEL6sVwFaYeyrOLSYbQt73JvGbPOYFq+9AElXiSnfI5Q4465RRZ1sHv7lDjDOnGRDDaqPXqClqWK/q1Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.3.tgz", + "integrity": "sha512-oxB2Ik03hI0gv+VNn9tnh1t1YEe9MDPptViAEgfdf3YQHsn0pzGTgCdlSCJXcwhqm8phaEuM7zeEu3QQzVBrPg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "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" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "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" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mint": { + "version": "4.2.981", + "resolved": "https://registry.npmjs.org/mint/-/mint-4.2.981.tgz", + "integrity": "sha512-dXoklJcBCj9IzGi2XXpnr4L4+SPiTOyvY7TPMaGaHe8FrTx+j+vQwwnML+YP1tGNLZ1kPR+9YVqAEnzeDF8vSw==", + "dev": true, + "license": "Elastic-2.0", + "dependencies": { + "@mintlify/cli": "4.0.1584" + }, + "bin": { + "mint": "index.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neotraverse": { + "version": "0.6.18", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", + "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/nimma": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/nimma/-/nimma-0.2.3.tgz", + "integrity": "sha512-1ZOI8J+1PKKGceo/5CT5GfQOG6H8I2BencSK06YarZ2wXwH37BSSUWldqJmMJYA5JfqDqffxDXynt6f11AyKcA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsep-plugin/regex": "^1.0.1", + "@jsep-plugin/ternary": "^1.0.2", + "astring": "^1.8.1", + "jsep": "^1.2.0" + }, + "engines": { + "node": "^12.20 || >=14.13" + }, + "optionalDependencies": { + "jsonpath-plus": "^6.0.1 || ^10.1.0", + "lodash.topath": "^4.5.2" + } + }, + "node_modules/nlcst-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/node-abi": { + "version": "3.97.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.97.0.tgz", + "integrity": "sha512-6Pu8F0eXGZlyz0EepPJrWgWDcBI8rKt2Wj8exOJU1tjVbu/VyZy5ZaLYS5N+Jp/Y3IP3sIRKcIOElTu7uC6KKA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/non-error": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/non-error/-/non-error-0.1.0.tgz", + "integrity": "sha512-TMB1uHiGsHRGv1uYclfhivcnf0/PdFp2pNqRxXjncaAsjYMoisaQJI+SSZCqRq+VliwRTC8tsMQfmrWjDMhkPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.1.tgz", + "integrity": "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/oauth4webapi": { + "version": "3.8.8", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.8.tgz", + "integrity": "sha512-8N28E+a/oxfXWBgOMt+ZP/JUf/XR+IFbvkAEPP3gznXOMv9BpAAwiIj0TFNz3tGTPc0ZQ8zmWBNgN1nAys0gng==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/oniguruma-parser": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", + "integrity": "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==", + "dev": true, + "license": "MIT" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz", + "integrity": "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "oniguruma-parser": "^0.12.2", + "regex": "^6.1.0", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/openid-client": { + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.8.2.tgz", + "integrity": "sha512-uOvTCndr4udZsKihJ68H9bUICrriHdUVJ6Az+4Ns6cW55rwM5h0bjVIzDz2SxgOI84LKjFyjOFvERLzdTUROGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jose": "^6.1.3", + "oauth4webapi": "^3.8.4" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/orderedmap": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", + "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", + "dev": true, + "license": "MIT" + }, + "node_modules/own-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.2.tgz", + "integrity": "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-any": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-any/-/p-any-4.0.0.tgz", + "integrity": "sha512-S/B50s+pAVe0wmEZHmBs/9yJXeZ5KhHzOsgKzt0hRdgkoR3DxW9ts46fcsWi/r3VnzsnkKS7q4uimze+zjdryw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-cancelable": "^3.0.0", + "p-some": "^6.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/p-some": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-some/-/p-some-6.0.0.tgz", + "integrity": "sha512-CJbQCKdfSX3fIh8/QKgS+9rjm7OBNUTmwWswAFQAhc8j1NR1dsEDETUEuVUtQHZpV+J03LqWBEwvu0g1Yn+TYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^4.0.0", + "p-cancelable": "^3.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", + "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "dev": true, + "license": "MIT" + }, + "node_modules/parse-latin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", + "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "@types/unist": "^3.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-modify-children": "^4.0.0", + "unist-util-visit-children": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/patch-console": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/patch-console/-/patch-console-2.0.0.tgz", + "integrity": "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-expression-matcher": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.6.2.tgz", + "integrity": "sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "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, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkce-challenge": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", + "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/pony-cause": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pony-cause/-/pony-cause-1.1.1.tgz", + "integrity": "sha512-PxkIc/2ZpLiEzQXu5YRDOUgBlfGYBY8156HY5ZcRAwwonMk5W/MrJP2LLkG/hF7GEQzaHo2aS7ho6ZLCOvf+6g==", + "dev": true, + "license": "0BSD", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", + "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/posthog-node": { + "version": "5.17.2", + "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-5.17.2.tgz", + "integrity": "sha512-lz3YJOr0Nmiz0yHASaINEDHqoV+0bC3eD8aZAG+Ky292dAnVYul+ga/dMX8KCBXg8hHfKdxw0SztYD5j6dgUqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@posthog/core": "1.7.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettier": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/property-information": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/prosemirror-model": { + "version": "1.25.4", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz", + "integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "orderedmap": "^2.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.8.tgz", + "integrity": "sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/public-ip": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/public-ip/-/public-ip-5.0.0.tgz", + "integrity": "sha512-xaH3pZMni/R2BG7ZXXaWS9Wc9wFlhyDVJF47IJ+3ali0TGv+2PsckKxbmo+rnx3ZxiV2wblVhtdS3bohAP6GGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dns-socket": "^4.2.2", + "got": "^12.0.0", + "is-ip": "^3.1.0" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/public-ip/node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.0.tgz", + "integrity": "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "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" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/re2js": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/re2js/-/re2js-2.8.6.tgz", + "integrity": "sha512-xLgQil4kIUCrAzVk9fRSkxkFNwmygLFjVxXrLc65aE1F0+Zsb8rxumFBy4XKyvgMCTL6kilDq3EZ0piE2dP/Dg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/react": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-reconciler": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.32.0.tgz", + "integrity": "sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.2.tgz", + "integrity": "sha512-/peqiBB/n07gQGLsWaHho3WfvUyRscw0gYTsEFMhrIe/nWLkYaf5SbKYjGYqtRV3aPwykJgF2VEMo1ac4bnsGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "dev": true, + "license": "MIT" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rehype-katex": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz", + "integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/katex": "^0.16.0", + "hast-util-from-html-isomorphic": "^2.0.0", + "hast-util-to-text": "^4.0.0", + "katex": "^0.16.0", + "unist-util-visit-parents": "^6.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-minify-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/rehype-minify-whitespace/-/rehype-minify-whitespace-6.0.2.tgz", + "integrity": "sha512-Zk0pyQ06A3Lyxhe9vGtOtzz3Z0+qZ5+7icZ/PL/2x1SHPbKao5oB/g/rlc6BCTajqBb33JcOe71Ye1oFsuYbnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-minify-whitespace": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz", + "integrity": "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-frontmatter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz", + "integrity": "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-frontmatter": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-math": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", + "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-math": "^3.0.0", + "micromark-extension-math": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx-remove-esm": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/remark-mdx-remove-esm/-/remark-mdx-remove-esm-1.3.3.tgz", + "integrity": "sha512-KgGfD4JV3lKse0n/m8UxW4jK6H/9ffkCVxVAJ60aGY4uiPX/+SQCT5/lQcRGcjyQuRLDq2Df2krv6pD/qWJRVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.4", + "unist-util-remove": "^4.0.0" + }, + "peerDependencies": { + "unified": "^11" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.1.tgz", + "integrity": "sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-smartypants": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", + "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", + "dev": true, + "license": "MIT", + "dependencies": { + "retext": "^9.0.0", + "retext-smartypants": "^6.0.0", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "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" + } + }, + "node_modules/reselect": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.3.0.tgz", + "integrity": "sha512-XGoLeRAVzUTcJ1qkxPQhDJyIZ5d6zzZD9nT7AEZOaaU9UbWclhycElmhO+VD5bFeLuzhPBaOV2oXC8uG35ZSpg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/retext": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", + "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "retext-latin": "^4.0.0", + "retext-stringify": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-latin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", + "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "parse-latin": "^7.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-smartypants": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", + "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/router/node_modules/path-to-regexp": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", + "dev": true, + "license": "MIT", + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/rxjs/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-stable-stringify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz", + "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/serialize-error": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-13.0.2.tgz", + "integrity": "sha512-G+YKwp9I6IvWMe5RlwqxdmTPIcq/G8HK/sU51gdV1XAJznYkRSTB0ph+zB9AfSxG0fx6xrqYA6i9HeIcHFTXow==", + "dev": true, + "license": "MIT", + "dependencies": { + "non-error": "^0.1.0", + "type-fest": "^5.4.1" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-error/node_modules/type-fest": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.10.0.tgz", + "integrity": "sha512-NoSdpq/WEiAg5sjmBkmV/hfxv6HJH4NqPNrqjtSO5CwRmpsDfaf4begxW34KdJykH/l1yHtwBWQkCRdoXO8mPA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/sharp": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.5.tgz", + "integrity": "sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.5", + "@img/sharp-darwin-x64": "0.35.5", + "@img/sharp-freebsd-wasm32": "0.35.5", + "@img/sharp-libvips-darwin-arm64": "1.3.4", + "@img/sharp-libvips-darwin-x64": "1.3.4", + "@img/sharp-libvips-linux-arm": "1.3.4", + "@img/sharp-libvips-linux-arm64": "1.3.4", + "@img/sharp-libvips-linux-ppc64": "1.3.4", + "@img/sharp-libvips-linux-riscv64": "1.3.4", + "@img/sharp-libvips-linux-s390x": "1.3.4", + "@img/sharp-libvips-linux-x64": "1.3.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.4", + "@img/sharp-libvips-linuxmusl-x64": "1.3.4", + "@img/sharp-linux-arm": "0.35.5", + "@img/sharp-linux-arm64": "0.35.5", + "@img/sharp-linux-ppc64": "0.35.5", + "@img/sharp-linux-riscv64": "0.35.5", + "@img/sharp-linux-s390x": "0.35.5", + "@img/sharp-linux-x64": "0.35.5", + "@img/sharp-linuxmusl-arm64": "0.35.5", + "@img/sharp-linuxmusl-x64": "0.35.5", + "@img/sharp-webcontainers-wasm32": "0.35.5", + "@img/sharp-win32-arm64": "0.35.5", + "@img/sharp-win32-ia32": "0.35.5", + "@img/sharp-win32-x64": "0.35.5" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/sharp-ico": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/sharp-ico/-/sharp-ico-0.1.5.tgz", + "integrity": "sha512-a3jODQl82NPp1d5OYb0wY+oFaPk7AvyxipIowCHk7pBsZCWgbe0yAkU2OOXdoH0ENyANhyOQbs9xkAiRHcF02Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "decode-ico": "*", + "ico-endec": "*", + "sharp": "*" + } + }, + "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, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shiki": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.23.0.tgz", + "integrity": "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "3.23.0", + "@shikijs/engine-javascript": "3.23.0", + "@shikijs/engine-oniguruma": "3.23.0", + "@shikijs/langs": "3.23.0", + "@shikijs/themes": "3.23.0", + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/socket.io": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", + "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.8.tgz", + "integrity": "sha512-6Oy52pbg+kvdCVvjcN+FnY7BvxZ7cIHNScbvztT/It5d0vbwoJoVZmF2gjJmnV0/4WlXRfG15zc45ySk9Ah8bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "~4.4.1", + "ws": "~8.21.0" + } + }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.7.tgz", + "integrity": "sha512-IH/iSeO9T6gz1KkFleGDWkG9N3dl4jXVYUtMhIqH10Md0ttMer8nUNWiP1DKuNrybD2xBrixLJdCC9J6ECoYkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/standardwebhooks": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.1.1.tgz", + "integrity": "sha512-bCbX9ZEyFkWPsRz7Bl3NuQUJohmwGSev/yhr7vhaGPlc4AfIrspIRa6cPTBuI1ItmrTDJ4d/S2hCsfe4+vQGnQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@stablelib/base64": "^1.0.0", + "fast-sha256": "^1.3.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "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/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strnum": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.4.2.tgz", + "integrity": "sha512-rDG3Ah4TV0k1hWvLSzkZtMmLN9+eS+h3knq4MP6A42Y3Yh5qGNnOUs1jJkoSr8FG5dsL28c7KgkIBzSEykqtuw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "anynum": "^1.0.1" + } + }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-js/node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "dev": true, + "license": "MIT" + }, + "node_modules/style-to-js/node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, + "node_modules/style-to-object": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", + "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.1.1" + } + }, + "node_modules/sucrase": { + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", + "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tailwindcss-v3": { + "name": "tailwindcss", + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss-v3/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/tailwindcss-v3/node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tailwindcss-v3/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/tailwindcss-v3/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tailwindcss-v3/node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/tar": { + "version": "7.5.21", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.21.tgz", + "integrity": "sha512-XdhtCvlMywwxpCW8YEq3lOXBJpUPTR2OHHcwLPO3HwsJqOHa2Ok/oJ7ruGzp+JrKoRPVCzJwAdEjqLW/vNRPHA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar-fs": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz", + "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-data-view": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/to-data-view/-/to-data-view-1.1.0.tgz", + "integrity": "sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==", + "dev": true, + "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", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "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" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trim-trailing-lines": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-2.1.0.tgz", + "integrity": "sha512-5UR5Biq4VlVOtzqkm2AZlgvSlDJtME46uV0br0gENbwN4l5+mMKT4b9gJKqWtuL2zAIqajGJGuvbCbcAJUZqBg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/twoslash": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/twoslash/-/twoslash-0.3.9.tgz", + "integrity": "sha512-rDclk+OtzuTX+tnea7DYLCkqGQ3eP0IyfD+kzUJ7t46X/NzlaxwrhecmEBNuSCuEn3V+n1PhcjUUQQ7gUJzX5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript/vfs": "^1.6.4", + "twoslash-protocol": "0.3.9" + }, + "peerDependencies": { + "typescript": "^5.5.0 || ^6.0.0" + } + }, + "node_modules/twoslash-protocol": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/twoslash-protocol/-/twoslash-protocol-0.3.9.tgz", + "integrity": "sha512-9/iwp+CXOnjFMPQuPL5PkuRbZnDoNpBvtJCLs9t8kDYkL3YHujbvnHfZA1i5fApDftVEdBw+T/4F+dH5kIzpYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.5.tgz", + "integrity": "sha512-0FHJvLPqZ7KJzp17O13jfsAjsqazgrxBu2zEK95PmUz8lv2+GjRuxUInCr2Rk9Dms3ihN21zJ929ZO43yJ95QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz", + "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==", + "dev": true, + "license": "MIT" + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-builder": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-4.0.0.tgz", + "integrity": "sha512-wmRFnH+BLpZnTKpc5L7O67Kac89s9HMrtELpnNaE6TAobq5DTZZs5YaTQfAZBA9bFPECx2uVAPO31c+GVug8mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-map/-/unist-util-map-4.0.0.tgz", + "integrity": "sha512-HJs1tpkSmRJUzj6fskQrS5oYhBYlmtcvy4SepdDEEsL04FjBrgF0Mgggvxc1/qGBGgW7hRh9+UBK1aqTEnBpIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-modify-children": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", + "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "array-iterate": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-4.0.0.tgz", + "integrity": "sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-children": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", + "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/urijs": { + "version": "1.19.11", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", + "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/use-sync-external-store": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.7.0.tgz", + "integrity": "sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/valibot": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.5.0.tgz", + "integrity": "sha512-nil6AkP2TChWL43Z5uJ6GTxX01CUA+g8LWUM+N/rB9NBbkUMaUsi9PUNzlUPgoKASgmx9f7eGOYpJ04/fSa6FQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-matter": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vfile-matter/-/vfile-matter-5.0.1.tgz", + "integrity": "sha512-o6roP82AiX0XfkyTHyRCMXgHfltUNlXSEqCIS80f+mbAyiQBE2fxtDVMtseyytGx75sihiJFo/zR6r/4LTs2Cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "vfile": "^6.0.0", + "yaml": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "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, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.24", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.24.tgz", + "integrity": "sha512-wk4Mf4pR5mRP7eYuuTBCIQ9d0ud2Fv2jRLQpfgnRjbOxAFHmjKFValgTpitVKzJJS8ajnYQV2Du1SZ8j6b/EUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/widest-line": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/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/node_modules/ansi-styles": { + "version": "4.3.0", + "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" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/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/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "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" + } + }, + "node_modules/wrap-ansi/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/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/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz", + "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-naming": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.3.0.tgz", + "integrity": "sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xss": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.15.tgz", + "integrity": "sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^2.20.3", + "cssfilter": "0.0.10" + }, + "bin": { + "xss": "bin/xss" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/xss/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, + "license": "MIT" + }, + "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": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "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" + } + }, + "node_modules/yargs/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/yargs/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/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "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" + } + }, + "node_modules/yargs/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/yargs/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/yoctocolors-cjs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoga-layout": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz", + "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.25.2", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", + "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", + "dev": true, + "license": "ISC", + "optional": true, + "peerDependencies": { + "zod": "^3.25.28 || ^4" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 00000000..a0e6e698 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,31 @@ +{ + "name": "opengeometry-docs", + "private": true, + "type": "module", + "engines": { + "node": ">=22.6.0" + }, + "scripts": { + "dev": "mint dev --no-open", + "validate": "mint validate", + "links": "mint broken-links --check-anchors", + "format:check": "prettier --check . ../.github/workflows/docs.yml", + "format": "prettier --write . ../.github/workflows/docs.yml", + "index": "node scripts/build-index.mjs", + "index:check": "node scripts/build-index.mjs --check", + "check": "npm run format:check && npm run index:check && npm run validate && npm run links" + }, + "devDependencies": { + "front-matter": "4.0.2", + "mint": "4.2.981", + "prettier": "3.8.3" + }, + "overrides": { + "adm-zip": "^0.6.1", + "axios": "^1.20.0", + "fflate": "^0.8.3", + "js-yaml@^4": "^4.3.2", + "qs": "^6.16.0", + "sharp": "^0.35.5" + } +} diff --git a/docs/quickstart.mdx b/docs/quickstart.mdx deleted file mode 100644 index 88d1797b..00000000 --- a/docs/quickstart.mdx +++ /dev/null @@ -1,340 +0,0 @@ ---- -title: Quickstart -description: Create your first 3D shape with OpenGeometry in minutes ---- - -This guide walks through a minimal OpenGeometry + Three.js setup for browser-based CAD, AEC/BIM, and other geometry-heavy web tools. - -## Prerequisites - -Make sure you have completed the [installation](/installation) steps and have both OpenGeometry and Three.js installed. - -## Basic Setup - -Let's create a complete example that renders a 3D cuboid in the browser. - - - - - -First, set up a basic HTML page with a container for your 3D scene: - -```html - - - - - - OpenGeometry Quickstart - - - -
- - - -``` - -
- - - -Create a `main.ts` file and set up a basic Three.js scene: - -```typescript -import * as THREE from 'three'; -import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; -import { OpenGeometry, Cuboid, Vector3 } from 'opengeometry'; - -// Get the app container -const app = document.getElementById('app'); -if (!app) throw new Error('Missing #app container'); - -// Create scene -const scene = new THREE.Scene(); -scene.background = new THREE.Color(0xf3f4f6); - -// Create camera -const camera = new THREE.PerspectiveCamera( - 55, - window.innerWidth / window.innerHeight, - 0.1, - 1000 -); -camera.position.set(5, 4, 6); - -// Create renderer -const renderer = new THREE.WebGLRenderer({ antialias: true }); -renderer.setSize(window.innerWidth, window.innerHeight); -renderer.setPixelRatio(window.devicePixelRatio); -app.appendChild(renderer.domElement); - -// Add orbit controls -const controls = new OrbitControls(camera, renderer.domElement); -controls.enableDamping = true; -controls.target.set(0, 0.8, 0); -controls.update(); - -// Add grid helper -scene.add(new THREE.GridHelper(20, 20, 0x9ca3af, 0xd1d5db)); - -// Add lights -const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); -scene.add(ambientLight); - -const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); -directionalLight.position.set(5, 8, 3); -scene.add(directionalLight); -``` - - - - - -Initialize the OpenGeometry WASM module once before creating shapes: - -```typescript -// Initialize OpenGeometry -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); -``` - - - Call `OpenGeometry.create(...)` before constructing `Vector3` or any wrapper. - - - - With Vite, copy `node_modules/opengeometry/opengeometry_bg.wasm` to `public/opengeometry_bg.wasm` - so it is served at `/opengeometry_bg.wasm`. - - - - - - -Now create a cuboid and add it to the scene: - -```typescript -// Create a cuboid -const cuboid = new Cuboid({ - center: new Vector3(0, 0.8, 0), - width: 1.5, - height: 1.6, - depth: 1.2, - color: 0x10b981, -}); - -// Enable outline rendering -cuboid.outline = true; - -// Add to scene -scene.add(cuboid); -``` - - - `Cuboid` is a `THREE.Group` containing a transient surface mesh and analytic feature outline, so - it can be added directly to Three.js scenes. Primitive wrappers such as `Line` and `Arc` are - line-based. - - - - - - -Finally, create the render loop: - -```typescript -// Animation loop -function animate() { - requestAnimationFrame(animate); - controls.update(); - renderer.render(scene, camera); -} - -animate(); - -// Handle window resize -window.addEventListener('resize', () => { - camera.aspect = window.innerWidth / window.innerHeight; - camera.updateProjectionMatrix(); - renderer.setSize(window.innerWidth, window.innerHeight); -}); -``` - - - -
- -## Complete Example - -Here's the complete `main.ts` file: - -```typescript -import * as THREE from 'three'; -import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; -import { OpenGeometry, Cuboid, Vector3 } from 'opengeometry'; - -const app = document.getElementById('app'); -if (!app) throw new Error('Missing #app container'); - -const scene = new THREE.Scene(); -scene.background = new THREE.Color(0xf3f4f6); - -const camera = new THREE.PerspectiveCamera( - 55, - window.innerWidth / window.innerHeight, - 0.1, - 1000 -); -camera.position.set(5, 4, 6); - -const renderer = new THREE.WebGLRenderer({ antialias: true }); -renderer.setSize(window.innerWidth, window.innerHeight); -renderer.setPixelRatio(window.devicePixelRatio); -app.appendChild(renderer.domElement); - -const controls = new OrbitControls(camera, renderer.domElement); -controls.enableDamping = true; -controls.target.set(0, 0.8, 0); -controls.update(); - -scene.add(new THREE.GridHelper(20, 20, 0x9ca3af, 0xd1d5db)); - -const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); -scene.add(ambientLight); - -const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); -directionalLight.position.set(5, 8, 3); -scene.add(directionalLight); - -// Initialize OpenGeometry -await OpenGeometry.create({ wasmURL: "/opengeometry_bg.wasm" }); - -// Create a cuboid -const cuboid = new Cuboid({ - center: new Vector3(0, 0.8, 0), - width: 1.5, - height: 1.6, - depth: 1.2, - color: 0x10b981, -}); -cuboid.outline = true; -scene.add(cuboid); - -// Animation loop -function animate() { - requestAnimationFrame(animate); - controls.update(); - renderer.render(scene, camera); -} - -animate(); - -// Handle window resize -window.addEventListener('resize', () => { - camera.aspect = window.innerWidth / window.innerHeight; - camera.updateProjectionMatrix(); - renderer.setSize(window.innerWidth, window.innerHeight); -}); -``` - -## Try Other Shapes - -OpenGeometry provides many built-in shapes for browser CAD and AEC/BIM workflows. The snippets -below assume you have already initialized `OpenGeometry`. - -### Cylinder Example - -```typescript -import { Cylinder, Vector3 } from 'opengeometry'; - -const cylinder = new Cylinder({ - center: new Vector3(0, 0.8, 0), - radius: 0.6, - height: 1.6, - deflection: 0.01, - color: 0xf97316, -}); -cylinder.outline = true; -scene.add(cylinder); -``` - -### Sphere Example - -```typescript -import { Sphere, Vector3 } from 'opengeometry'; - -const sphere = new Sphere({ - center: new Vector3(0, 1.0, 0), - radius: 0.9, - deflection: 0.01, - color: 0x0ea5e9, -}); -sphere.outline = true; -scene.add(sphere); -``` - -### 2D Primitives - -You can also create 2D primitives like lines, arcs, and curves: - -```typescript -import { Line, Arc, Polyline, Vector3 } from 'opengeometry'; - -// Line -const line = new Line({ - start: new Vector3(-2, 0, 0), - end: new Vector3(2, 0, 0), - color: 0x111827, -}); -scene.add(line); - -// Arc -const arc = new Arc({ - center: new Vector3(0, 0, 0), - radius: 1.0, - startAngle: 0, - sweepAngle: Math.PI * 1.5, - deflection: 0.01, - color: 0xb91c1c, -}); -scene.add(arc); - -// Polyline -const polyline = new Polyline({ - points: [ - new Vector3(-1, 0, 0), - new Vector3(0, 0, 1), - new Vector3(1, 0, 0), - ], - color: 0x0284c7, -}); -scene.add(polyline); -``` - -## Next Steps - - - - Explore the complete API documentation for all shapes and operations - - - See interactive examples showcasing all features - - - - - For more complete reference examples, use the standalone demo catalog at - [demo.opengeometry.io](https://demo.opengeometry.io/) or browse the example guide at - [Examples](/integration/examples). - diff --git a/docs/scripts/build-index.mjs b/docs/scripts/build-index.mjs new file mode 100644 index 00000000..b335bc00 --- /dev/null +++ b/docs/scripts/build-index.mjs @@ -0,0 +1,130 @@ +import { readFileSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import frontMatter from 'front-matter'; + +const DOCS = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const SDK = path.resolve(DOCS, '../main/opengeometry-three'); +const SITE = 'https://docs.opengeometry.io'; +const CHECK = process.argv.includes('--check'); + +const PAGES = { + OpenGeometry: 'opengeometry/api/opengeometry', + OGMark: 'opengeometry/api/og-mark', + HostGroup: 'opengeometry/api/display', + SystemAssembly: 'opengeometry/api/system-assembly', + Wire: 'opengeometry/api/wire', + Solid: 'opengeometry/api/solid', + Sheet: 'opengeometry/api/sheet', + BodyEventMap: 'opengeometry/api/body', + PointClassification: 'opengeometry/api/body', + Measure: 'opengeometry/api/body', + Validity: 'opengeometry/api/body', + MirrorPlane: 'opengeometry/api/body', + OGError: 'opengeometry/api/og-error', + ErrorDetails: 'opengeometry/api/og-error', + OperateErrorDetails: 'opengeometry/api/og-error', + AnalyticExchangeBodyV2: 'opengeometry/api/export', + IfcPreparedValue: 'opengeometry/api/export', + OffsetRegion: 'opengeometry/api/regions', + CurvedRegion2D: 'opengeometry/api/regions', + CurvedRegionEdge: 'opengeometry/api/regions', + OffsetHole: 'opengeometry/api/offsets', + OffsetPath2D: 'opengeometry/api/offsets', + OffsetPolylineOptions: 'opengeometry/api/offsets', +}; +const CONSTANTS_PAGE = 'opengeometry/api/constants'; +const PARAMS_TYPE = /^(Profile\w*|\w+Params)$/; + +function names(list) { + return list + .split(',') + .map((name) => name.trim().replace(/^type\s+/, '')) + .filter(Boolean); +} + +function moduleExports(file, kind = 'value') { + const text = readFileSync(file, 'utf8'); + const found = []; + for (const [, typeOnly, list] of text.matchAll(/export\s+(type\s+)?\{([^}]*)\}\s+from/g)) { + for (const name of names(list)) found.push({ export: name, kind: typeOnly ? 'type' : kind }); + } + for (const [, from] of text.matchAll(/export\s+\*\s+from\s+'([^']+)'/g)) { + const target = path.resolve(path.dirname(file), from); + found.push(...moduleExports(target.endsWith('.ts') ? target : `${target}.ts`, kind)); + } + for (const [, name] of text.matchAll(/export\s+const\s+(\w+)/g)) + found.push({ export: name, kind: 'value' }); + return found; +} + +function navigationPages(node, trail = []) { + if (typeof node === 'string') return [{ page: node, trail }]; + if (Array.isArray(node)) return node.flatMap((item) => navigationPages(item, trail)); + const label = node.tab ?? node.group; + const next = label ? [...trail, label] : trail; + return [node.pages, node.groups, node.tabs] + .filter(Boolean) + .flatMap((child) => navigationPages(child, next)); +} + +function pageText(page) { + return readFileSync(path.join(DOCS, `${page}.mdx`), 'utf8'); +} + +const problems = []; +const coverage = moduleExports(path.join(SDK, 'index.ts')).map((entry) => { + const constant = entry.export.startsWith('OG_') || PARAMS_TYPE.test(entry.export); + const page = PAGES[entry.export] ?? (constant ? CONSTANTS_PAGE : undefined); + if (!page) problems.push(`${entry.export} has no API page`); + else if (!new RegExp(`\\b${entry.export}\\b`).test(pageText(page))) + problems.push(`${entry.export} is not named on ${page}`); + return { ...entry, page }; +}); +for (const name of Object.keys(PAGES)) { + if (!coverage.some((entry) => entry.export === name)) + problems.push(`${name} is mapped but not exported`); +} + +const docs = JSON.parse(readFileSync(path.join(DOCS, 'docs.json'), 'utf8')); +const pages = navigationPages(docs.navigation.tabs); +const sections = new Map(); +for (const { page, trail } of pages) { + const { attributes } = frontMatter(pageText(page)); + if (!attributes.title || !attributes.description) + problems.push(`${page} needs a title and a description`); + const section = trail.filter((label) => label !== 'Documentation').join(' / ') || 'Documentation'; + if (!sections.has(section)) sections.set(section, []); + sections + .get(section) + .push(`- [${attributes.title}](${SITE}/${page}.md): ${attributes.description}`); +} + +const llms = [ + `# ${docs.name}`, + '', + `> ${docs.description}`, + '', + 'Package: `opengeometry` on npm. These docs describe version 3.0. Check `node_modules/opengeometry/package.json` and `index.d.ts` before you use an example.', + '', + 'Points and vectors are `[x, y, z]` arrays, units are metres and Y is up. Await `OpenGeometry.create` once before the first body. Code that uses `Cuboid`, `Vector3` or `setPlacement` is written for 2.0 and does not work with 3.0.', + '', + ...[...sections].flatMap(([section, lines]) => [`## ${section}`, '', ...lines, '']), +].join('\n'); + +const outputs = { + 'api-coverage.json': `${JSON.stringify(coverage, null, 2)}\n`, + 'llms.txt': llms, +}; + +for (const [name, text] of Object.entries(outputs)) { + const file = path.join(DOCS, name); + if (!CHECK) writeFileSync(file, text); + else if (readFileSync(file, 'utf8') !== text) + problems.push(`${name} is stale: run npm run index`); +} + +if (problems.length > 0) { + console.error(problems.join('\n')); + process.exitCode = 1; +} diff --git a/docs/style.css b/docs/style.css new file mode 100644 index 00000000..68d3cf5f --- /dev/null +++ b/docs/style.css @@ -0,0 +1,58 @@ +.sidebar-group:has(> li[id='/opengeometry/changelog']) { + --og-tree-line-color: #e5e5e5; + --og-tree-line-radius: 0.625rem; +} + +.dark .sidebar-group:has(> li[id='/opengeometry/changelog']) { + --og-tree-line-color: rgba(255, 255, 255, 0.1); +} + +.sidebar-group:has(> li[id='/opengeometry/changelog']) li { + position: relative; + --og-tree-line-start: 0.5rem; + --og-tree-line-length: 0.5rem; +} + +.sidebar-group:has(> li[id='/opengeometry/changelog']) ul { + margin-inline-start: 1.25rem; +} + +.sidebar-group:has(> li[id='/opengeometry/changelog']) > li > ul { + margin-inline-start: 1.5rem; +} + +.sidebar-group:has(> li[id='/opengeometry/changelog']) ul > li { + --og-tree-line-start: 0; + --og-tree-line-length: 0.75rem; +} + +.sidebar-group:has(> li[id='/opengeometry/changelog']) ul > li > :is(a, button) { + padding-inline-start: 0.75rem !important; +} + +.sidebar-group:has(> li[id='/opengeometry/changelog']) li::before, +.sidebar-group:has(> li[id='/opengeometry/changelog']) li::after { + content: ''; + position: absolute; + pointer-events: none; + inset-inline-start: var(--og-tree-line-start); +} + +.sidebar-group:has(> li[id='/opengeometry/changelog']) li::before { + inset-block: -1px; + border-inline-start: 1px solid var(--og-tree-line-color); +} + +.sidebar-group:has(> li[id='/opengeometry/changelog']) li::after { + box-sizing: border-box; + inset-block-start: -1px; + block-size: calc(0.375rem + 0.5lh + 2px); + inline-size: var(--og-tree-line-length); + border-inline-start: 1px solid var(--og-tree-line-color); + border-block-end: 1px solid var(--og-tree-line-color); + border-end-start-radius: var(--og-tree-line-radius); +} + +.sidebar-group:has(> li[id='/opengeometry/changelog']) li:last-child::before { + content: none; +} diff --git a/docs/what-is-opengeometry.mdx b/docs/what-is-opengeometry.mdx deleted file mode 100644 index c8f450c6..00000000 --- a/docs/what-is-opengeometry.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: OpenGeometry -description: A CAD kernel for the web built with Rust, WebAssembly, and Three.js for browser CAD and AEC/BIM workflows ---- - -## What is OpenGeometry? - -OpenGeometry is a CAD kernel for the web that provides 2D and 3D geometric primitives and CAD operations via WebAssembly. Written in Rust and compiled to WASM, it delivers near-native performance for complex geometric computations directly in the browser. - -OpenGeometry makes it easy to build sophisticated CAD applications, browser-based AEC/BIM tools, 3D modeling workflows, architectural visualization software, and interactive geometry editors for the web. - -OpenGeometry works with Three.js with plans to support other 3D libraries as well. - -Floorkit is a dedicated toolkit/application for architects and interior designers that is built on top of OpenGeometry. It is a downstream AEC workflow layer, while OpenGeometry is the core engine. - - -Check out [Floorkit](https://ploterr.com/floorkit) for more information. - - -## Why OpenGeometry? - -Building CAD applications for the web has traditionally required complex server-side processing or compromising on performance. OpenGeometry changes that: - -- **High Performance**: Rust-compiled WASM delivers near-native speed for geometric operations -- **Browser-Native**: No server required - all computation happens client-side -- **Three.js Integration**: Drop-in components that work seamlessly with Three.js scenes -- **Type-Safe**: Full TypeScript support with complete type definitions -- **Production-Ready**: Robust triangulation, extrusion, offset, and Boolean operations - -## Key Features - - - The snippets below assume you import from `opengeometry` and call - `await OpenGeometry.create({ wasmURL })` before any `new Vector3(...)` or wrapper construction. - - -### 2D & 3D Primitives - -Create lines, polylines, arcs, curves, and rectangles with simple, intuitive APIs: - -```typescript -const line = new Line({ - start: new Vector3(-3.0, 0.0, -2.0), - end: new Vector3(-1.0, 0.0, -1.0), - color: 0x111827, -}); -``` - -### Parametric Shapes - -Build complex 3D shapes including cuboids, cylinders, spheres, wedges, and polygons: - -```typescript -const cuboid = new Cuboid({ - center: new Vector3(0.0, 0.8, -1.2), - width: 1.2, - height: 1.6, - depth: 1.0, - color: 0x10b981, -}); -cuboid.outline = true; -``` - -### Advanced Operations - -- **Triangulation**: Robust polygon triangulation with hole support -- **Extrusion**: Convert 2D profiles into 3D solids -- **Sweep**: Create complex shapes by sweeping profiles along paths -- **Offset**: Generate offset curves and surfaces -- **Boolean Operations**: Union, intersection, and subtraction (experimental) - -### BREP Data Access - -Access boundary representation data for advanced CAD workflows: - -```typescript -const brepData = cuboid.getBrepData(); -``` - - - Want to suggest a primitive or shape? Create an issue on our [GitHub repository](https://github.com/OpenGeometry-io/OpenGeometry). - - -## What Can You Build? - -OpenGeometry enables a wide range of web-based 3D applications: - -- **Architectural Design Tools**: Floor plan editors, building configurators, space planning applications -- **Engineering CAD**: Mechanical design tools, assembly visualizers, technical drawing generators -- **Creative Tools**: 3D modeling applications, procedural geometry generators, parametric design systems -- **Product Configurators**: Interactive 3D product customization for e-commerce - -## Get Started - - - - Install OpenGeometry and set up your development environment - - - Create your first 3D shape in minutes - - - Explore the complete API documentation - - - See live interactive examples and demos - - - -## Open Source - -OpenGeometry is open source and actively developed. Visit the [GitHub repository](https://github.com/OpenGeometry-io/OpenGeometry) to contribute, report issues, or explore the source code. - - - OpenGeometry is under active development. Expect frequent updates and new features. The API may change as the project evolves. - diff --git a/main/opengeometry-three/examples-vite/boolean.html b/main/opengeometry-three/examples-vite/boolean.html index ddc9015a..55e01f66 100644 --- a/main/opengeometry-three/examples-vite/boolean.html +++ b/main/opengeometry-three/examples-vite/boolean.html @@ -21,7 +21,6 @@

Solid Boolean

The source solids are on the left and the exact kernel result is on the right. - This 2.5 example uses two cuboids because sphere primitives are planned for a later milestone.