diff --git a/CHANGES.md b/CHANGES.md index f423ab399..9c7eb4851 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,12 +7,19 @@ - Added `offset` getter to `AccessorView`. - Added `stride`, `offset`, and `data` getters to `AccessorWriter`. - Added `value_type` typedef to `AccessorWriter`. +- Added `InstanceAttributeSemantics` to `CesiumGltf`. +- Added `VertexAttributeSemantics::FEATURE_ID_n`. +- Added a `const` version of `Tileset::forEachLoadedTile`. +- Added `DebugTileStateDatabase`, which provides tools for debugging the tile selection algorithm using SQLite. +- Added `CesiumAsync::SqliteHelper`, containing functions for working with SQLite. - Updates generated classes for `EXT_structural_metadata`. See https://github.com/CesiumGS/glTF/pull/71. ##### Fixes :wrench: - Fixed a bug in `thenPassThrough` that caused a compiler error when given a value by r-value refrence. +- Fixed a raster overlay bug that could cause unnecessary upsampling with failed or missing overlay tiles. - Fixed a bug in `SubtreeFileReader::loadBinary` that prevented valid subtrees from loading if they did not contain binary data. +- Fixed a bug in the `Tileset` selection algorithm that could cause detail to disappear during load in some cases. ### v0.42.0 - 2024-12-02 @@ -1116,4 +1123,4 @@ In addition to the above, this release updates the following third-party librari ### v0.1.0 - 2021-03-30 -- Initial release. +- Initial release. \ No newline at end of file diff --git a/CMakeGraphVizOptions.cmake b/CMakeGraphVizOptions.cmake new file mode 100644 index 000000000..50b68689e --- /dev/null +++ b/CMakeGraphVizOptions.cmake @@ -0,0 +1,7 @@ +set(GRAPHVIZ_GENERATE_PER_TARGET FALSE) +set(GRAPHVIZ_GENERATE_DEPENDERS FALSE) +set(GRAPHVIZ_OBJECT_LIBS FALSE) +list(APPEND GRAPHVIZ_IGNORE_TARGETS cesium-native-tests) +list(APPEND GRAPHVIZ_IGNORE_TARGETS "Catch2::*") +list(APPEND GRAPHVIZ_IGNORE_TARGETS "lib*.lib") +list(APPEND GRAPHVIZ_IGNORE_TARGETS "lib*.so") \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..b0c37370b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,75 @@ +# Contribution Guide {#contributing} + + + +## Table of Contents + +- [📬Submitting an Issue](#submitting-an-issue) +- [📝Opening a Pull Request](#opening-a-pull-request) + - [Contributor License Agreement (CLA)](#contributor-license-agreement-cla) + - [Pull Request Guidelines](#pull-request-guidelines) +- [⚖️Code of Conduct](#️code-of-conduct) + + + +Community involvement in Cesium Native has been and continues to be a key part of its development. Contributing to Cesium Native can take many forms: + + +- Making a pull request to add features or fix issues. +- Submitting an issue to report a bug. +- Triaging existing issues. This can include attempting to reproduce issues or sharing additional information you have. +- Being active on the [Cesium community forum](https://community.cesium.com/) by answering questions and providing input on Cesium's direction. +- Writing tutorials, creating examples, and improving the reference documentation. +- Sharing projects you've made with Cesium Native with us through the [Cesium community forum](https://community.cesium.com/) or at hello@cesium.com. + +More details about writing issues and pull requests is detailed below. For any other guidance you need, don't hesitate to ask on the [Cesium community forum](https://community.cesium.com/)! + +## 📬Submitting an Issue + +If you have a question, please do not submit an issue; instead, search the [Cesium community forum](https://community.cesium.com/). The forum is very active and there are years of informative archives, often with answers from the core Cesium team. If you do not find an answer to your question, start a new thread and you'll likely get a quick response! + +If you think you've found a bug in Cesium Native, first search the [issues](https://github.com/CesiumGS/cesium-native/issues). If an issue already exists, please add a comment expressing your interest and any additional information. This helps us prioritize issues. + +If a related issue does not exist, submit a new one. Please be concise and include as much of the following information as is relevant: + +- Minimum amount of sample code (and data). +- Screenshot or animated .gif if appropriate (try [LICEcap](http://www.cockos.com/licecap/)). For example, see [#803](https://github.com/CesiumGS/cesium-native/issues/803). Screenshots are particularly useful for exceptions and rendering artifacts. +- Link to the thread if this was discussed on the Cesium forum or elsewhere. For example, see [#878](https://github.com/CesiumGS/cesium-native/issues/878). +- Your operating system and version, compiler and version, and video card. If you're using Cesium Native with an engine like Unreal or Unity, please include this information as well. Are they all up-to-date? Is the issue specific to one of them? +- The version of Cesium Native. Did this work in a previous version? +- Ideas for how to fix or workaround the issue. Also mention if you are willing to help fix it. If so, the Cesium team can often provide guidance and the issue may get fixed more quickly with your help. + +## 📝Opening a Pull Request + +Pull requests are a huge help in the development of Cesium Native. Following the tips in this guide will help your pull request get merged quickly. + +> If you plan to make a major change, please start a new thread on the [Cesium community forum](https://community.cesium.com/) first. Pull requests for small features and bug fixes can generally just be opened without discussion on the forum. + +### Contributor License Agreement (CLA) + +Before we can review a pull request, we require a signed Contributor License Agreement. There is a CLA for: + +- [individuals](https://docs.google.com/forms/d/e/1FAIpQLScU-yvQdcdjCFHkNXwdNeEXx5Qhu45QXuWX_uF5qiLGFSEwlA/viewform) and +- [corporations](https://docs.google.com/forms/d/e/1FAIpQLSeYEaWlBl1tQEiegfHMuqnH9VxyfgXGyIw13C2sN7Fj3J3GVA/viewform). + +This only needs to be completed once, and enables contributions to all of the projects under the [CesiumGS](https://github.com/CesiumGS) organization, including Cesium Native. The CLA ensures you retain copyright to your contributions, and provides us the right to use, modify, and redistribute your contributions using the [Apache 2.0 License](LICENSE.md). + +If you have any questions, feel free to reach out to hello@cesium.com! + +### Pull Request Guidelines + +Our code is our lifeblood so maintaining Cesium Native's high code quality is important to us. +- For an overview of our workflow see [github pull request workflows](https://cesium.com/blog/2013/10/08/github-pull-request-workflows/). +- Pull request tips + - If your pull request fixes an existing issue, include a link to the issue in the description (like this: "Fixes [#1](https://github.com/CesiumGS/cesium-native/issues/1)"). Likewise, if your pull request fixes an issue reported on the Cesium forum, include a link to the thread. + - If your pull request needs additional work, include a [task list](https://github.com/blog/1375%0A-task-lists-in-gfm-issues-pulls-comments). + - Once you are done making new commits to address feedback, add a comment to the pull request such as `"this is ready"`. +- Code and tests + - Review the [C++ Style Guide](doc/topics/style-guide.md). These guidelines help us write consistent, performant, less buggy code and improve our productivity by standardizing the decisions we make across the codebase. + - Verify that all tests pass, and write new tests with excellent code coverage for new code. Tests can be built and run using the `cesium-native-tests` target. + - Update [CHANGES.md](CHANGES.md) with a brief description of your changes. + - If you plan to add a third-party library, start a [GitHub issue](https://github.com/CesiumGS/cesium/issues/new) discussing it first. + +## ⚖️Code of Conduct + +To ensure an inclusive community, contributors and users in the Cesium community should follow the [code of conduct](https://github.com/CesiumGS/cesium/blob/main/CODE_OF_CONDUCT.md). \ No newline at end of file diff --git a/Cesium3DTiles/include/Cesium3DTiles/Library.h b/Cesium3DTiles/include/Cesium3DTiles/Library.h index b68e1a484..11d4a24d5 100644 --- a/Cesium3DTiles/include/Cesium3DTiles/Library.h +++ b/Cesium3DTiles/include/Cesium3DTiles/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes for using [3D Tiles](https://github.com/CesiumGS/3d-tiles). + * + * @mermaid-interactive{dependencies/Cesium3DTiles} */ namespace Cesium3DTiles {} diff --git a/Cesium3DTilesContent/include/Cesium3DTilesContent/Library.h b/Cesium3DTilesContent/include/Cesium3DTilesContent/Library.h index 26f187703..6ebc79126 100644 --- a/Cesium3DTilesContent/include/Cesium3DTilesContent/Library.h +++ b/Cesium3DTilesContent/include/Cesium3DTilesContent/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes that support loading and converting 3D Tiles tile content. + * + * @mermaid-interactive{dependencies/Cesium3DTilesContent} */ namespace Cesium3DTilesContent {} diff --git a/Cesium3DTilesReader/include/Cesium3DTilesReader/Library.h b/Cesium3DTilesReader/include/Cesium3DTilesReader/Library.h index 8dc93b668..d42b9ce78 100644 --- a/Cesium3DTilesReader/include/Cesium3DTilesReader/Library.h +++ b/Cesium3DTilesReader/include/Cesium3DTilesReader/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes for reading [3D Tiles](https://github.com/CesiumGS/3d-tiles). + * + * @mermaid-interactive{dependencies/Cesium3DTilesReader} */ namespace Cesium3DTilesReader {} diff --git a/Cesium3DTilesReader/src/SubtreeFileReader.cpp b/Cesium3DTilesReader/src/SubtreeFileReader.cpp index 4ec1c59c6..f023a956a 100644 --- a/Cesium3DTilesReader/src/SubtreeFileReader.cpp +++ b/Cesium3DTilesReader/src/SubtreeFileReader.cpp @@ -19,6 +19,7 @@ SubtreeFileReader::getOptions() const { return this->_reader.getOptions(); } +//! [async-system-store-in-lambda] Future> SubtreeFileReader::load( const AsyncSystem& asyncSystem, const std::shared_ptr& pAssetAccessor, @@ -30,6 +31,7 @@ Future> SubtreeFileReader::load( return this->load(asyncSystem, pAssetAccessor, pRequest); }); } +//! [async-system-store-in-lambda] Future> SubtreeFileReader::load( const AsyncSystem& asyncSystem, diff --git a/Cesium3DTilesSelection/include/Cesium3DTilesSelection/DebugTileStateDatabase.h b/Cesium3DTilesSelection/include/Cesium3DTilesSelection/DebugTileStateDatabase.h new file mode 100644 index 000000000..d6cd68905 --- /dev/null +++ b/Cesium3DTilesSelection/include/Cesium3DTilesSelection/DebugTileStateDatabase.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +namespace Cesium3DTilesSelection { + +class Tile; +class Tileset; + +/** + * @brief Helps debug the tile selection algorithm by recording the state of + * tiles each frame to a SQLite database. + */ +class DebugTileStateDatabase { +public: + /** + * @brief Creates a new instance. + * + * @param databaseFilename The full path and filename of the output SQLite + * database. + */ + DebugTileStateDatabase(const std::string& databaseFilename); + ~DebugTileStateDatabase() noexcept; + + /** + * @brief Records the state of all tiles that are currently loaded by the + * given tileset. + * + * @param frameNumber The current frame number. + * @param tileset The tileset. + */ + void recordAllTileStates(int32_t frameNumber, const Tileset& tileset); + + /** + * @brief Records the state of a given tile. + * + * @param frameNumber The current frame number. + * @param tile The tile. + */ + void recordTileState(int32_t frameNumber, const Tile& tile); + +private: + struct Impl; + std::unique_ptr _pImpl; +}; + +} // namespace Cesium3DTilesSelection diff --git a/Cesium3DTilesSelection/include/Cesium3DTilesSelection/Library.h b/Cesium3DTilesSelection/include/Cesium3DTilesSelection/Library.h index 7383da319..fd663fba0 100644 --- a/Cesium3DTilesSelection/include/Cesium3DTilesSelection/Library.h +++ b/Cesium3DTilesSelection/include/Cesium3DTilesSelection/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes that implement the 3D Tiles standard + * + * @mermaid-interactive{dependencies/Cesium3DTilesSelection} */ namespace Cesium3DTilesSelection {} diff --git a/Cesium3DTilesSelection/include/Cesium3DTilesSelection/TileOcclusionRendererProxy.h b/Cesium3DTilesSelection/include/Cesium3DTilesSelection/TileOcclusionRendererProxy.h index 2b48d8801..b3f47b5fb 100644 --- a/Cesium3DTilesSelection/include/Cesium3DTilesSelection/TileOcclusionRendererProxy.h +++ b/Cesium3DTilesSelection/include/Cesium3DTilesSelection/TileOcclusionRendererProxy.h @@ -7,12 +7,10 @@ #include #include -/** - * @brief The occlusion state of a tile as reported by the renderer proxy. - */ namespace Cesium3DTilesSelection { + /** - * @brief The current occlusion state of a tile, used for occlusion culling. + * @brief The occlusion state of a tile as reported by the renderer proxy. */ enum class CESIUM3DTILESSELECTION_API TileOcclusionState { /** diff --git a/Cesium3DTilesSelection/include/Cesium3DTilesSelection/Tileset.h b/Cesium3DTilesSelection/include/Cesium3DTilesSelection/Tileset.h index 6d72e57bd..1c062ea2f 100644 --- a/Cesium3DTilesSelection/include/Cesium3DTilesSelection/Tileset.h +++ b/Cesium3DTilesSelection/include/Cesium3DTilesSelection/Tileset.h @@ -235,6 +235,14 @@ class CESIUM3DTILESSELECTION_API Tileset final { */ void forEachLoadedTile(const std::function& callback); + /** + * @brief Invokes a function for each tile that is currently loaded. + * + * @param callback The function to invoke. + */ + void forEachLoadedTile( + const std::function& callback) const; + /** * @brief Gets the total number of bytes of tile and raster overlay data that * are currently loaded. diff --git a/Cesium3DTilesSelection/src/DebugTileStateDatabase.cpp b/Cesium3DTilesSelection/src/DebugTileStateDatabase.cpp new file mode 100644 index 000000000..05ec46a39 --- /dev/null +++ b/Cesium3DTilesSelection/src/DebugTileStateDatabase.cpp @@ -0,0 +1,267 @@ +#include +#include +#include + +#include + +using namespace CesiumAsync; + +namespace { + +const std::string DROP_STATE_TABLE_SQL = "DROP TABLE IF EXISTS TileStates"; +const std::string CREATE_STATE_TABLE_SQL = + "CREATE TABLE IF NOT EXISTS TileSelectionStates (" + " Value INTEGER PRIMARY KEY," + " Name TEXT" + ");" + "CREATE TABLE IF NOT EXISTS IsRenderableStates (" + " Value INTEGER PRIMARY KEY, " + " Name TEXT" + ");" + "CREATE TABLE IF NOT EXISTS TileSelectionFrames (" + " Pointer INTEGER NOT NULL," + " FrameNumber INTEGER NOT NULL," + " TileID TEXT," + " SelectionStateFrameNumber INTEGER," + " SelectionState INTEGER," + " IsRenderable BOOLEAN," + " PRIMARY KEY (Pointer, FrameNumber)," + " FOREIGN KEY (SelectionState) REFERENCES TileSelectionStates(Value)," + " FOREIGN KEY (IsRenderable) REFERENCES IsRenderableStates(Value)" + ")"; +const std::string PRAGMA_WAL_SQL = "PRAGMA journal_mode=WAL"; +const std::string PRAGMA_SYNC_SQL = "PRAGMA synchronous=OFF"; +const std::string WRITE_TILE_SELECTION_SQL = + "REPLACE INTO TileSelectionFrames (" + " Pointer," + " FrameNumber," + " TileID," + " SelectionStateFrameNumber," + " SelectionState," + " IsRenderable" + ") VALUES (" + " ?, ?, ?, ?, ?, ?" + ")"; + +} // namespace + +namespace Cesium3DTilesSelection { + +struct DebugTileStateDatabase::Impl { + CesiumAsync::SqliteConnectionPtr pConnection; + CesiumAsync::SqliteStatementPtr writeTileState; +}; + +DebugTileStateDatabase::DebugTileStateDatabase( + const std::string& databaseFilename) + : _pImpl(std::make_unique()) { + CESIUM_SQLITE(sqlite3*) pConnection; + int status = + CESIUM_SQLITE(sqlite3_open)(databaseFilename.c_str(), &pConnection); + if (status != SQLITE_OK) { + throw std::runtime_error(CESIUM_SQLITE(sqlite3_errstr)(status)); + } + + this->_pImpl->pConnection = + std::unique_ptr( + pConnection); + + // Recreate state database + char* createTableError = nullptr; + + status = CESIUM_SQLITE(sqlite3_exec)( + this->_pImpl->pConnection.get(), + DROP_STATE_TABLE_SQL.c_str(), + nullptr, + nullptr, + &createTableError); + if (status != SQLITE_OK) { + std::string errorStr(createTableError); + CESIUM_SQLITE(sqlite3_free)(createTableError); + throw std::runtime_error(errorStr); + } + + status = CESIUM_SQLITE(sqlite3_exec)( + this->_pImpl->pConnection.get(), + CREATE_STATE_TABLE_SQL.c_str(), + nullptr, + nullptr, + &createTableError); + if (status != SQLITE_OK) { + std::string errorStr(createTableError); + CESIUM_SQLITE(sqlite3_free)(createTableError); + throw std::runtime_error(errorStr); + } + + // turn on WAL mode + char* walError = nullptr; + status = CESIUM_SQLITE(sqlite3_exec)( + this->_pImpl->pConnection.get(), + PRAGMA_WAL_SQL.c_str(), + nullptr, + nullptr, + &walError); + if (status != SQLITE_OK) { + std::string errorStr(walError); + CESIUM_SQLITE(sqlite3_free)(walError); + throw std::runtime_error(errorStr); + } + + // turn off synchronous mode + char* syncError = nullptr; + status = CESIUM_SQLITE(sqlite3_exec)( + this->_pImpl->pConnection.get(), + PRAGMA_SYNC_SQL.c_str(), + nullptr, + nullptr, + &syncError); + if (status != SQLITE_OK) { + std::string errorStr(syncError); + CESIUM_SQLITE(sqlite3_free)(syncError); + throw std::runtime_error(errorStr); + } + + this->_pImpl->writeTileState = SqliteHelper::prepareStatement( + this->_pImpl->pConnection, + WRITE_TILE_SELECTION_SQL); + + std::vector> + tileSelectionStates = { + {TileSelectionState::Result::None, "None"}, + {TileSelectionState::Result::Culled, "Culled"}, + {TileSelectionState::Result::Rendered, "Rendered"}, + {TileSelectionState::Result::Refined, "Refined"}, + {TileSelectionState::Result::RenderedAndKicked, "RenderedAndKicked"}, + {TileSelectionState::Result::RefinedAndKicked, "RefinedAndKicked"}}; + + for (const auto& state : tileSelectionStates) { + std::string sql = fmt::format( + "REPLACE INTO TileSelectionStates (Value, Name) VALUES ({}, '{}');", + static_cast(state.first), + state.second.c_str()); + status = CESIUM_SQLITE(sqlite3_exec)( + this->_pImpl->pConnection.get(), + sql.c_str(), + nullptr, + nullptr, + nullptr); + } + + std::vector> isRenderableStates = { + {0, "Not Renderable"}, + {1, "Renderable"}}; + + for (const auto& state : isRenderableStates) { + std::string sql = fmt::format( + "REPLACE INTO IsRenderableStates (Value, Name) VALUES ({}, '{}');", + state.first, + state.second.c_str()); + status = CESIUM_SQLITE(sqlite3_exec)( + this->_pImpl->pConnection.get(), + sql.c_str(), + nullptr, + nullptr, + nullptr); + } +} + +DebugTileStateDatabase::~DebugTileStateDatabase() noexcept = default; + +void DebugTileStateDatabase::recordAllTileStates( + int32_t frameNumber, + const Tileset& tileset) { + int status = CESIUM_SQLITE(sqlite3_exec)( + this->_pImpl->pConnection.get(), + "BEGIN TRANSACTION", + nullptr, + nullptr, + nullptr); + if (status != SQLITE_OK) { + return; + } + + tileset.forEachLoadedTile([frameNumber, this](const Tile& tile) { + this->recordTileState(frameNumber, tile); + }); + + status = CESIUM_SQLITE(sqlite3_exec)( + this->_pImpl->pConnection.get(), + "COMMIT TRANSACTION", + nullptr, + nullptr, + nullptr); +} + +void DebugTileStateDatabase::recordTileState( + int32_t frameNumber, + const Tile& tile) { + int status = CESIUM_SQLITE(sqlite3_reset)(this->_pImpl->writeTileState.get()); + if (status != SQLITE_OK) { + return; + } + + status = + CESIUM_SQLITE(sqlite3_clear_bindings)(this->_pImpl->writeTileState.get()); + if (status != SQLITE_OK) { + return; + } + + status = CESIUM_SQLITE(sqlite3_bind_int64)( + this->_pImpl->writeTileState.get(), + 1, // Pointer + reinterpret_cast(&tile)); + if (status != SQLITE_OK) { + return; + } + + status = CESIUM_SQLITE(sqlite3_bind_int)( + this->_pImpl->writeTileState.get(), + 2, // FrameNumber + frameNumber); + if (status != SQLITE_OK) { + return; + } + + std::string id = TileIdUtilities::createTileIdString(tile.getTileID()); + status = CESIUM_SQLITE(sqlite3_bind_text)( + this->_pImpl->writeTileState.get(), + 3, // TileID + id.c_str(), + static_cast(id.size()), + SQLITE_STATIC); + if (status != SQLITE_OK) { + return; + } + + status = CESIUM_SQLITE(sqlite3_bind_int)( + this->_pImpl->writeTileState.get(), + 4, // SelectionStateFrameNumber + tile.getLastSelectionState().getFrameNumber()); + if (status != SQLITE_OK) { + return; + } + + status = CESIUM_SQLITE(sqlite3_bind_int)( + this->_pImpl->writeTileState.get(), + 5, // SelectionState + static_cast(tile.getLastSelectionState().getResult( + tile.getLastSelectionState().getFrameNumber()))); + if (status != SQLITE_OK) { + return; + } + + status = CESIUM_SQLITE(sqlite3_bind_int)( + this->_pImpl->writeTileState.get(), + 6, // IsRenderable + static_cast(tile.isRenderable())); + if (status != SQLITE_OK) { + return; + } + + status = CESIUM_SQLITE(sqlite3_step)(this->_pImpl->writeTileState.get()); + if (status != SQLITE_DONE) { + return; + } +} + +} // namespace Cesium3DTilesSelection diff --git a/Cesium3DTilesSelection/src/Tileset.cpp b/Cesium3DTilesSelection/src/Tileset.cpp index 30f97ee69..bf8db71dc 100644 --- a/Cesium3DTilesSelection/src/Tileset.cpp +++ b/Cesium3DTilesSelection/src/Tileset.cpp @@ -506,6 +506,16 @@ void Tileset::forEachLoadedTile( } } +void Tileset::forEachLoadedTile( + const std::function& callback) const { + const Tile* pCurrent = this->_loadedTiles.head(); + while (pCurrent) { + const Tile* pNext = this->_loadedTiles.next(pCurrent); + callback(*pCurrent); + pCurrent = pNext; + } +} + int64_t Tileset::getTotalDataBytes() const noexcept { return this->_pTilesetContentManager->getTotalDataUsed(); } @@ -1004,37 +1014,38 @@ Tileset::TraversalDetails Tileset::_renderLeaf( lastFrameSelectionState); } +namespace { + /** - * We can render it if _any_ of the following are true: - * 1. We rendered it (or kicked it) last frame. - * 2. This tile was culled last frame, or it wasn't even visited because an - * ancestor was culled. - * 3. The tile is done loading and ready to render. - * Note that even if we decide to render a tile here, it may later get "kicked" - * in favor of an ancestor. + * @brief Determines if we must refine this tile so that we can continue + * rendering the deeper descendant tiles of this tile. + * + * If this tile was refined last frame, and is not yet renderable, then we + * should REFINE past this tile in order to continue rendering the deeper tiles + * that we rendered last frame, until such time as this tile is loaded and we + * can render it instead. This is necessary to avoid detail vanishing when + * the camera zooms out and lower-detail tiles are not yet loaded. + * + * @param tile The tile to check, which is assumed to meet the SSE for + * rendering. + * @param lastFrameSelectionState The selection state of this tile last frame. + * @param lastFrameNumber The previous frame number. + * @return True if this tile must be refined instead of rendered, so that we can + * continue rendering deeper tiles. */ -static bool shouldRenderThisTile( +bool mustContinueRefiningToDeeperTiles( const Tile& tile, const TileSelectionState& lastFrameSelectionState, int32_t lastFrameNumber) noexcept { const TileSelectionState::Result originalResult = lastFrameSelectionState.getOriginalResult(lastFrameNumber); - if (originalResult == TileSelectionState::Result::Rendered) { - return true; - } - if (originalResult == TileSelectionState::Result::Culled || - originalResult == TileSelectionState::Result::None) { - return true; - } - // Tile::isRenderable is actually a pretty complex operation, so only do - // it when absolutely necessary - if (tile.isRenderable()) { - return true; - } - return false; + return originalResult == TileSelectionState::Result::Refined && + !tile.isRenderable(); } +} // namespace + Tileset::TraversalDetails Tileset::_renderInnerTile( const FrameState& frameState, Tile& tile, @@ -1260,6 +1271,12 @@ Tileset::_checkOcclusion(const Tile& tile, const FrameState& frameState) { return TileOcclusionState::NotOccluded; } +namespace { + +enum class VisitTileAction { Render, Refine }; + +} + // Visits a tile for possible rendering. When we call this function with a tile: // * The tile has previously been determined to be visible. // * Its parent tile does _not_ meet the SSE (unless ancestorMeetsSse=true, @@ -1285,7 +1302,14 @@ Tileset::TraversalDetails Tileset::_visitTile( const bool unconditionallyRefine = tile.getUnconditionallyRefine(); - bool wantToRefine = unconditionallyRefine || (!meetsSse && !ancestorMeetsSse); + // Determine whether to REFINE or RENDER. Note that even if this tile is + // initially marked for RENDER here, it may later switch to REFINE as a + // result of `mustContinueRefiningToDeeperTiles`. + VisitTileAction action = VisitTileAction::Render; + if (unconditionallyRefine) + action = VisitTileAction::Refine; + else if (!meetsSse && !ancestorMeetsSse) + action = VisitTileAction::Refine; const TileSelectionState lastFrameSelectionState = tile.getLastSelectionState(); @@ -1314,14 +1338,15 @@ Tileset::TraversalDetails Tileset::_visitTile( // If this tile and a child were both refined last frame, this tile does not // need occlusion results. bool shouldCheckOcclusion = this->_options.enableOcclusionCulling && - wantToRefine && !unconditionallyRefine && + action == VisitTileAction::Refine && + !unconditionallyRefine && (!tileLastRefined || !childLastRefined); if (shouldCheckOcclusion) { TileOcclusionState occlusion = this->_checkOcclusion(tile, frameState); if (occlusion == TileOcclusionState::Occluded) { ++result.tilesOccluded; - wantToRefine = false; + action = VisitTileAction::Render; meetsSse = true; } else if ( occlusion == TileOcclusionState::OcclusionUnavailable && @@ -1330,55 +1355,47 @@ Tileset::TraversalDetails Tileset::_visitTile( frameState.lastFrameNumber) != TileSelectionState::Result::Refined) { ++result.tilesWaitingForOcclusionResults; - wantToRefine = false; + action = VisitTileAction::Render; meetsSse = true; } } bool queuedForLoad = false; - if (!wantToRefine) { - // This tile (or an ancestor) is the one we want to render this frame, but - // we'll do different things depending on the state of this tile and on what - // we did _last_ frame. - - // We can render it if _any_ of the following are true: - // 1. We rendered it (or kicked it) last frame. - // 2. This tile was culled last frame, or it wasn't even visited because an - // ancestor was culled. - // 3. The tile is done loading and ready to render. - // - // Note that even if we decide to render a tile here, it may later get - // "kicked" in favor of an ancestor. - const bool renderThisTile = shouldRenderThisTile( + if (action == VisitTileAction::Render) { + // This tile meets the screen-space error requirement, so we'd like to + // render it, if we can. + bool mustRefine = mustContinueRefiningToDeeperTiles( tile, lastFrameSelectionState, frameState.lastFrameNumber); - if (renderThisTile) { + if (mustRefine) { + // // We must refine even though this tile meets the SSE. + action = VisitTileAction::Refine; + + // Loading this tile is very important, because a number of deeper, + // higher-detail tiles are being rendered in its stead, so we want to load + // it with high priority. However, if `ancestorMeetsSse` is set, then our + // parent tile is in the exact same situation, and loading this tile with + // high priority would compete with that one. We should prefer the parent + // because it is closest to the actual desired LOD and because up the tree + // there can only be fewer tiles that need loading. + if (!ancestorMeetsSse) { + addTileToLoadQueue(tile, TileLoadPriorityGroup::Urgent, tilePriority); + queuedForLoad = true; + } + + // Fall through to REFINE, but mark this tile as already meeting the + // required SSE. + ancestorMeetsSse = true; + } else { + // Render this tile and return without visiting children. // Only load this tile if it (not just an ancestor) meets the SSE. - if (meetsSse && !ancestorMeetsSse) { + if (!ancestorMeetsSse) { addTileToLoadQueue(tile, TileLoadPriorityGroup::Normal, tilePriority); } return _renderInnerTile(frameState, tile, result); } - - // Otherwise, we can't render this tile (or blank space where it would be) - // because doing so would cause detail to disappear that was visible last - // frame. Instead, keep rendering any still-visible descendants that were - // rendered last frame and render nothing for newly-visible descendants. - // E.g. if we were rendering level 15 last frame but this frame we want - // level 14 and the closest renderable level <= 14 is 0, rendering level - // zero would be pretty jarring so instead we keep rendering level 15 even - // though its SSE is better than required. So fall through to continue - // traversal... - ancestorMeetsSse = true; - - // Load this blocker tile with high priority, but only if this tile (not - // just an ancestor) meets the SSE. - if (meetsSse) { - addTileToLoadQueue(tile, TileLoadPriorityGroup::Urgent, tilePriority); - queuedForLoad = true; - } } // Refine! @@ -1647,10 +1664,30 @@ Tileset::TraversalDetails Tileset::createTraversalDetailsForSingleTile( TileSelectionState::Result lastFrameResult = lastFrameSelectionState.getResult(frameState.lastFrameNumber); bool isRenderable = tile.isRenderable(); + bool wasRenderedLastFrame = - lastFrameResult == TileSelectionState::Result::Rendered || - (tile.getRefine() == TileRefine::Add && - lastFrameResult == TileSelectionState::Result::Refined); + lastFrameResult == TileSelectionState::Result::Rendered; + if (!wasRenderedLastFrame && + lastFrameResult == TileSelectionState::Result::Refined) { + if (tile.getRefine() == TileRefine::Add) { + // An additive-refined tile that was refined was also rendered. + wasRenderedLastFrame = true; + } else { + // With replace-refinement, if any of this refined tile's children were + // rendered last frame, but are no longer rendered because this tile is + // loaded and has sufficient detail, we must treat this tile as rendered + // last frame, too. This is necessary to prevent this tile from being + // kicked just because _it_ wasn't rendered last frame (which could cause + // a new hole to appear). + for (const Tile& child : tile.getChildren()) { + TraversalDetails childDetails = createTraversalDetailsForSingleTile( + frameState, + child, + child.getLastSelectionState()); + wasRenderedLastFrame |= childDetails.anyWereRenderedLastFrame; + } + } + } TraversalDetails traversalDetails; traversalDetails.allAreRenderable = isRenderable; diff --git a/Cesium3DTilesWriter/include/Cesium3DTilesWriter/Library.h b/Cesium3DTilesWriter/include/Cesium3DTilesWriter/Library.h index ea4f4c77d..e7ce93914 100644 --- a/Cesium3DTilesWriter/include/Cesium3DTilesWriter/Library.h +++ b/Cesium3DTilesWriter/include/Cesium3DTilesWriter/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes for writing [3D Tiles](https://github.com/CesiumGS/3d-tiles). + * + * @mermaid-interactive{dependencies/Cesium3DTilesWriter} */ namespace Cesium3DTilesWriter {} diff --git a/CesiumAsync/include/CesiumAsync/Library.h b/CesiumAsync/include/CesiumAsync/Library.h index cd308e10b..9467f2c37 100644 --- a/CesiumAsync/include/CesiumAsync/Library.h +++ b/CesiumAsync/include/CesiumAsync/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes that support asynchronous operations. + * + * @mermaid-interactive{dependencies/CesiumAsync} */ namespace CesiumAsync {} diff --git a/CesiumAsync/include/CesiumAsync/SqliteHelper.h b/CesiumAsync/include/CesiumAsync/SqliteHelper.h new file mode 100644 index 000000000..9633e8011 --- /dev/null +++ b/CesiumAsync/include/CesiumAsync/SqliteHelper.h @@ -0,0 +1,60 @@ +#pragma once + +#include "cesium-sqlite3.h" + +#include +#include + +struct CESIUM_SQLITE(sqlite3); +struct CESIUM_SQLITE(sqlite3_stmt); + +namespace CesiumAsync { + +/** + * @brief A deleter that can be used with `std::unique_ptr` to properly destroy + * a SQLite connection when it is no longer needed. + */ +struct DeleteSqliteConnection { + void operator()(CESIUM_SQLITE(sqlite3*) pConnection) noexcept; +}; + +/** + * @brief A deleter that can be used with `std::unique_ptr` to properly destroy + * a SQLite prepared statement when it is no longer needed. + */ +struct DeleteSqliteStatement { + void operator()(CESIUM_SQLITE(sqlite3_stmt*) pStatement) noexcept; +}; + +/** + * @brief A `std::unique_ptr` that will properly delete the connection + * using the SQLite API. + */ +using SqliteConnectionPtr = + std::unique_ptr; + +/** + * @brief A `std::unique_ptr` that will properly delete the + * statement using the SQLite API. + */ +using SqliteStatementPtr = + std::unique_ptr; + +/** + * @brief Helper functions for working with SQLite. + */ +struct SqliteHelper { + /** + * @brief Create a prepared statement. + * + * @param pConnection The SQLite connection in which to create the prepared + * statement. + * @param sql The SQL text for the statement. + * @return The created prepared statement. + */ + static SqliteStatementPtr prepareStatement( + const SqliteConnectionPtr& pConnection, + const std::string& sql); +}; + +} // namespace CesiumAsync diff --git a/CesiumAsync/src/SqliteCache.cpp b/CesiumAsync/src/SqliteCache.cpp index c4f7934ad..b5e858e64 100644 --- a/CesiumAsync/src/SqliteCache.cpp +++ b/CesiumAsync/src/SqliteCache.cpp @@ -1,7 +1,6 @@ -#include "CesiumAsync/SqliteCache.h" - -#include "CesiumAsync/IAssetResponse.h" - +#include +#include +#include #include #include @@ -129,40 +128,6 @@ std::optional convertStringToHeaders( return headers; } -struct DeleteSqliteConnection { - void operator()(CESIUM_SQLITE(sqlite3*) pConnection) noexcept { - CESIUM_SQLITE(sqlite3_close_v2)(pConnection); - } -}; - -struct DeleteSqliteStatement { - void operator()(CESIUM_SQLITE(sqlite3_stmt*) pStatement) noexcept { - CESIUM_SQLITE(sqlite3_finalize)(pStatement); - } -}; - -using SqliteConnectionPtr = - std::unique_ptr; -using SqliteStatementPtr = - std::unique_ptr; - -SqliteStatementPtr prepareStatement( - const SqliteConnectionPtr& pConnection, - const std::string& sql) { - CESIUM_SQLITE(sqlite3_stmt*) pStmt; - const int status = CESIUM_SQLITE(sqlite3_prepare_v2)( - pConnection.get(), - sql.c_str(), - int(sql.size()), - &pStmt, - nullptr); - if (status != SQLITE_OK) { - throw std::runtime_error( - std::string(CESIUM_SQLITE(sqlite3_errstr)(status))); - } - return SqliteStatementPtr(pStmt); -} - } // namespace namespace CesiumAsync { @@ -277,32 +242,37 @@ void SqliteCache::createConnection() const { // get entry based on key this->_pImpl->_getEntryStmtWrapper = - prepareStatement(this->_pImpl->_pConnection, GET_ENTRY_SQL); + SqliteHelper::prepareStatement(this->_pImpl->_pConnection, GET_ENTRY_SQL); // update last accessed for entry - this->_pImpl->_updateLastAccessedTimeStmtWrapper = prepareStatement( - this->_pImpl->_pConnection, - UPDATE_LAST_ACCESSED_TIME_SQL); + this->_pImpl->_updateLastAccessedTimeStmtWrapper = + SqliteHelper::prepareStatement( + this->_pImpl->_pConnection, + UPDATE_LAST_ACCESSED_TIME_SQL); // store response - this->_pImpl->_storeResponseStmtWrapper = - prepareStatement(this->_pImpl->_pConnection, STORE_RESPONSE_SQL); + this->_pImpl->_storeResponseStmtWrapper = SqliteHelper::prepareStatement( + this->_pImpl->_pConnection, + STORE_RESPONSE_SQL); // query total items - this->_pImpl->_totalItemsQueryStmtWrapper = - prepareStatement(this->_pImpl->_pConnection, TOTAL_ITEMS_QUERY_SQL); + this->_pImpl->_totalItemsQueryStmtWrapper = SqliteHelper::prepareStatement( + this->_pImpl->_pConnection, + TOTAL_ITEMS_QUERY_SQL); // delete expired items - this->_pImpl->_deleteExpiredStmtWrapper = - prepareStatement(this->_pImpl->_pConnection, DELETE_EXPIRED_ITEMS_SQL); + this->_pImpl->_deleteExpiredStmtWrapper = SqliteHelper::prepareStatement( + this->_pImpl->_pConnection, + DELETE_EXPIRED_ITEMS_SQL); // delete expired items - this->_pImpl->_deleteLRUStmtWrapper = - prepareStatement(this->_pImpl->_pConnection, DELETE_LRU_ITEMS_SQL); + this->_pImpl->_deleteLRUStmtWrapper = SqliteHelper::prepareStatement( + this->_pImpl->_pConnection, + DELETE_LRU_ITEMS_SQL); // clear all items this->_pImpl->_clearAllStmtWrapper = - prepareStatement(this->_pImpl->_pConnection, CLEAR_ALL_SQL); + SqliteHelper::prepareStatement(this->_pImpl->_pConnection, CLEAR_ALL_SQL); } SqliteCache::~SqliteCache() = default; diff --git a/CesiumAsync/src/SqliteHelper.cpp b/CesiumAsync/src/SqliteHelper.cpp new file mode 100644 index 000000000..fd48bda1a --- /dev/null +++ b/CesiumAsync/src/SqliteHelper.cpp @@ -0,0 +1,36 @@ +#include + +#include + +#include + +namespace CesiumAsync { + +void DeleteSqliteConnection::operator()(CESIUM_SQLITE(sqlite3*) + pConnection) noexcept { + CESIUM_SQLITE(sqlite3_close_v2)(pConnection); +} + +void DeleteSqliteStatement::operator()(CESIUM_SQLITE(sqlite3_stmt*) + pStatement) noexcept { + CESIUM_SQLITE(sqlite3_finalize)(pStatement); +} + +SqliteStatementPtr SqliteHelper::prepareStatement( + const SqliteConnectionPtr& pConnection, + const std::string& sql) { + CESIUM_SQLITE(sqlite3_stmt*) pStmt; + const int status = CESIUM_SQLITE(sqlite3_prepare_v2)( + pConnection.get(), + sql.c_str(), + int(sql.size()), + &pStmt, + nullptr); + if (status != SQLITE_OK) { + throw std::runtime_error( + std::string(CESIUM_SQLITE(sqlite3_errstr)(status))); + } + return SqliteStatementPtr(pStmt); +} + +} // namespace CesiumAsync diff --git a/CesiumGeometry/include/CesiumGeometry/Library.h b/CesiumGeometry/include/CesiumGeometry/Library.h index 50a7029cc..b7e9cef56 100644 --- a/CesiumGeometry/include/CesiumGeometry/Library.h +++ b/CesiumGeometry/include/CesiumGeometry/Library.h @@ -2,6 +2,8 @@ /** * @brief Basic geometry classes for Cesium + * + * @mermaid-interactive{dependencies/CesiumGeometry} */ namespace CesiumGeometry {} diff --git a/CesiumGeospatial/include/CesiumGeospatial/Library.h b/CesiumGeospatial/include/CesiumGeospatial/Library.h index 423b64ad8..031528300 100644 --- a/CesiumGeospatial/include/CesiumGeospatial/Library.h +++ b/CesiumGeospatial/include/CesiumGeospatial/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes for geospatial computations in Cesium + * + * @mermaid-interactive{dependencies/CesiumGeospatial} */ namespace CesiumGeospatial {} diff --git a/CesiumGltf/include/CesiumGltf/InstanceAttributeSemantics.h b/CesiumGltf/include/CesiumGltf/InstanceAttributeSemantics.h new file mode 100644 index 000000000..6c2b92220 --- /dev/null +++ b/CesiumGltf/include/CesiumGltf/InstanceAttributeSemantics.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +namespace CesiumGltf { + +/** + * @brief The standard glTF instance attribute semantics from + * `EXT_mesh_gpu_instancing` plus additional instance attribute semantics from + * extensions. + */ +struct InstanceAttributeSemantics { + /** + * @brief XYZ translation vector. + */ + static const std::string TRANSLATION; + + /** + * @brief XYZW rotation quaternion. + */ + static const std::string ROTATION; + + /** + * @brief XYZ scale vector. + */ + static const std::string SCALE; + + /** + * @brief Feature IDs used by `EXT_instance_features`. + */ + static const std::array FEATURE_ID_n; +}; + +} // namespace CesiumGltf diff --git a/CesiumGltf/include/CesiumGltf/Library.h b/CesiumGltf/include/CesiumGltf/Library.h index 517fa6fad..8a4fc2bcb 100644 --- a/CesiumGltf/include/CesiumGltf/Library.h +++ b/CesiumGltf/include/CesiumGltf/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes for working with [glTF](https://www.khronos.org/gltf/) models. + * + * @mermaid-interactive{dependencies/CesiumGltf} */ namespace CesiumGltf {} diff --git a/CesiumGltf/include/CesiumGltf/VertexAttributeSemantics.h b/CesiumGltf/include/CesiumGltf/VertexAttributeSemantics.h index 03ea6a84f..9eb0f2197 100644 --- a/CesiumGltf/include/CesiumGltf/VertexAttributeSemantics.h +++ b/CesiumGltf/include/CesiumGltf/VertexAttributeSemantics.h @@ -6,7 +6,8 @@ namespace CesiumGltf { /** - * @brief The standard glTF vertex attribute semantics from the specification. + * @brief The standard glTF vertex attribute semantics from the specification + * plus additional vertex attribute semantics from extensions. */ struct VertexAttributeSemantics { /** @@ -46,6 +47,11 @@ struct VertexAttributeSemantics { * @brief The weights indicating how strongly the joint influences the vertex. */ static const std::array WEIGHTS_n; + + /** + * @brief Feature IDs used by `EXT_mesh_features`. + */ + static const std::array FEATURE_ID_n; }; } // namespace CesiumGltf diff --git a/CesiumGltf/src/InstanceAttributeSemantics.cpp b/CesiumGltf/src/InstanceAttributeSemantics.cpp new file mode 100644 index 000000000..6bde1ea61 --- /dev/null +++ b/CesiumGltf/src/InstanceAttributeSemantics.cpp @@ -0,0 +1,33 @@ +#include + +namespace CesiumGltf { + +/** + * @brief XYZ translation vector. + */ +const std::string InstanceAttributeSemantics::TRANSLATION = "TRANSLATION"; + +/** + * @brief XYZW rotation quaternion. + */ +const std::string InstanceAttributeSemantics::ROTATION = "ROTATION"; + +/** + * @brief XYZ scale vector. + */ +const std::string InstanceAttributeSemantics::SCALE = "SCALE"; + +/** + * @brief Feature IDs used in `EXT_mesh_features`. + */ +const std::array InstanceAttributeSemantics::FEATURE_ID_n = { + "_FEATURE_ID_0", + "_FEATURE_ID_1", + "_FEATURE_ID_2", + "_FEATURE_ID_3", + "_FEATURE_ID_4", + "_FEATURE_ID_5", + "_FEATURE_ID_6", + "_FEATURE_ID_7"}; + +} // namespace CesiumGltf diff --git a/CesiumGltf/src/VertexAttributeSemantics.cpp b/CesiumGltf/src/VertexAttributeSemantics.cpp index 932a3e002..e8a1661a3 100644 --- a/CesiumGltf/src/VertexAttributeSemantics.cpp +++ b/CesiumGltf/src/VertexAttributeSemantics.cpp @@ -72,4 +72,17 @@ const std::array VertexAttributeSemantics::WEIGHTS_n = { "WEIGHTS_6", "WEIGHTS_7"}; +/** + * @brief Feature IDs used in `EXT_mesh_features`. + */ +const std::array VertexAttributeSemantics::FEATURE_ID_n = { + "_FEATURE_ID_0", + "_FEATURE_ID_1", + "_FEATURE_ID_2", + "_FEATURE_ID_3", + "_FEATURE_ID_4", + "_FEATURE_ID_5", + "_FEATURE_ID_6", + "_FEATURE_ID_7"}; + } // namespace CesiumGltf diff --git a/CesiumGltfContent/include/CesiumGltfContent/Library.h b/CesiumGltfContent/include/CesiumGltfContent/Library.h index 7b8ad7942..fe24b38de 100644 --- a/CesiumGltfContent/include/CesiumGltfContent/Library.h +++ b/CesiumGltfContent/include/CesiumGltfContent/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes that support manipulating the content of a glTF. + * + * @mermaid-interactive{dependencies/CesiumGltfContent} */ namespace CesiumGltfContent {} diff --git a/CesiumGltfReader/include/CesiumGltfReader/Library.h b/CesiumGltfReader/include/CesiumGltfReader/Library.h index d4f85b2ae..a4dabcb2c 100644 --- a/CesiumGltfReader/include/CesiumGltfReader/Library.h +++ b/CesiumGltfReader/include/CesiumGltfReader/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes for reading [glTF](https://www.khronos.org/gltf/) models. + * + * @mermaid-interactive{dependencies/CesiumGltfReader} */ namespace CesiumGltfReader {} diff --git a/CesiumGltfWriter/include/CesiumGltfWriter/Library.h b/CesiumGltfWriter/include/CesiumGltfWriter/Library.h index 65c640127..d99007717 100644 --- a/CesiumGltfWriter/include/CesiumGltfWriter/Library.h +++ b/CesiumGltfWriter/include/CesiumGltfWriter/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes for writing [glTF](https://www.khronos.org/gltf/) models. + * + * @mermaid-interactive{dependencies/CesiumGltfWriter} */ namespace CesiumGltfWriter {} diff --git a/CesiumIonClient/include/CesiumIonClient/Library.h b/CesiumIonClient/include/CesiumIonClient/Library.h index a95a0f5ef..62ea3fd9f 100644 --- a/CesiumIonClient/include/CesiumIonClient/Library.h +++ b/CesiumIonClient/include/CesiumIonClient/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes for working with Cesium ion clients + * + * @mermaid-interactive{dependencies/CesiumIonClient} */ namespace CesiumIonClient {} diff --git a/CesiumJsonReader/include/CesiumJsonReader/Library.h b/CesiumJsonReader/include/CesiumJsonReader/Library.h index 1a44da88e..8f4253197 100644 --- a/CesiumJsonReader/include/CesiumJsonReader/Library.h +++ b/CesiumJsonReader/include/CesiumJsonReader/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes for reading JSON. + * + * @mermaid-interactive{dependencies/CesiumJsonReader} */ namespace CesiumJsonReader {} diff --git a/CesiumJsonWriter/include/CesiumJsonWriter/Library.h b/CesiumJsonWriter/include/CesiumJsonWriter/Library.h index e7b1ba5f8..c7dbc66c1 100644 --- a/CesiumJsonWriter/include/CesiumJsonWriter/Library.h +++ b/CesiumJsonWriter/include/CesiumJsonWriter/Library.h @@ -2,6 +2,8 @@ /** * @brief Classes for writing JSON. + * + * @mermaid-interactive{dependencies/CesiumJsonWriter} */ namespace CesiumJsonWriter {} diff --git a/CesiumQuantizedMeshTerrain/include/CesiumQuantizedMeshTerrain/Library.h b/CesiumQuantizedMeshTerrain/include/CesiumQuantizedMeshTerrain/Library.h index 16e10c1cb..0c6ccf934 100644 --- a/CesiumQuantizedMeshTerrain/include/CesiumQuantizedMeshTerrain/Library.h +++ b/CesiumQuantizedMeshTerrain/include/CesiumQuantizedMeshTerrain/Library.h @@ -3,6 +3,8 @@ /** * @brief Classes for accessing terrain based on layer.json and * quantized-mesh-1.0. + * + * @mermaid-interactive{dependencies/CesiumQuantizedMeshTerrain} */ namespace CesiumQuantizedMeshTerrain {} diff --git a/CesiumRasterOverlays/include/CesiumRasterOverlays/Library.h b/CesiumRasterOverlays/include/CesiumRasterOverlays/Library.h index 873c2df2a..cab3f4040 100644 --- a/CesiumRasterOverlays/include/CesiumRasterOverlays/Library.h +++ b/CesiumRasterOverlays/include/CesiumRasterOverlays/Library.h @@ -3,6 +3,8 @@ /** * @brief Classes for raster overlays, which allow draping massive 2D textures * over a model. + * + * @mermaid-interactive{dependencies/CesiumRasterOverlays} */ namespace CesiumRasterOverlays {} diff --git a/CesiumRasterOverlays/src/QuadtreeRasterOverlayTileProvider.cpp b/CesiumRasterOverlays/src/QuadtreeRasterOverlayTileProvider.cpp index 8c7c451aa..b7b19ae13 100644 --- a/CesiumRasterOverlays/src/QuadtreeRasterOverlayTileProvider.cpp +++ b/CesiumRasterOverlays/src/QuadtreeRasterOverlayTileProvider.cpp @@ -663,7 +663,11 @@ QuadtreeRasterOverlayTileProvider::combineImages( continue; } - result.moreDetailAvailable |= loaded.moreDetailAvailable; + // Tiles with a subset inherently have no more detail available (otherwise + // we wouldn't need the subset). + if (!it->pValue->subset) { + result.moreDetailAvailable |= loaded.moreDetailAvailable; + } blitImage( target, diff --git a/CesiumUtility/include/CesiumUtility/Library.h b/CesiumUtility/include/CesiumUtility/Library.h index ed1ded7c0..509c5cf90 100644 --- a/CesiumUtility/include/CesiumUtility/Library.h +++ b/CesiumUtility/include/CesiumUtility/Library.h @@ -2,6 +2,8 @@ /** * @brief Utility classes for Cesium + * + * @mermaid-interactive{dependencies/CesiumUtility} */ namespace CesiumUtility {} diff --git a/README.md b/README.md index e910d3ad9..6ce657f87 100644 --- a/README.md +++ b/README.md @@ -1,125 +1,111 @@ # Cesium Native -Cesium Native is a set of C++ libraries for 3D geospatial, including: - -* [3D Tiles](https://github.com/CesiumGS/3d-tiles) runtime streaming -* lightweight glTF serialization and deserialization, and -* high-precision 3D geospatial math types and functions, including support for global-scale WGS84 ellipsoids. - [![License](https://img.shields.io/:license-Apache_2.0-blue.svg)](https://github.com/CesiumGS/cesium-native/blob/main/LICENSE) [![Build Status](https://github.com/CesiumGS/cesium-native/actions/workflows/build.yml/badge.svg)](https://github.com/CesiumGS/cesium-native/actions/workflows/build.yml) +[![Release](https://img.shields.io/github/v/tag/CesiumGS/cesium-native?label=release)](https://github.com/CesiumGS/cesium-native/tags) -Cesium Native powers Cesium's runtime integrations for [Cesium for Unreal](https://github.com/CesiumGS/cesium-unreal), [Cesium for Unity](https://github.com/CesiumGS/cesium-unity), [Cesium for Omniverse](https://github.com/CesiumGS/cesium-omniverse), and [Cesium for O3DE](https://github.com/CesiumGS/cesium-o3de). Cesium Native is the foundational layer for any 3D geospatial software, especially those that want to stream 3D Tiles. - -![Cesium Platform and Ecosystem](./doc/integration-ecosystem-diagram.jpg) -*

A high-level Cesium platform architecture with the runtime integrations powered by Cesium Native and streaming content from Cesium ion.

* - -### 🗃️Libraries Overview +📚Documentation - 📒Change Log - 💬Community Forums -| Library | Description | -| -- | -- | -| **Cesium3DTiles** | Lightweight 3D Tiles classes. | -| **Cesium3DTilesReader** | 3D Tiles deserialization, including 3D Tiles extension support. | -| **Cesium3DTilesWriter** | 3D Tiles serialization, including 3D Tiles extension support. | -| **Cesium3DTilesSelection** | Runtime streaming, decoding, level of detail selection, culling, cache management, and decoding of 3D Tiles. | -| **CesiumAsync** | Classes for multi-threaded asynchronous tasks. | -| **CesiumGeometry** | Common 3D geometry classes; and bounds testing, intersection testing, and spatial indexing algorithms. | -| **CesiumGeospatial** | 3D geospatial math types and functions for ellipsoids, transforms, projections. | -| **CesiumGltf** | Lightweight glTF processing and optimization functions. | -| **CesiumGltfReader** | glTF deserialization / decoding, including glTF extension support (`KHR_draco_mesh_compression` etc). | -| **CesiumGltfWriter** | glTF serialization / encoding, including glTF extension support. | -| **CesiumIonClient** | Functions to access [Cesium ion](https://cesium.com/cesium-ion/) accounts and 3D tilesets using ion's REST API. | -| **CesiumJsonReader** | Reads JSON from a buffer into statically-typed classes. | -| **CesiumJsonWriter** | Writes JSON from statically-typed classes into a buffer. | -| **CesiumUtility** | Utility functions for JSON parsing, URI processing, etc. | +## 📖About +Cesium Native is a set of C++ libraries for 3D geospatial, including: -### 📗License +* [3D Tiles](https://github.com/CesiumGS/3d-tiles) runtime streaming +* lightweight glTF serialization and deserialization +* high-precision 3D geospatial math types and functions, including support for global-scale WGS84 ellipsoids. +* support for draping raster overlays from WMS, TMS, WMTS, and other sources over 3D tilesets + +Cesium Native powers Cesium's runtime integrations for [Cesium for Unreal](https://github.com/CesiumGS/cesium-unreal), [Cesium for Unity](https://github.com/CesiumGS/cesium-unity), [Cesium for Omniverse](https://github.com/CesiumGS/cesium-omniverse), and [Cesium for O3DE](https://github.com/CesiumGS/cesium-o3de). Cesium Native is the foundational layer for any 3D geospatial software, especially those that want to stream 3D Tiles. See [Projects Using Cesium Native](#projects-using-cesium-native) for a list of projects currently integrating with Cesium Native. + +![Cesium Platform and Ecosystem](./doc/img/integration-ecosystem-diagram.png) + +

A high-level Cesium platform architecture with the runtime integrations powered by Cesium Native and streaming content from Cesium ion.

+ +## 📷Screenshots + + + + + + + + + + + + +
+ + Googleplex + + +

The Googleplex in Mountain View, California, USA, visualized with Google Photorealistic 3D Tiles in Cesium for Unity.

+
+ + New York + + +

Cesium OSM Buildings in Cesium for Unreal with shading from metadata on building height and age.

+
+ + Copernicus Crater + + +

The Copernicus Crater, visualized with Cesium Moon Terrain in Cesium for Unreal.
 

+
+ + San Francisco + + +

Cesium for Omniverse scene set in San Francisco, California, USA. Data courtesy Aerometrex.

+
+ +## 🗃️Libraries Overview + +| Library | Description | +| ------------------------------ | --------------------------------------------------------------------------------------------------------------- | +| **Cesium3DTiles** | Lightweight 3D Tiles classes. | +| **Cesium3DTilesContent** | Classes that support loading and converting 3D Tiles tile content. | +| **Cesium3DTilesReader** | 3D Tiles deserialization, including 3D Tiles extension support. | +| **Cesium3DTilesWriter** | 3D Tiles serialization, including 3D Tiles extension support. | +| **Cesium3DTilesSelection** | Runtime streaming, level of detail selection, culling, cache management, and decoding of 3D Tiles. | +| **CesiumAsync** | Classes for multi-threaded asynchronous tasks. | +| **CesiumGeometry** | Common 3D geometry classes; and bounds testing, intersection testing, and spatial indexing algorithms. | +| **CesiumGeospatial** | 3D geospatial math types and functions for ellipsoids, transforms, projections. | +| **CesiumGltf** | Lightweight glTF processing and optimization functions. | +| **CesiumGltfContent** | Classes that support manipulating the content of a glTF. | +| **CesiumGltfReader** | glTF deserialization / decoding, including glTF extension support (`KHR_draco_mesh_compression` etc). | +| **CesiumGltfWriter** | glTF serialization / encoding, including glTF extension support. | +| **CesiumIonClient** | Functions to access [Cesium ion](https://cesium.com/cesium-ion/) accounts and 3D tilesets using ion's REST API. | +| **CesiumJsonReader** | Reads JSON from a buffer into statically-typed classes. | +| **CesiumJsonWriter** | Writes JSON from statically-typed classes into a buffer. | +| **CesiumQuantizedMeshTerrain** | Classes for accessing terrain in the [quantized-mesh-1.0](https://github.com/CesiumGS/quantized-mesh) format. | +| **CesiumRasterOverlays** | Classes for raster overlays, which allow draping massive 2D textures over a model. | +| **CesiumUtility** | Utility functions for JSON parsing, URI processing, credits, etc. | + +## 📗License [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). Cesium Native is free for both commercial and non-commercial use. -## 💻Developers - -### ⭐Prerequisites - -* Visual Studio 2019 (or newer), GCC v11.x+, Clang 12+. Other compilers are likely to work but are not regularly tested. -* CMake 3.15+ -* For best JPEG-decoding performance, you must have [nasm](https://www.nasm.us/) installed so that CMake can find it. Everything will work fine without it, just slower. - -### 🚀Getting Started - -#### Clone the repo - -Check out the repo with: - -```bash -git clone git@github.com:CesiumGS/cesium-native.git --recurse-submodules -``` - -If you forget the `--recurse-submodules`, nothing will work because the git submodules will be missing. You should be able to fix it with: - -```bash -git submodule update --init --recursive -``` - -#### Compile from command line - -```bash -## Windows compilation using Visual Studio -cmake -B build -S . -G "Visual Studio 15 2017 Win64" -cmake --build build --config Debug -cmake --build build --config Release - -## Linux compilation -cmake -B build -S . -cmake --build build -``` - -#### Compile from Visual Studio Code - -1) Install the `CMake Tools` extension. It should prompt you to generate project files from CMake. -2) On Windows, choose `Visual Studio 2017 Release - amd64` as the kit to build. Or choose an appropriate kit for your platform. -3) Then press Ctrl-Shift-P and execute the `CMake: Build` task or press F7. - -#### Compile with any Visual Studio version using CMake generated projects - -1) Open the CMake UI (cmake-gui) -2) Under "Where is the source code", point to your repo -3) Specify your output folder in "Where to build the binaries" -4) Click "Configure". -5) Under "Specify the generator for this project", choose the VS version on your system -6) Click Finish, wait for the process to finish -7) Click Generate - -Look for cesium-native.sln in your output folder. - -Unit tests can also be run from this solution, under the cesium-native-tests project. - -![image](https://github.com/CesiumGS/cesium-native/assets/130494071/4d398bfc-f770-49d4-8ef5-a995096ad4a1) +## 🔧Projects Using Cesium Native +The following official Cesium integrations are built on top of Cesium Native: -#### Generate Documentation +- [Cesium for Unreal](https://github.com/CesiumGS/cesium-unreal) +- [Cesium for Unity](https://github.com/CesiumGS/cesium-unity) +- [Cesium for Omniverse](https://github.com/CesiumGS/cesium-omniverse) +- [Cesium for O3DE](https://github.com/CesiumGS/cesium-o3de) -* Install [Doxygen](https://www.doxygen.nl/). -* Run: `cmake --build build --target cesium-native-docs` -* Open `build/doc/html/index.html` +In addition, Cesium Native has been used by the community to build projects including: +- [vsgCs](https://github.com/timoore/vsgCs) integrates Cesium Native with VulkanSceneGraph. +- [osgEarth](https://github.com/gwaldron/osgearth) uses Cesium Native to load 3D Tiles in OpenSceneGraph. -#### Regenerate glTF and 3D Tiles classes +If you have a project that integrates with Cesium Native that isn't on this list yet, please let us know! -Much of the code in `CesiumGltf`, `Cesium3DTiles`, `CesiumGltfReader`, and `Cesium3DTilesReader` is generated from the standards' JSON Schema specifications. To regenerate the code: +## 💻Developing with Cesium Native -* Make sure you have a relatively recent version of Node.js installed. -* Install dependencies by running: +See the [Developer Setup Guide](doc/topics/developer-setup.md) to learn how to set up a development environment with Cesium Native and begin developing with it. -``` -npm install -cd tools/generate-classes -npm install -cd ../.. -``` +## ⭐Contributing -* From the repo root directory, run these commands - * `npm run generate-gltf` - * `npm run generate-3d-tiles` - * `npm run generate-quantized-mesh-terrain` -* On Windows, the line endings of the generated files will be different than those checked into the repo. Just `git add` them and git will fix the line endings (no need to commit). +Are you interested in contributing to Cesium Native's development? Contributions can come in many forms, from answering questions to creating issues and pull requests. See our [Contribution Guide](CONTRIBUTING.md) to find out how to get started! \ No newline at end of file diff --git a/cmake/detect-vcpkg-triplet.cmake b/cmake/detect-vcpkg-triplet.cmake index 2c3b69e57..b1b332191 100644 --- a/cmake/detect-vcpkg-triplet.cmake +++ b/cmake/detect-vcpkg-triplet.cmake @@ -24,10 +24,19 @@ elseif(APPLE) else() set(DETECTED_VCPKG_TRIPLET "${CMAKE_OSX_ARCHITECTURES}-osx") endif() - elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") - set(DETECTED_VCPKG_TRIPLET "arm64-osx") else() - set(DETECTED_VCPKG_TRIPLET "x64-osx") + if(NOT CMAKE_SYSTEM_PROCESSOR) + execute_process( + COMMAND uname -m + OUTPUT_VARIABLE CMAKE_SYSTEM_PROCESSOR + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set(DETECTED_VCPKG_TRIPLET "arm64-osx") + else() + set(DETECTED_VCPKG_TRIPLET "x64-osx") + endif() endif() elseif(LINUX) # Assuming x64 here isn't necessarily correct, but it's the only platform we officially support. diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 64bf7cb4b..a73405473 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -5,6 +5,7 @@ if(DOXYGEN_FOUND) LIB_DIRS ../Cesium3DTiles/include ../Cesium3DTiles/generated/include + ../Cesium3DTilesContent/include ../Cesium3DTilesReader/include ../Cesium3DTilesReader/generated/include ../Cesium3DTilesWriter/include @@ -31,6 +32,7 @@ if(DOXYGEN_FOUND) set( DOXYGEN_EXAMPLE_PATH ../Cesium3DTiles/test + ../Cesium3DTilesContent/test ../Cesium3DTilesReader/test ../Cesium3DTilesWriter/test ../Cesium3DTilesSelection/test @@ -46,6 +48,7 @@ if(DOXYGEN_FOUND) ../CesiumQuantizedMeshTerrain/test ../CesiumRasterOverlays/test ../CesiumUtility/test + ../ # For examples drawn from the actual code ) # These macro definitions confuse doxygen, causing it @@ -84,13 +87,23 @@ if(DOXYGEN_FOUND) set(DOXYGEN_BUILTIN_STL_SUPPORT YES) set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "../README.md") set(DOXYGEN_EXCLUDE_PATTERNS "*/node_modules/*") - set(DOXYGEN_IMAGE_PATH "./") + set(DOXYGEN_DOT_GRAPH_MAX_NODES 100) set(DOXYGEN_WARN_AS_ERROR FAIL_ON_WARNINGS_PRINT) + list(APPEND DOXYGEN_IMAGE_PATH "${CMAKE_CURRENT_LIST_DIR}/") + list(APPEND DOXYGEN_IMAGE_PATH "${CMAKE_CURRENT_LIST_DIR}/img") + + set(DOXYGEN_MARKDOWN_ID_STYLE GITHUB) + set(DOXYGEN_INTERACTIVE_SVG YES) + # Tag files can be used by other Doxygen projects to link to our docs + # For example, Cesium for Unreal can use it to link to the Cesium Native docs without duplicating them. + set(DOXYGEN_GENERATE_TAGFILE "${CMAKE_CURRENT_BINARY_DIR}/html/cesium-native.tag") # Add support for Mermaid charts using the @mermaid command. - set(DOXYGEN_HTML_EXTRA_FILES "${CMAKE_CURRENT_LIST_DIR}/assets/mermaid.min.js ${CMAKE_CURRENT_LIST_DIR}/assets/mingcute.json.js") - set(DOXYGEN_ALIASES mermaid{1}="\\htmlonly
^^ \\endhtmlonly \\htmlinclude \\\"\\1.mmd\\\" \\htmlonly ^^
\\endhtmlonly") + set(DOXYGEN_HTML_EXTRA_FILES "${CMAKE_CURRENT_LIST_DIR}/assets/mermaid.min.js ${CMAKE_CURRENT_LIST_DIR}/assets/mingcute.json.js ${CMAKE_CURRENT_LIST_DIR}/assets/panzoom.js") + list(APPEND DOXYGEN_ALIASES mermaid{1}="\\htmlonly
^^ \\endhtmlonly \\htmlinclude \\\"\\1.mmd\\\" \\htmlonly ^^
\\endhtmlonly") + list(APPEND DOXYGEN_ALIASES mermaid-interactive{1}="\\htmlonly
^^ \\endhtmlonly \\htmlinclude \\\"\\1.mmd\\\" \\htmlonly ^^
\\endhtmlonly") + list(APPEND DOXYGEN_ALIASES svg-interactive{2}="\\htmlonly
^^ \\endhtmlonly \\image html \\\"\\1.svg\\\" \\htmlonly ^^
\\endhtmlonly") set(DOXYGEN_VERBATIM_VARS DOXYGEN_ALIASES DOXYGEN_HTML_EXTRA_FILES) list(APPEND DOXYGEN_EXAMPLE_PATH "${CMAKE_CURRENT_LIST_DIR}/diagrams") @@ -101,7 +114,9 @@ if(DOXYGEN_FOUND) doxygen_add_docs( cesium-native-docs + "../CONTRIBUTING.md" "../README.md" + "../CHANGES.md" ${CESIUM_DOC_TOPICS} ${LIB_DIRS} ) diff --git a/doc/assets/panzoom.js b/doc/assets/panzoom.js new file mode 100644 index 000000000..4e41cd718 --- /dev/null +++ b/doc/assets/panzoom.js @@ -0,0 +1,24 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016 - 2024 Andrei Kashcha + +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. +*/ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.panzoom=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i0){transform.x+=diff;adjusted=true}diff=boundingBox.right-clientRect.left;if(diff<0){transform.x+=diff;adjusted=true}diff=boundingBox.top-clientRect.bottom;if(diff>0){transform.y+=diff;adjusted=true}diff=boundingBox.bottom-clientRect.top;if(diff<0){transform.y+=diff;adjusted=true}return adjusted}function getBoundingBox(){if(!bounds)return;if(typeof bounds==="boolean"){var ownerRect=owner.getBoundingClientRect();var sceneWidth=ownerRect.width;var sceneHeight=ownerRect.height;return{left:sceneWidth*boundsPadding,top:sceneHeight*boundsPadding,right:sceneWidth*(1-boundsPadding),bottom:sceneHeight*(1-boundsPadding)}}return bounds}function getClientRect(){var bbox=panController.getBBox();var leftTop=client(bbox.left,bbox.top);return{left:leftTop.x,top:leftTop.y,right:bbox.width*transform.scale+leftTop.x,bottom:bbox.height*transform.scale+leftTop.y}}function client(x,y){return{x:x*transform.scale+transform.x,y:y*transform.scale+transform.y}}function makeDirty(){isDirty=true;frameAnimation=window.requestAnimationFrame(frame)}function zoomByRatio(clientX,clientY,ratio){if(isNaN(clientX)||isNaN(clientY)||isNaN(ratio)){throw new Error("zoom requires valid numbers")}var newScale=transform.scale*ratio;if(newScalemaxZoom){if(transform.scale===maxZoom)return;ratio=maxZoom/transform.scale}var size=transformToScreen(clientX,clientY);transform.x=size.x-ratio*(size.x-transform.x);transform.y=size.y-ratio*(size.y-transform.y);if(bounds&&boundsPadding===1&&minZoom===1){transform.scale*=ratio;keepTransformInsideBounds()}else{var transformAdjusted=keepTransformInsideBounds();if(!transformAdjusted)transform.scale*=ratio}triggerEvent("zoom");makeDirty()}function zoomAbs(clientX,clientY,zoomLevel){var ratio=zoomLevel/transform.scale;zoomByRatio(clientX,clientY,ratio)}function centerOn(ui){var parent=ui.ownerSVGElement;if(!parent)throw new Error("ui element is required to be within the scene");var clientRect=ui.getBoundingClientRect();var cx=clientRect.left+clientRect.width/2;var cy=clientRect.top+clientRect.height/2;var container=parent.getBoundingClientRect();var dx=container.width/2-cx;var dy=container.height/2-cy;internalMoveBy(dx,dy,true)}function smoothMoveTo(x,y){internalMoveBy(x-transform.x,y-transform.y,true)}function internalMoveBy(dx,dy,smooth){if(!smooth){return moveBy(dx,dy)}if(moveByAnimation)moveByAnimation.cancel();var from={x:0,y:0};var to={x:dx,y:dy};var lastX=0;var lastY=0;moveByAnimation=animate(from,to,{step:function(v){moveBy(v.x-lastX,v.y-lastY);lastX=v.x;lastY=v.y}})}function scroll(x,y){cancelZoomAnimation();moveTo(x,y)}function dispose(){releaseEvents()}function listenForEvents(){owner.addEventListener("mousedown",onMouseDown,{passive:false});owner.addEventListener("dblclick",onDoubleClick,{passive:false});owner.addEventListener("touchstart",onTouch,{passive:false});owner.addEventListener("keydown",onKeyDown,{passive:false});wheel.addWheelListener(owner,onMouseWheel,{passive:false});makeDirty()}function releaseEvents(){wheel.removeWheelListener(owner,onMouseWheel);owner.removeEventListener("mousedown",onMouseDown);owner.removeEventListener("keydown",onKeyDown);owner.removeEventListener("dblclick",onDoubleClick);owner.removeEventListener("touchstart",onTouch);if(frameAnimation){window.cancelAnimationFrame(frameAnimation);frameAnimation=0}smoothScroll.cancel();releaseDocumentMouse();releaseTouches();textSelection.release();triggerPanEnd()}function frame(){if(isDirty)applyTransform()}function applyTransform(){isDirty=false;panController.applyTransform(transform);triggerEvent("transform");frameAnimation=0}function onKeyDown(e){var x=0,y=0,z=0;if(e.keyCode===38){y=1}else if(e.keyCode===40){y=-1}else if(e.keyCode===37){x=1}else if(e.keyCode===39){x=-1}else if(e.keyCode===189||e.keyCode===109){z=1}else if(e.keyCode===187||e.keyCode===107){z=-1}if(filterKey(e,x,y,z)){return}if(x||y){e.preventDefault();e.stopPropagation();var clientRect=owner.getBoundingClientRect();var offset=Math.min(clientRect.width,clientRect.height);var moveSpeedRatio=.05;var dx=offset*moveSpeedRatio*x;var dy=offset*moveSpeedRatio*y;internalMoveBy(dx,dy)}if(z){var scaleMultiplier=getScaleMultiplier(z*100);var offset=transformOrigin?getTransformOriginOffset():midPoint();publicZoomTo(offset.x,offset.y,scaleMultiplier)}}function midPoint(){var ownerRect=owner.getBoundingClientRect();return{x:ownerRect.width/2,y:ownerRect.height/2}}function onTouch(e){beforeTouch(e);if(e.touches.length===1){return handleSingleFingerTouch(e,e.touches[0])}else if(e.touches.length===2){pinchZoomLength=getPinchZoomLength(e.touches[0],e.touches[1]);multiTouch=true;startTouchListenerIfNeeded()}}function beforeTouch(e){if(options.onTouch&&!options.onTouch(e)){return}e.stopPropagation();e.preventDefault()}function beforeDoubleClick(e){if(options.onDoubleClick&&!options.onDoubleClick(e)){return}e.preventDefault();e.stopPropagation()}function handleSingleFingerTouch(e){var touch=e.touches[0];var offset=getOffsetXY(touch);lastSingleFingerOffset=offset;var point=transformToScreen(offset.x,offset.y);mouseX=point.x;mouseY=point.y;smoothScroll.cancel();startTouchListenerIfNeeded()}function startTouchListenerIfNeeded(){if(touchInProgress){return}touchInProgress=true;document.addEventListener("touchmove",handleTouchMove);document.addEventListener("touchend",handleTouchEnd);document.addEventListener("touchcancel",handleTouchEnd)}function handleTouchMove(e){if(e.touches.length===1){e.stopPropagation();var touch=e.touches[0];var offset=getOffsetXY(touch);var point=transformToScreen(offset.x,offset.y);var dx=point.x-mouseX;var dy=point.y-mouseY;if(dx!==0&&dy!==0){triggerPanStart()}mouseX=point.x;mouseY=point.y;internalMoveBy(dx,dy)}else if(e.touches.length===2){multiTouch=true;var t1=e.touches[0];var t2=e.touches[1];var currentPinchLength=getPinchZoomLength(t1,t2);var scaleMultiplier=1+(currentPinchLength/pinchZoomLength-1)*pinchSpeed;var firstTouchPoint=getOffsetXY(t1);var secondTouchPoint=getOffsetXY(t2);mouseX=(firstTouchPoint.x+secondTouchPoint.x)/2;mouseY=(firstTouchPoint.y+secondTouchPoint.y)/2;if(transformOrigin){var offset=getTransformOriginOffset();mouseX=offset.x;mouseY=offset.y}publicZoomTo(mouseX,mouseY,scaleMultiplier);pinchZoomLength=currentPinchLength;e.stopPropagation();e.preventDefault()}}function handleTouchEnd(e){if(e.touches.length>0){var offset=getOffsetXY(e.touches[0]);var point=transformToScreen(offset.x,offset.y);mouseX=point.x;mouseY=point.y}else{var now=new Date;if(now-lastTouchEndTime0)delta*=100;var scaleMultiplier=getScaleMultiplier(delta);if(scaleMultiplier!==1){var offset=transformOrigin?getTransformOriginOffset():getOffsetXY(e);publicZoomTo(offset.x,offset.y,scaleMultiplier);e.preventDefault()}}function getOffsetXY(e){var offsetX,offsetY;var ownerRect=owner.getBoundingClientRect();offsetX=e.clientX-ownerRect.left;offsetY=e.clientY-ownerRect.top;return{x:offsetX,y:offsetY}}function smoothZoom(clientX,clientY,scaleMultiplier){var fromValue=transform.scale;var from={scale:fromValue};var to={scale:scaleMultiplier*fromValue};smoothScroll.cancel();cancelZoomAnimation();zoomToAnimation=animate(from,to,{step:function(v){zoomAbs(clientX,clientY,v.scale)},done:triggerZoomEnd})}function smoothZoomAbs(clientX,clientY,toScaleValue){var fromValue=transform.scale;var from={scale:fromValue};var to={scale:toScaleValue};smoothScroll.cancel();cancelZoomAnimation();zoomToAnimation=animate(from,to,{step:function(v){zoomAbs(clientX,clientY,v.scale)}})}function getTransformOriginOffset(){var ownerRect=owner.getBoundingClientRect();return{x:ownerRect.width*transformOrigin.x,y:ownerRect.height*transformOrigin.y}}function publicZoomTo(clientX,clientY,scaleMultiplier){smoothScroll.cancel();cancelZoomAnimation();return zoomByRatio(clientX,clientY,scaleMultiplier)}function cancelZoomAnimation(){if(zoomToAnimation){zoomToAnimation.cancel();zoomToAnimation=null}}function getScaleMultiplier(delta){var sign=Math.sign(delta);var deltaAdjustedSpeed=Math.min(.25,Math.abs(speed*delta/128));return 1-sign*deltaAdjustedSpeed}function triggerPanStart(){if(!panstartFired){triggerEvent("panstart");panstartFired=true;smoothScroll.start()}}function triggerPanEnd(){if(panstartFired){if(!multiTouch)smoothScroll.stop();triggerEvent("panend")}}function triggerZoomEnd(){triggerEvent("zoomend")}function triggerEvent(name){api.fire(name,api)}}function parseTransformOrigin(options){if(!options)return;if(typeof options==="object"){if(!isNumber(options.x)||!isNumber(options.y))failTransformOrigin(options);return options}failTransformOrigin()}function failTransformOrigin(options){console.error(options);throw new Error(["Cannot parse transform origin.","Some good examples:",' "center center" can be achieved with {x: 0.5, y: 0.5}',' "top center" can be achieved with {x: 0.5, y: 0}',' "bottom right" can be achieved with {x: 1, y: 1}'].join("\n"))}function noop(){}function validateBounds(bounds){var boundsType=typeof bounds;if(boundsType==="undefined"||boundsType==="boolean")return;var validBounds=isNumber(bounds.left)&&isNumber(bounds.top)&&isNumber(bounds.bottom)&&isNumber(bounds.right);if(!validBounds)throw new Error("Bounds object is not valid. It can be: "+"undefined, boolean (true|false) or an object {left, top, right, bottom}")}function isNumber(x){return Number.isFinite(x)}function isNaN(value){if(Number.isNaN){return Number.isNaN(value)}return value!==value}function rigidScroll(){return{start:noop,stop:noop,cancel:noop}}function autoRun(){if(typeof document==="undefined")return;var scripts=document.getElementsByTagName("script");if(!scripts)return;var panzoomScript;for(var i=0;iminVelocity){ax=amplitude*vx;targetX+=ax}if(vy<-minVelocity||vy>minVelocity){ay=amplitude*vy;targetY+=ay}raf=requestAnimationFrame(autoScroll)}function autoScroll(){var elapsed=Date.now()-timestamp;var moving=false;var dx=0;var dy=0;if(ax){dx=-ax*Math.exp(-elapsed/timeConstant);if(dx>.5||dx<-.5)moving=true;else dx=ax=0}if(ay){dy=-ay*Math.exp(-elapsed/timeConstant);if(dy>.5||dy<-.5)moving=true;else dy=ay=0}if(moving){scroll(targetX+dx,targetY+dy);raf=requestAnimationFrame(autoScroll)}}}function getCancelAnimationFrame(){if(typeof cancelAnimationFrame==="function")return cancelAnimationFrame;return clearTimeout}function getRequestAnimationFrame(){if(typeof requestAnimationFrame==="function")return requestAnimationFrame;return function(handler){return setTimeout(handler,16)}}},{}],5:[function(require,module,exports){module.exports=makeSvgController;module.exports.canAttach=isSVGElement;function makeSvgController(svgElement,options){if(!isSVGElement(svgElement)){throw new Error("svg element is required for svg.panzoom to work")}var owner=svgElement.ownerSVGElement;if(!owner){throw new Error("Do not apply panzoom to the root element. "+"Use its child instead (e.g. ). "+"As of March 2016 only FireFox supported transform on the root element")}if(!options.disableKeyboardInteraction){owner.setAttribute("tabindex",0)}var api={getBBox:getBBox,getScreenCTM:getScreenCTM,getOwner:getOwner,applyTransform:applyTransform,initTransform:initTransform};return api;function getOwner(){return owner}function getBBox(){var bbox=svgElement.getBBox();return{left:bbox.x,top:bbox.y,width:bbox.width,height:bbox.height}}function getScreenCTM(){var ctm=owner.getCTM();if(!ctm){return owner.getScreenCTM()}return ctm}function initTransform(transform){var screenCTM=svgElement.getCTM();if(screenCTM===null){screenCTM=document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGMatrix()}transform.x=screenCTM.e;transform.y=screenCTM.f;transform.scale=screenCTM.a;owner.removeAttributeNS(null,"viewBox")}function applyTransform(transform){svgElement.setAttribute("transform","matrix("+transform.scale+" 0 0 "+transform.scale+" "+transform.x+" "+transform.y+")")}}function isSVGElement(element){return element&&element.ownerSVGElement&&element.getCTM}},{}],6:[function(require,module,exports){module.exports=Transform;function Transform(){this.x=0;this.y=0;this.scale=1}},{}],7:[function(require,module,exports){var BezierEasing=require("bezier-easing");var animations={ease:BezierEasing(.25,.1,.25,1),easeIn:BezierEasing(.42,0,1,1),easeOut:BezierEasing(0,0,.58,1),easeInOut:BezierEasing(.42,0,.58,1),linear:BezierEasing(0,0,1,1)};module.exports=animate;module.exports.makeAggregateRaf=makeAggregateRaf;module.exports.sharedScheduler=makeAggregateRaf();function animate(source,target,options){var start=Object.create(null);var diff=Object.create(null);options=options||{};var easing=typeof options.easing==="function"?options.easing:animations[options.easing];if(!easing){if(options.easing){console.warn("Unknown easing function in amator: "+options.easing)}easing=animations.ease}var step=typeof options.step==="function"?options.step:noop;var done=typeof options.done==="function"?options.done:noop;var scheduler=getScheduler(options.scheduler);var keys=Object.keys(target);keys.forEach(function(key){start[key]=source[key];diff[key]=target[key]-source[key]});var durationInMs=typeof options.duration==="number"?options.duration:400;var durationInFrames=Math.max(1,durationInMs*.06);var previousAnimationId;var frame=0;previousAnimationId=scheduler.next(loop);return{cancel:cancel};function cancel(){scheduler.cancel(previousAnimationId);previousAnimationId=0}function loop(){var t=easing(frame/durationInFrames);frame+=1;setValues(t);if(frame<=durationInFrames){previousAnimationId=scheduler.next(loop);step(source)}else{previousAnimationId=0;setTimeout(function(){done(source)},0)}}function setValues(t){keys.forEach(function(key){source[key]=diff[key]*t+start[key]})}}function noop(){}function getScheduler(scheduler){if(!scheduler){var canRaf=typeof window!=="undefined"&&window.requestAnimationFrame;return canRaf?rafScheduler():timeoutScheduler()}if(typeof scheduler.next!=="function")throw new Error("Scheduler is supposed to have next(cb) function");if(typeof scheduler.cancel!=="function")throw new Error("Scheduler is supposed to have cancel(handle) function");return scheduler}function rafScheduler(){return{next:window.requestAnimationFrame.bind(window),cancel:window.cancelAnimationFrame.bind(window)}}function timeoutScheduler(){return{next:function(cb){return setTimeout(cb,1e3/60)},cancel:function(id){return clearTimeout(id)}}}function makeAggregateRaf(){var frontBuffer=new Set;var backBuffer=new Set;var frameToken=0;return{next:next,cancel:next,clearAll:clearAll};function clearAll(){frontBuffer.clear();backBuffer.clear();cancelAnimationFrame(frameToken);frameToken=0}function next(callback){backBuffer.add(callback);renderNextFrame()}function renderNextFrame(){if(!frameToken)frameToken=requestAnimationFrame(renderFrame)}function renderFrame(){frameToken=0;var t=backBuffer;backBuffer=frontBuffer;frontBuffer=t;frontBuffer.forEach(function(callback){callback()});frontBuffer.clear()}function cancel(callback){backBuffer.delete(callback)}}},{"bezier-easing":8}],8:[function(require,module,exports){var NEWTON_ITERATIONS=4;var NEWTON_MIN_SLOPE=.001;var SUBDIVISION_PRECISION=1e-7;var SUBDIVISION_MAX_ITERATIONS=10;var kSplineTableSize=11;var kSampleStepSize=1/(kSplineTableSize-1);var float32ArraySupported=typeof Float32Array==="function";function A(aA1,aA2){return 1-3*aA2+3*aA1}function B(aA1,aA2){return 3*aA2-6*aA1}function C(aA1){return 3*aA1}function calcBezier(aT,aA1,aA2){return((A(aA1,aA2)*aT+B(aA1,aA2))*aT+C(aA1))*aT}function getSlope(aT,aA1,aA2){return 3*A(aA1,aA2)*aT*aT+2*B(aA1,aA2)*aT+C(aA1)}function binarySubdivide(aX,aA,aB,mX1,mX2){var currentX,currentT,i=0;do{currentT=aA+(aB-aA)/2;currentX=calcBezier(currentT,mX1,mX2)-aX;if(currentX>0){aB=currentT}else{aA=currentT}}while(Math.abs(currentX)>SUBDIVISION_PRECISION&&++i=NEWTON_MIN_SLOPE){return newtonRaphsonIterate(aX,guessForT,mX1,mX2)}else if(initialSlope===0){return guessForT}else{return binarySubdivide(aX,intervalStart,intervalStart+kSampleStepSize,mX1,mX2)}}return function BezierEasing(x){if(x===0){return 0}if(x===1){return 1}return calcBezier(getTForX(x),mY1,mY2)}}},{}],9:[function(require,module,exports){module.exports=function eventify(subject){validateSubject(subject);var eventsStorage=createEventsStorage(subject);subject.on=eventsStorage.on;subject.off=eventsStorage.off;subject.fire=eventsStorage.fire;return subject};function createEventsStorage(subject){var registeredEvents=Object.create(null);return{on:function(eventName,callback,ctx){if(typeof callback!=="function"){throw new Error("callback is expected to be a function")}var handlers=registeredEvents[eventName];if(!handlers){handlers=registeredEvents[eventName]=[]}handlers.push({callback:callback,ctx:ctx});return subject},off:function(eventName,callback){var wantToRemoveAll=typeof eventName==="undefined";if(wantToRemoveAll){registeredEvents=Object.create(null);return subject}if(registeredEvents[eventName]){var deleteAllCallbacksForEvent=typeof callback!=="function";if(deleteAllCallbacksForEvent){delete registeredEvents[eventName]}else{var callbacks=registeredEvents[eventName];for(var i=0;i1){fireArguments=Array.prototype.splice.call(arguments,1)}for(var i=0;i CesiumUtility[CesiumUtility] + class CesiumUtility,Cesium3DTiles libraryNode diff --git a/doc/diagrams/dependencies/Cesium3DTilesContent.mmd b/doc/diagrams/dependencies/Cesium3DTilesContent.mmd new file mode 100644 index 000000000..6456574e3 --- /dev/null +++ b/doc/diagrams/dependencies/Cesium3DTilesContent.mmd @@ -0,0 +1,20 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: Cesium3DTilesContent Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + Cesium3DTilesContent[Cesium3DTilesContent] --> Cesium3DTiles[Cesium3DTiles] + Cesium3DTilesContent[Cesium3DTilesContent] --> Cesium3DTilesReader[Cesium3DTilesReader] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumAsync[CesiumAsync] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumGeometry[CesiumGeometry] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumGeospatial[CesiumGeospatial] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumGltf[CesiumGltf] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumGltfContent[CesiumGltfContent] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumGltfReader[CesiumGltfReader] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumUtility[CesiumUtility] + Cesium3DTilesContent[Cesium3DTilesContent] --> libmorton_libmorton{{libmorton::libmorton}} + class libmorton_libmorton dependencyNode + class Cesium3DTiles,Cesium3DTilesReader,CesiumAsync,CesiumGeometry,CesiumGeospatial,CesiumGltf,CesiumGltfContent,CesiumGltfReader,CesiumUtility,Cesium3DTilesContent libraryNode diff --git a/doc/diagrams/dependencies/Cesium3DTilesReader.mmd b/doc/diagrams/dependencies/Cesium3DTilesReader.mmd new file mode 100644 index 000000000..07759cd76 --- /dev/null +++ b/doc/diagrams/dependencies/Cesium3DTilesReader.mmd @@ -0,0 +1,12 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: Cesium3DTilesReader Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + Cesium3DTilesReader[Cesium3DTilesReader] --> Cesium3DTiles[Cesium3DTiles] + Cesium3DTilesReader[Cesium3DTilesReader] --> CesiumAsync[CesiumAsync] + Cesium3DTilesReader[Cesium3DTilesReader] --> CesiumJsonReader[CesiumJsonReader] + class Cesium3DTiles,CesiumAsync,CesiumJsonReader,Cesium3DTilesReader libraryNode diff --git a/doc/diagrams/dependencies/Cesium3DTilesSelection.mmd b/doc/diagrams/dependencies/Cesium3DTilesSelection.mmd new file mode 100644 index 000000000..08bf7d913 --- /dev/null +++ b/doc/diagrams/dependencies/Cesium3DTilesSelection.mmd @@ -0,0 +1,28 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: Cesium3DTilesSelection Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + Cesium3DTilesSelection[Cesium3DTilesSelection] --> Cesium3DTiles[Cesium3DTiles] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> Cesium3DTilesContent[Cesium3DTilesContent] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> Cesium3DTilesReader[Cesium3DTilesReader] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumAsync[CesiumAsync] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumGeometry[CesiumGeometry] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumGeospatial[CesiumGeospatial] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumGltf[CesiumGltf] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumGltfReader[CesiumGltfReader] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumRasterOverlays[CesiumRasterOverlays] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumUtility[CesiumUtility] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> draco_draco{{draco::draco}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> libmorton_libmorton{{libmorton::libmorton}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> nonstd_expected-lite{{nonstd::expected-lite}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> spdlog_spdlog{{spdlog::spdlog}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> spdlog_spdlog_header_only{{spdlog::spdlog_header_only}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> tinyxml2_tinyxml2{{tinyxml2::tinyxml2}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> uriparser_uriparser{{uriparser::uriparser}} + class draco_draco,libmorton_libmorton,nonstd_expected-lite,spdlog_spdlog,spdlog_spdlog_header_only,tinyxml2_tinyxml2,uriparser_uriparser dependencyNode + class Cesium3DTiles,Cesium3DTilesContent,Cesium3DTilesReader,CesiumAsync,CesiumGeometry,CesiumGeospatial,CesiumGltf,CesiumGltfReader,CesiumQuantizedMeshTerrain,CesiumRasterOverlays,CesiumUtility,Cesium3DTilesSelection libraryNode diff --git a/doc/diagrams/dependencies/Cesium3DTilesWriter.mmd b/doc/diagrams/dependencies/Cesium3DTilesWriter.mmd new file mode 100644 index 000000000..5848765e0 --- /dev/null +++ b/doc/diagrams/dependencies/Cesium3DTilesWriter.mmd @@ -0,0 +1,11 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: Cesium3DTilesWriter Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + Cesium3DTilesWriter[Cesium3DTilesWriter] --> Cesium3DTiles[Cesium3DTiles] + Cesium3DTilesWriter[Cesium3DTilesWriter] --> CesiumJsonWriter[CesiumJsonWriter] + class Cesium3DTiles,CesiumJsonWriter,Cesium3DTilesWriter libraryNode diff --git a/doc/diagrams/dependencies/CesiumAsync.mmd b/doc/diagrams/dependencies/CesiumAsync.mmd new file mode 100644 index 000000000..114093249 --- /dev/null +++ b/doc/diagrams/dependencies/CesiumAsync.mmd @@ -0,0 +1,15 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumAsync Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumAsync[CesiumAsync] --> Async_{{Async++}} + CesiumAsync[CesiumAsync] --> CesiumUtility[CesiumUtility] + CesiumAsync[CesiumAsync] --> spdlog_spdlog{{spdlog::spdlog}} + CesiumAsync[CesiumAsync] --> spdlog_spdlog_header_only{{spdlog::spdlog_header_only}} + CesiumAsync[CesiumAsync] --> unofficial_sqlite3_sqlite3{{unofficial::sqlite3::sqlite3}} + class Async_,spdlog_spdlog,spdlog_spdlog_header_only,unofficial_sqlite3_sqlite3 dependencyNode + class CesiumUtility,CesiumAsync libraryNode diff --git a/doc/diagrams/dependencies/CesiumGeometry.mmd b/doc/diagrams/dependencies/CesiumGeometry.mmd new file mode 100644 index 000000000..360199b65 --- /dev/null +++ b/doc/diagrams/dependencies/CesiumGeometry.mmd @@ -0,0 +1,10 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumGeometry Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumGeometry[CesiumGeometry] --> CesiumUtility[CesiumUtility] + class CesiumUtility,CesiumGeometry libraryNode diff --git a/doc/diagrams/dependencies/CesiumGeospatial.mmd b/doc/diagrams/dependencies/CesiumGeospatial.mmd new file mode 100644 index 000000000..d74ead9b9 --- /dev/null +++ b/doc/diagrams/dependencies/CesiumGeospatial.mmd @@ -0,0 +1,14 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumGeospatial Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumGeospatial[CesiumGeospatial] --> CesiumGeometry[CesiumGeometry] + CesiumGeospatial[CesiumGeospatial] --> CesiumUtility[CesiumUtility] + CesiumGeospatial[CesiumGeospatial] --> earcut{{earcut}} + CesiumGeospatial[CesiumGeospatial] --> s2_s2{{s2::s2}} + class earcut,s2_s2 dependencyNode + class CesiumGeometry,CesiumUtility,CesiumGeospatial libraryNode diff --git a/doc/diagrams/dependencies/CesiumGltf.mmd b/doc/diagrams/dependencies/CesiumGltf.mmd new file mode 100644 index 000000000..a5f7215cc --- /dev/null +++ b/doc/diagrams/dependencies/CesiumGltf.mmd @@ -0,0 +1,10 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumGltf Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumGltf[CesiumGltf] --> CesiumUtility[CesiumUtility] + class CesiumUtility,CesiumGltf libraryNode diff --git a/doc/diagrams/dependencies/CesiumGltfContent.mmd b/doc/diagrams/dependencies/CesiumGltfContent.mmd new file mode 100644 index 000000000..72a6586f8 --- /dev/null +++ b/doc/diagrams/dependencies/CesiumGltfContent.mmd @@ -0,0 +1,15 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumGltfContent Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumGltfContent[CesiumGltfContent] --> CesiumAsync[CesiumAsync] + CesiumGltfContent[CesiumGltfContent] --> CesiumGeometry[CesiumGeometry] + CesiumGltfContent[CesiumGltfContent] --> CesiumGeospatial[CesiumGeospatial] + CesiumGltfContent[CesiumGltfContent] --> CesiumGltf[CesiumGltf] + CesiumGltfContent[CesiumGltfContent] --> CesiumGltfReader[CesiumGltfReader] + CesiumGltfContent[CesiumGltfContent] --> CesiumUtility[CesiumUtility] + class CesiumAsync,CesiumGeometry,CesiumGeospatial,CesiumGltf,CesiumGltfReader,CesiumUtility,CesiumGltfContent libraryNode diff --git a/doc/diagrams/dependencies/CesiumGltfReader.mmd b/doc/diagrams/dependencies/CesiumGltfReader.mmd new file mode 100644 index 000000000..6d593bb09 --- /dev/null +++ b/doc/diagrams/dependencies/CesiumGltfReader.mmd @@ -0,0 +1,20 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumGltfReader Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumGltfReader[CesiumGltfReader] --> CesiumAsync[CesiumAsync] + CesiumGltfReader[CesiumGltfReader] --> CesiumGltf[CesiumGltf] + CesiumGltfReader[CesiumGltfReader] --> CesiumJsonReader[CesiumJsonReader] + CesiumGltfReader[CesiumGltfReader] --> KTX_ktx{{KTX::ktx}} + CesiumGltfReader[CesiumGltfReader] --> WebP_webp{{WebP::webp}} + CesiumGltfReader[CesiumGltfReader] --> WebP_webpdecoder{{WebP::webpdecoder}} + CesiumGltfReader[CesiumGltfReader] --> draco_draco{{draco::draco}} + CesiumGltfReader[CesiumGltfReader] --> libjpeg-turbo_turbojpeg-static{{libjpeg-turbo::turbojpeg-static}} + CesiumGltfReader[CesiumGltfReader] --> meshoptimizer_meshoptimizer{{meshoptimizer::meshoptimizer}} + CesiumGltfReader[CesiumGltfReader] --> modp_b64_modp_b64{{modp_b64::modp_b64}} + class KTX_ktx,WebP_webp,WebP_webpdecoder,draco_draco,libjpeg-turbo_turbojpeg-static,meshoptimizer_meshoptimizer,modp_b64_modp_b64 dependencyNode + class CesiumAsync,CesiumGltf,CesiumJsonReader,CesiumGltfReader libraryNode diff --git a/doc/diagrams/dependencies/CesiumGltfWriter.mmd b/doc/diagrams/dependencies/CesiumGltfWriter.mmd new file mode 100644 index 000000000..163c78a23 --- /dev/null +++ b/doc/diagrams/dependencies/CesiumGltfWriter.mmd @@ -0,0 +1,13 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumGltfWriter Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumGltfWriter[CesiumGltfWriter] --> CesiumGltf[CesiumGltf] + CesiumGltfWriter[CesiumGltfWriter] --> CesiumJsonWriter[CesiumJsonWriter] + CesiumGltfWriter[CesiumGltfWriter] --> modp_b64_modp_b64{{modp_b64::modp_b64}} + class modp_b64_modp_b64 dependencyNode + class CesiumGltf,CesiumJsonWriter,CesiumGltfWriter libraryNode diff --git a/doc/diagrams/dependencies/CesiumIonClient.mmd b/doc/diagrams/dependencies/CesiumIonClient.mmd new file mode 100644 index 000000000..3eef3068a --- /dev/null +++ b/doc/diagrams/dependencies/CesiumIonClient.mmd @@ -0,0 +1,16 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumIonClient Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumIonClient[CesiumIonClient] --> CesiumAsync[CesiumAsync] + CesiumIonClient[CesiumIonClient] --> CesiumUtility[CesiumUtility] + CesiumIonClient[CesiumIonClient] --> OpenSSL_Crypto{{OpenSSL::Crypto}} + CesiumIonClient[CesiumIonClient] --> httplib_httplib{{httplib::httplib}} + CesiumIonClient[CesiumIonClient] --> modp_b64_modp_b64{{modp_b64::modp_b64}} + CesiumIonClient[CesiumIonClient] --> picosha2_picosha2{{picosha2::picosha2}} + class OpenSSL_Crypto,httplib_httplib,modp_b64_modp_b64,picosha2_picosha2 dependencyNode + class CesiumAsync,CesiumUtility,CesiumIonClient libraryNode diff --git a/doc/diagrams/dependencies/CesiumJsonReader.mmd b/doc/diagrams/dependencies/CesiumJsonReader.mmd new file mode 100644 index 000000000..e15fa4f6b --- /dev/null +++ b/doc/diagrams/dependencies/CesiumJsonReader.mmd @@ -0,0 +1,10 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumJsonReader Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumJsonReader[CesiumJsonReader] --> CesiumUtility[CesiumUtility] + class CesiumUtility,CesiumJsonReader libraryNode diff --git a/doc/diagrams/dependencies/CesiumJsonWriter.mmd b/doc/diagrams/dependencies/CesiumJsonWriter.mmd new file mode 100644 index 000000000..97447577e --- /dev/null +++ b/doc/diagrams/dependencies/CesiumJsonWriter.mmd @@ -0,0 +1,10 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumJsonWriter Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumJsonWriter[CesiumJsonWriter] --> CesiumUtility[CesiumUtility] + class CesiumUtility,CesiumJsonWriter libraryNode diff --git a/doc/diagrams/dependencies/CesiumQuantizedMeshTerrain.mmd b/doc/diagrams/dependencies/CesiumQuantizedMeshTerrain.mmd new file mode 100644 index 000000000..52581a688 --- /dev/null +++ b/doc/diagrams/dependencies/CesiumQuantizedMeshTerrain.mmd @@ -0,0 +1,16 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumQuantizedMeshTerrain Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumAsync[CesiumAsync] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumGeospatial[CesiumGeospatial] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumGltf[CesiumGltf] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumGltfContent[CesiumGltfContent] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumJsonReader[CesiumJsonReader] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumJsonWriter[CesiumJsonWriter] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumUtility[CesiumUtility] + class CesiumAsync,CesiumGeospatial,CesiumGltf,CesiumGltfContent,CesiumJsonReader,CesiumJsonWriter,CesiumUtility,CesiumQuantizedMeshTerrain libraryNode diff --git a/doc/diagrams/dependencies/CesiumRasterOverlays.mmd b/doc/diagrams/dependencies/CesiumRasterOverlays.mmd new file mode 100644 index 000000000..10e7477d8 --- /dev/null +++ b/doc/diagrams/dependencies/CesiumRasterOverlays.mmd @@ -0,0 +1,19 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumRasterOverlays Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumAsync[CesiumAsync] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumGeometry[CesiumGeometry] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumGeospatial[CesiumGeospatial] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumGltf[CesiumGltf] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumGltfContent[CesiumGltfContent] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumGltfReader[CesiumGltfReader] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumUtility[CesiumUtility] + CesiumRasterOverlays[CesiumRasterOverlays] --> nonstd_expected-lite{{nonstd::expected-lite}} + CesiumRasterOverlays[CesiumRasterOverlays] --> tinyxml2_tinyxml2{{tinyxml2::tinyxml2}} + class nonstd_expected-lite,tinyxml2_tinyxml2 dependencyNode + class CesiumAsync,CesiumGeometry,CesiumGeospatial,CesiumGltf,CesiumGltfContent,CesiumGltfReader,CesiumUtility,CesiumRasterOverlays libraryNode diff --git a/doc/diagrams/dependencies/CesiumUtility.mmd b/doc/diagrams/dependencies/CesiumUtility.mmd new file mode 100644 index 000000000..4b13dfd72 --- /dev/null +++ b/doc/diagrams/dependencies/CesiumUtility.mmd @@ -0,0 +1,14 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! + +title: CesiumUtility Dependency Graph +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumUtility[CesiumUtility] --> glm_glm{{glm::glm}} + CesiumUtility[CesiumUtility] --> spdlog_spdlog{{spdlog::spdlog}} + CesiumUtility[CesiumUtility] --> uriparser_uriparser{{uriparser::uriparser}} + CesiumUtility[CesiumUtility] --> zlib-ng_zlib-ng{{zlib-ng::zlib-ng}} + class glm_glm,spdlog_spdlog,uriparser_uriparser,zlib-ng_zlib-ng dependencyNode + class CesiumUtility libraryNode diff --git a/doc/diagrams/dependencies/all.mmd b/doc/diagrams/dependencies/all.mmd new file mode 100644 index 000000000..339f85764 --- /dev/null +++ b/doc/diagrams/dependencies/all.mmd @@ -0,0 +1,139 @@ +--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! +config: + layout: elk + +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px + CesiumUtility[CesiumUtility] --> glm_glm{{glm::glm}} + CesiumUtility[CesiumUtility] --> spdlog_spdlog{{spdlog::spdlog}} + CesiumUtility[CesiumUtility] --> uriparser_uriparser{{uriparser::uriparser}} + CesiumUtility[CesiumUtility] --> zlib-ng_zlib-ng{{zlib-ng::zlib-ng}} + Cesium3DTiles[Cesium3DTiles] --> CesiumUtility[CesiumUtility] + Cesium3DTilesContent[Cesium3DTilesContent] --> Cesium3DTiles[Cesium3DTiles] + Cesium3DTilesContent[Cesium3DTilesContent] --> Cesium3DTilesReader[Cesium3DTilesReader] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumAsync[CesiumAsync] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumGeometry[CesiumGeometry] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumGeospatial[CesiumGeospatial] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumGltf[CesiumGltf] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumGltfContent[CesiumGltfContent] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumGltfReader[CesiumGltfReader] + Cesium3DTilesContent[Cesium3DTilesContent] --> CesiumUtility[CesiumUtility] + Cesium3DTilesContent[Cesium3DTilesContent] --> libmorton_libmorton{{libmorton::libmorton}} + Cesium3DTilesReader[Cesium3DTilesReader] --> Cesium3DTiles[Cesium3DTiles] + Cesium3DTilesReader[Cesium3DTilesReader] --> CesiumAsync[CesiumAsync] + Cesium3DTilesReader[Cesium3DTilesReader] --> CesiumJsonReader[CesiumJsonReader] + CesiumAsync[CesiumAsync] --> Async_{{Async++}} + CesiumAsync[CesiumAsync] --> CesiumUtility[CesiumUtility] + CesiumAsync[CesiumAsync] --> spdlog_spdlog{{spdlog::spdlog}} + CesiumAsync[CesiumAsync] --> spdlog_spdlog_header_only{{spdlog::spdlog_header_only}} + CesiumAsync[CesiumAsync] --> unofficial_sqlite3_sqlite3{{unofficial::sqlite3::sqlite3}} + CesiumJsonReader[CesiumJsonReader] --> CesiumUtility[CesiumUtility] + CesiumGeometry[CesiumGeometry] --> CesiumUtility[CesiumUtility] + CesiumGeospatial[CesiumGeospatial] --> CesiumGeometry[CesiumGeometry] + CesiumGeospatial[CesiumGeospatial] --> CesiumUtility[CesiumUtility] + CesiumGeospatial[CesiumGeospatial] --> earcut{{earcut}} + CesiumGeospatial[CesiumGeospatial] --> s2_s2{{s2::s2}} + CesiumGltf[CesiumGltf] --> CesiumUtility[CesiumUtility] + CesiumGltfContent[CesiumGltfContent] --> CesiumAsync[CesiumAsync] + CesiumGltfContent[CesiumGltfContent] --> CesiumGeometry[CesiumGeometry] + CesiumGltfContent[CesiumGltfContent] --> CesiumGeospatial[CesiumGeospatial] + CesiumGltfContent[CesiumGltfContent] --> CesiumGltf[CesiumGltf] + CesiumGltfContent[CesiumGltfContent] --> CesiumGltfReader[CesiumGltfReader] + CesiumGltfContent[CesiumGltfContent] --> CesiumUtility[CesiumUtility] + CesiumGltfReader[CesiumGltfReader] --> CesiumAsync[CesiumAsync] + CesiumGltfReader[CesiumGltfReader] --> CesiumGltf[CesiumGltf] + CesiumGltfReader[CesiumGltfReader] --> CesiumJsonReader[CesiumJsonReader] + CesiumGltfReader[CesiumGltfReader] --> KTX_ktx{{KTX::ktx}} + CesiumGltfReader[CesiumGltfReader] --> WebP_webp{{WebP::webp}} + CesiumGltfReader[CesiumGltfReader] --> WebP_webpdecoder{{WebP::webpdecoder}} + CesiumGltfReader[CesiumGltfReader] --> draco_draco{{draco::draco}} + CesiumGltfReader[CesiumGltfReader] --> libjpeg-turbo_turbojpeg-static{{libjpeg-turbo::turbojpeg-static}} + CesiumGltfReader[CesiumGltfReader] --> meshoptimizer_meshoptimizer{{meshoptimizer::meshoptimizer}} + CesiumGltfReader[CesiumGltfReader] --> modp_b64_modp_b64{{modp_b64::modp_b64}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> Cesium3DTiles[Cesium3DTiles] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> Cesium3DTilesContent[Cesium3DTilesContent] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> Cesium3DTilesReader[Cesium3DTilesReader] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumAsync[CesiumAsync] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumGeometry[CesiumGeometry] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumGeospatial[CesiumGeospatial] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumGltf[CesiumGltf] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumGltfReader[CesiumGltfReader] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumRasterOverlays[CesiumRasterOverlays] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> CesiumUtility[CesiumUtility] + Cesium3DTilesSelection[Cesium3DTilesSelection] --> draco_draco{{draco::draco}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> libmorton_libmorton{{libmorton::libmorton}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> nonstd_expected-lite{{nonstd::expected-lite}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> spdlog_spdlog{{spdlog::spdlog}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> spdlog_spdlog_header_only{{spdlog::spdlog_header_only}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> tinyxml2_tinyxml2{{tinyxml2::tinyxml2}} + Cesium3DTilesSelection[Cesium3DTilesSelection] --> uriparser_uriparser{{uriparser::uriparser}} + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumAsync[CesiumAsync] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumGeospatial[CesiumGeospatial] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumGltf[CesiumGltf] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumGltfContent[CesiumGltfContent] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumJsonReader[CesiumJsonReader] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumJsonWriter[CesiumJsonWriter] + CesiumQuantizedMeshTerrain[CesiumQuantizedMeshTerrain] --> CesiumUtility[CesiumUtility] + CesiumJsonWriter[CesiumJsonWriter] --> CesiumUtility[CesiumUtility] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumAsync[CesiumAsync] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumGeometry[CesiumGeometry] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumGeospatial[CesiumGeospatial] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumGltf[CesiumGltf] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumGltfContent[CesiumGltfContent] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumGltfReader[CesiumGltfReader] + CesiumRasterOverlays[CesiumRasterOverlays] --> CesiumUtility[CesiumUtility] + CesiumRasterOverlays[CesiumRasterOverlays] --> nonstd_expected-lite{{nonstd::expected-lite}} + CesiumRasterOverlays[CesiumRasterOverlays] --> tinyxml2_tinyxml2{{tinyxml2::tinyxml2}} + Cesium3DTilesWriter[Cesium3DTilesWriter] --> Cesium3DTiles[Cesium3DTiles] + Cesium3DTilesWriter[Cesium3DTilesWriter] --> CesiumJsonWriter[CesiumJsonWriter] + CesiumGltfWriter[CesiumGltfWriter] --> CesiumGltf[CesiumGltf] + CesiumGltfWriter[CesiumGltfWriter] --> CesiumJsonWriter[CesiumJsonWriter] + CesiumGltfWriter[CesiumGltfWriter] --> modp_b64_modp_b64{{modp_b64::modp_b64}} + CesiumIonClient[CesiumIonClient] --> CesiumAsync[CesiumAsync] + CesiumIonClient[CesiumIonClient] --> CesiumUtility[CesiumUtility] + CesiumIonClient[CesiumIonClient] --> OpenSSL_Crypto{{OpenSSL::Crypto}} + CesiumIonClient[CesiumIonClient] --> httplib_httplib{{httplib::httplib}} + CesiumIonClient[CesiumIonClient] --> modp_b64_modp_b64{{modp_b64::modp_b64}} + CesiumIonClient[CesiumIonClient] --> picosha2_picosha2{{picosha2::picosha2}} + class glm_glm,spdlog_spdlog,uriparser_uriparser,zlib-ng_zlib-ng,libmorton_libmorton,Async_,spdlog_spdlog_header_only,unofficial_sqlite3_sqlite3,earcut,s2_s2,KTX_ktx,WebP_webp,WebP_webpdecoder,draco_draco,libjpeg-turbo_turbojpeg-static,meshoptimizer_meshoptimizer,modp_b64_modp_b64,nonstd_expected-lite,tinyxml2_tinyxml2,OpenSSL_Crypto,httplib_httplib,picosha2_picosha2 dependencyNode + class CesiumUtility,Cesium3DTiles,Cesium3DTilesReader,CesiumAsync,CesiumGeometry,CesiumGeospatial,CesiumGltf,CesiumGltfContent,CesiumGltfReader,Cesium3DTilesContent,CesiumJsonReader,CesiumQuantizedMeshTerrain,CesiumRasterOverlays,Cesium3DTilesSelection,CesiumJsonWriter,Cesium3DTilesWriter,CesiumGltfWriter,CesiumIonClient libraryNode + linkStyle 0 stroke:#ff0029,stroke-width:8px + linkStyle 1,20,60 stroke:#377eb8,stroke-width:8px + linkStyle 2,63 stroke:#66a61e,stroke-width:8px + linkStyle 3 stroke:#984ea3,stroke-width:8px + linkStyle 4,13,19,23,24,26,29,35,56,70,71,78,87 stroke:#00d2d5,stroke-width:8px + linkStyle 5,15,46,81 stroke:#ff7f00,stroke-width:8px + linkStyle 6,48 stroke:#af8d00,stroke-width:8px + linkStyle 7,16,30,36,49,64,72,86 stroke:#7f80cd,stroke-width:8px + linkStyle 8,25,31,50,73 stroke:#b3e900,stroke-width:8px + linkStyle 9,32,51,65,74 stroke:#c42e60,stroke-width:8px + linkStyle 10,33,37,52,66,75,83 stroke:#a65628,stroke-width:8px + linkStyle 11,67,76 stroke:#f781bf,stroke-width:8px + linkStyle 12,34,53,77 stroke:#8dd3c7,stroke-width:8px + linkStyle 14,58 stroke:#bebada,stroke-width:8px + linkStyle 17,38,68 stroke:#fb8072,stroke-width:8px + linkStyle 18 stroke:#80b1d3,stroke-width:8px + linkStyle 21,61 stroke:#fdb462,stroke-width:8px + linkStyle 22 stroke:#fccde5,stroke-width:8px + linkStyle 27 stroke:#bc80bd,stroke-width:8px + linkStyle 28 stroke:#ffed6f,stroke-width:8px + linkStyle 39 stroke:#c4eaff,stroke-width:8px + linkStyle 40 stroke:#cf8c00,stroke-width:8px + linkStyle 41 stroke:#1b9e77,stroke-width:8px + linkStyle 42,57 stroke:#d95f02,stroke-width:8px + linkStyle 43 stroke:#e7298a,stroke-width:8px + linkStyle 44 stroke:#e6ab02,stroke-width:8px + linkStyle 45,85,90 stroke:#a6761d,stroke-width:8px + linkStyle 47 stroke:#0097ff,stroke-width:8px + linkStyle 54 stroke:#00d067,stroke-width:8px + linkStyle 55 stroke:#000000,stroke-width:8px + linkStyle 59,79 stroke:#252525,stroke-width:8px + linkStyle 62,80 stroke:#525252,stroke-width:8px + linkStyle 69,82,84 stroke:#737373,stroke-width:8px + linkStyle 88 stroke:#969696,stroke-width:8px + linkStyle 89 stroke:#bdbdbd,stroke-width:8px + linkStyle 91 stroke:#f43600,stroke-width:8px diff --git a/doc/diagrams/tileset-culling-flowchart.mmd b/doc/diagrams/tileset-culling-flowchart.mmd new file mode 100644 index 000000000..6eca5b784 --- /dev/null +++ b/doc/diagrams/tileset-culling-flowchart.mmd @@ -0,0 +1,21 @@ +flowchart LR + Start@{ shape: sm-circ, label: "Start" } + ITileExcluder{Excluded by any ITileExcluder?} + CullAgainstViews[Cull Against Views] + FrustumCull{Is Inside View Frustum or Frustum Culling Disabled?} + FogCull{Is Visible in Fog or Fog Culling Disabled?} + MoreViews{More Views?} + Visit[Visit] + NoVisit[Do Not Visit] + + Start-->ITileExcluder + ITileExcluder-->|Yes|NoVisit + ITileExcluder-->|No|CullAgainstViews + CullAgainstViews-->|First View|FrustumCull + + FrustumCull-->|Yes|FogCull + FrustumCull-->|No|MoreViews + MoreViews-->|Yes - Next View|FrustumCull + MoreViews-->|No|NoVisit + FogCull-->|No|MoreViews + FogCull-->|Yes|Visit diff --git a/doc/diagrams/tileset-sequence-diagram-frame1.mmd b/doc/diagrams/tileset-sequence-diagram-frame1.mmd new file mode 100644 index 000000000..0416a743c --- /dev/null +++ b/doc/diagrams/tileset-sequence-diagram-frame1.mmd @@ -0,0 +1,12 @@ +sequenceDiagram + actor Application + participant Tileset + actor IAssetAccessor + actor IPrepareRendererResources + + Note over Application,Tileset: Frame 1 + Application->>Tileset: updateView + Tileset->>Tileset: Select Tiles A, B + Tileset-)IAssetAccessor: Start: get (Tile A) + Tileset-)IAssetAccessor: Start: get (Tile B) + Tileset-->>Application: Tiles to Render This Frame (None) diff --git a/doc/diagrams/tileset-sequence-diagram-frame2.mmd b/doc/diagrams/tileset-sequence-diagram-frame2.mmd new file mode 100644 index 000000000..b09e738c4 --- /dev/null +++ b/doc/diagrams/tileset-sequence-diagram-frame2.mmd @@ -0,0 +1,12 @@ +sequenceDiagram + actor Application + participant Tileset + actor IAssetAccessor + actor IPrepareRendererResources + + Note over Application,Tileset: Frame 2 + Application->>Tileset: updateView + IAssetAccessor--)Tileset: Resolve: get (Tile A) + Tileset->>Tileset: Select Tiles A, B + Tileset-)IPrepareRendererResources: Start: prepareInLoadThread (Tile A) + Tileset-->>Application: Tiles to Render This Frame (None) diff --git a/doc/diagrams/tileset-sequence-diagram-frame3.mmd b/doc/diagrams/tileset-sequence-diagram-frame3.mmd new file mode 100644 index 000000000..0ab0ce800 --- /dev/null +++ b/doc/diagrams/tileset-sequence-diagram-frame3.mmd @@ -0,0 +1,15 @@ +sequenceDiagram + actor Application + participant Tileset + actor IAssetAccessor + actor IPrepareRendererResources + + Note over Application,Tileset: Frame 3 + Application->>Tileset: updateView + IPrepareRendererResources--)Tileset: Resolve: prepareInLoadThread (Tile A) + IAssetAccessor--)Tileset: Resolve: get (Tile B) + Tileset->>Tileset: Select Tiles A, B + Tileset-)IPrepareRendererResources: Start: prepareInLoadThread (Tile B) + Tileset->>IPrepareRendererResources: prepareInMainThread (Tile A) + IPrepareRendererResources-->>Tileset: Renderer resources (Tile A) + Tileset-->>Application: Tiles to Render This Frame (A) diff --git a/doc/diagrams/tileset-sequence-diagram-frame4.mmd b/doc/diagrams/tileset-sequence-diagram-frame4.mmd new file mode 100644 index 000000000..e29b793b2 --- /dev/null +++ b/doc/diagrams/tileset-sequence-diagram-frame4.mmd @@ -0,0 +1,14 @@ +sequenceDiagram + actor Application + participant Tileset + actor IAssetAccessor + actor IPrepareRendererResources + + Note over Application,Tileset: Frame 4 + Application->>Tileset: updateView + IPrepareRendererResources--)Tileset: Resolve: prepareInLoadThread (Tile B) + Tileset->>Tileset: Select Tile B Only + Tileset->>IPrepareRendererResources: prepareInMainThread (Tile B) + IPrepareRendererResources-->>Tileset: Renderer resources (Tile B) + Tileset->>IPrepareRendererResources: free (Tile A) + Tileset-->>Application: Tiles to Render This Frame (B) diff --git a/doc/diagrams/tileset-traversal-flowchart.mmd b/doc/diagrams/tileset-traversal-flowchart.mmd new file mode 100644 index 000000000..ef96511fc --- /dev/null +++ b/doc/diagrams/tileset-traversal-flowchart.mmd @@ -0,0 +1,24 @@ +flowchart LR + Start@{ shape: sm-circ, label: "Start" } + VisitTileIfNeeded[_visitTileIfNeeded] + ShouldVisit{Should Visit?} + VisitTile[_visitTile] + MeetsSSE{Meets SSE?} + Done + Render + Refine + VisitVisibleChildrenNearToFar[_visitVisibleChildrenNearToFar] + Recurse[Recurse on Children] + + Start-->|Root Tile|VisitTileIfNeeded + VisitTileIfNeeded-->ShouldVisit + ShouldVisit-->|Yes|VisitTile + ShouldVisit-->|No|Done + VisitTile-->MeetsSSE + MeetsSSE-->|Yes|Render + MeetsSSE-->|No|Refine + Refine-->VisitVisibleChildrenNearToFar + VisitVisibleChildrenNearToFar-->Recurse + Recurse-->|Child Tile 1|VisitTileIfNeeded + Recurse-->|Child Tile ...|VisitTileIfNeeded + Recurse-->|Child Tile n|VisitTileIfNeeded diff --git a/doc/footer.html b/doc/footer.html index 8b75ff702..280ffec1b 100644 --- a/doc/footer.html +++ b/doc/footer.html @@ -1,8 +1,12 @@ + + - + + - + + \ No newline at end of file diff --git a/doc/img/dependency-graph.svg b/doc/img/dependency-graph.svg new file mode 100644 index 000000000..b34ba7aa5 --- /dev/null +++ b/doc/img/dependency-graph.svg @@ -0,0 +1 @@ +

CesiumUtility

glm::glm

spdlog::spdlog

uriparser::uriparser

zlib-ng::zlib-ng

Cesium3DTiles

Cesium3DTilesContent

Cesium3DTilesReader

CesiumAsync

CesiumGeometry

CesiumGeospatial

CesiumGltf

CesiumGltfContent

CesiumGltfReader

libmorton::libmorton

CesiumJsonReader

Async++

spdlog::spdlog_header_only

unofficial::sqlite3::sqlite3

earcut

s2::s2

KTX::ktx

WebP::webp

WebP::webpdecoder

draco::draco

libjpeg-turbo::turbojpeg-static

meshoptimizer::meshoptimizer

modp_b64::modp_b64

Cesium3DTilesSelection

CesiumQuantizedMeshTerrain

CesiumRasterOverlays

nonstd::expected-lite

tinyxml2::tinyxml2

CesiumJsonWriter

Cesium3DTilesWriter

CesiumGltfWriter

CesiumIonClient

OpenSSL::Crypto

httplib::httplib

picosha2::picosha2

\ No newline at end of file diff --git a/doc/img/integration-ecosystem-diagram.png b/doc/img/integration-ecosystem-diagram.png new file mode 100644 index 000000000..87664a50e Binary files /dev/null and b/doc/img/integration-ecosystem-diagram.png differ diff --git a/doc/img/screenshot-copernicus-crater.jpg b/doc/img/screenshot-copernicus-crater.jpg new file mode 100644 index 000000000..a30608653 Binary files /dev/null and b/doc/img/screenshot-copernicus-crater.jpg differ diff --git a/doc/img/screenshot-googleplex.jpg b/doc/img/screenshot-googleplex.jpg new file mode 100644 index 000000000..ffd27f5bf Binary files /dev/null and b/doc/img/screenshot-googleplex.jpg differ diff --git a/doc/img/screenshot-ny-metadata.jpg b/doc/img/screenshot-ny-metadata.jpg new file mode 100644 index 000000000..37fb5601f Binary files /dev/null and b/doc/img/screenshot-ny-metadata.jpg differ diff --git a/doc/img/screenshot-san-francisco.jpg b/doc/img/screenshot-san-francisco.jpg new file mode 100644 index 000000000..b01f6bbfa Binary files /dev/null and b/doc/img/screenshot-san-francisco.jpg differ diff --git a/doc/img/with-ancestor-meets-sse.gif b/doc/img/with-ancestor-meets-sse.gif new file mode 100644 index 000000000..0b22f8e5d Binary files /dev/null and b/doc/img/with-ancestor-meets-sse.gif differ diff --git a/doc/img/without-ancestor-meets-sse.gif b/doc/img/without-ancestor-meets-sse.gif new file mode 100644 index 000000000..cbb365005 Binary files /dev/null and b/doc/img/without-ancestor-meets-sse.gif differ diff --git a/doc/integration-ecosystem-diagram.jpg b/doc/integration-ecosystem-diagram.jpg deleted file mode 100644 index e83c2b2ad..000000000 Binary files a/doc/integration-ecosystem-diagram.jpg and /dev/null differ diff --git a/doc/topics/async-system.md b/doc/topics/async-system.md index 52b7b8b5a..5e6e78382 100644 --- a/doc/topics/async-system.md +++ b/doc/topics/async-system.md @@ -17,31 +17,16 @@ Once it's downloaded, we need to process that tile content that we just download We want to do as much of this kind of work as we possibly can in a background thread, because CPUs have multiple cores these days and the main thread is usually busy doing other important work. -Unfortunately, there is inevitably at least a little bit of tile loading work that can't be done in a background thread, though. Game engines, for example, usually have strict rules against creating game objects anywhere other than the main thread. We can't get anything onto the screen without creating game objects, so after the background work is complete, we then need to continue processing this tile in the main thread in order to do the final preparation to render it. +Unfortunately, there is inevitably at least a little bit of tile loading work that can't be done in a background thread. Game engines, for example, usually have strict rules against creating game objects anywhere other than the main thread. We can't get anything onto the screen without creating game objects, so after the background work is complete, we then need to continue processing this tile in the main thread in order to do the final preparation to render it. `AsyncSystem` gives us an elegant way to express this kind of sequential process involving a series of asynchronous steps. + -## Creating an AsyncSystem {#creating-an-asyncsystem} +## The AsyncSystem Class {#asyncsystem-class} -Most applications have a single `AsyncSystem` that is used throughout. It is constructed from an [ITaskProcessor](@ref CesiumAsync::ITaskProcessor) instance, which is a simple interface used to perform some work in a background thread. The simplest possible implementation looks like this: +An `AsyncSystem` object manages the other objects we use to schedule work and wait for its completion. During initialization, an application [constructs an AsyncSystem object](#creating-an-asyncsystem) and passes it to Cesium Native, which in turn uses it in all operations that might complete asynchronously. `AsyncSystem` instances can be safely and efficiently stored and copied by value; this makes it easy to make them available wherever they're needed, including in lambda captures. On the other hand, holding a reference to an `AsyncSystem` object is very bug-prone in asynchronous code; the lifetime of the reference holder can be quite different from the code that uses it and hard to reason about. It is idiomatic to pass a `const` reference to an `AsyncSystem` object as a parameter to a function, but that reference must be copied to a value if it will be used outside of the lifetime of the function. For example, in the following code, the `asyncSystem` function parameter is copied to a constant value member in the inner lambda: -\snippet{trimleft} ExamplesAsyncSystem.cpp simplest-task-processor - -This implementation will work well, but it isn't very efficient because a brand new thread is created for each task. Most applications will implement this interface using a thread pool, task graph, or similar functionality that their application already contains. - -The `AsyncSystem` can then be created as follows: - -\snippet{trimleft} ExamplesAsyncSystem.cpp create-async-system - -`AsyncSystem` instances can be safely and efficiently stored and copied by value. This makes it easy to make them available wherever they're needed, including in lambda captures. - -\snippet{trimleft} ExamplesAsyncSystem.cpp capture-by-value - -You can think of an instance of `AsyncSystem` as a reference (perhaps a "smart reference") to an underlying implementation. When we create an `AsyncSystem` using its constructor taking an `ITaskProcessor`, we're creating a brand new underlying implementation. If we then copy that `AsyncSystem` (using its copy constructor or assignment operator), we're not really copying that underlying implementation, we're just creating another reference to the same one. Only when the last `AsyncSystem` instance referencing a particular underlying implementation is destroyed is that _underlying implementation_ destroyed. - -You can copy and destroy `AsyncSystem` instances at will, but you must take care that the _last_ instance referencing a given underlying implementation is destroyed only after all of that underlying implementation's `Futures` are complete. So a common pattern is to create and store an `AsyncSystem` as a static local in an accessor function: - -\snippet{trimleft} ExamplesAsyncSystem.cpp async-system-singleton +\snippet{trimleft} Cesium3DTilesReader/src/SubtreeFileReader.cpp async-system-store-in-lambda ## Future {#future} @@ -84,7 +69,7 @@ So far, this all looks like a glorified callback system. The real power of `Asyn \snippet{trimleft} ExamplesAsyncSystem.cpp chaining -In this example, we call `get` to start a network request, as before. We immediately call `thenInWorkerThread` on the returned `Future` in order to register a continuation for when the request completes. This continuation runs in a background thread and calls a made-up function for this example, `processDownloadedContent`. We can imagine that it's doing some intensive processing, and we wouldn't want to block the main thread while it's doing it. +In this example, we call `get` to start a network request, as before. We immediately call `thenInWorkerThread` on the returned `Future` in order to register a continuation for when the request completes. This continuation runs in a background thread and calls `processDownloadedContent`. We can imagine that it's doing some intensive processing, and we wouldn't want to block the main thread while it's doing it. The continuation lambda returns an instance of example type `ProcessedContent`. Because the lambda function we pass to it returns `ProcessedContent`, the `thenInWorkerThread` call returns `Future`. This new `Future` will resolve when the request completes _and then_ the `processDownloadedContent` also completes. @@ -114,7 +99,7 @@ Unlike the `then...` family continuations, which receive the value of the succes \snippet{trimleft} ExamplesAsyncSystem.cpp catch -In this example, we call a made-up function `startOperationThatMightFail`, and it returns a `Future`. We then call `catchImmediately` on it in order to register a continuation that will be invoked if the operation fails with an exception. Notice that this continuation returns a `ProcessedContent` too, in this case created from the failure error message. This is a common pattern - a `catch` continuation turning the error into a result value that encapsulates the error. +In this example, we call `startOperationThatMightFail`, and it returns a `Future`. We then call `catchImmediately` on it in order to register a continuation that will be invoked if the operation fails with an exception. Notice that this continuation returns a `ProcessedContent` too, in this case created from the failure error message. This is a common pattern - a `catch` continuation turning the error into a result value that encapsulates the error. The `catchImmediately` returns a new `Future`, just like a `then...` method does. The value type `T` of the `Future` will be the same as the original `Future` that we called `catchImmediately` on, and it is for this reason that the continuation function given to `catch...` _must_ return a value of the same type that `startOperationThatMightFail` would have produced on success. The only other option is to throw an exception, at which point execution will continue at the continuation provided to the _next_ `catch...` in the chain. @@ -130,7 +115,7 @@ Imagine that we're downloading a web page from the internet, as we were in previ \snippet{trimleft} ExamplesAsyncSystem.cpp unwrapping -In this example, our first continuation calls a made-up function `findReferenceImageUrl` to determine the URL of an image referenced by the page. We then call `get` to download that image. Notice that we've captured `asyncSystem` and `pAssetAccessor` in the lambda in order to make this possible. The `get` call returns a `Future`, and we return that `Future` from our continuation. The returned `Future` is unwrapped by the `AsyncSystem`, and as a result, the second continuation, the one passed to `thenInMainThread`, will not be invoked until this second request `Future` resolves. +In this example, our first continuation calls `findReferenceImageUrl` to determine the URL of an image referenced by the page. We then call `get` to download that image. Notice that we've captured `asyncSystem` and `pAssetAccessor` in the lambda in order to make this possible. The `get` call returns a `Future`, and we return that `Future` from our continuation. The returned `Future` is unwrapped by the `AsyncSystem`, and as a result, the second continuation, the one passed to `thenInMainThread`, will not be invoked until this second request `Future` resolves. You may have noticed that our second continuation, the one passed to `thenInMainThread`, only has access to the image's `IAssetRequest`. What if we also need to use the page `IAssetRequest`? Or some other data derived from it? While it's possible to do this manually with extra continuations and lambda captures, the `thenPassThrough` method makes the process simpler. @@ -176,7 +161,7 @@ We'd like to be able to use the `AsyncSystem` to do further work after this comp \snippet{trimleft,strip} ExamplesAsyncSystem.cpp compute-something-slowly-async-system -The trick is to call [createPromise](@ref CesiumAsync::AsyncSystem::createPromise) to create a `Promise`, and then capture it in the callback lambda given to the library's `computeSomethingSlowly`. When the callback is invoked, we call [resolve](@ref CesiumAsync::Promise::resolve) on the `Promise`, which resolves the assocated `Future` that was previously obtained with [getFuture](@ref CesiumAsync::Promise::getFuture). We can then chain continuations off that `Future` in the normal way. Instead of calling `resolve` on the `Promise`, we can also call [reject](@ref CesiumAsync::Promise::reject). +The trick is to call [createPromise](@ref CesiumAsync::AsyncSystem::createPromise) to create a `Promise`, and then capture it in the callback lambda given to the library's `computeSomethingSlowly`. When the callback is invoked, we call [resolve](@ref CesiumAsync::Promise::resolve) on the `Promise`, which resolves the associated `Future` that was previously obtained with [getFuture](@ref CesiumAsync::Promise::getFuture). We can then chain continuations off that `Future` in the normal way. Instead of calling `resolve` on the `Promise`, we can also call [reject](@ref CesiumAsync::Promise::reject). One problem with this `createPromise` approach is that it does not behave as well as it should in the face of exceptions. Imagine that we're wrapping all of this functionality up in our own function, like this: @@ -202,7 +187,7 @@ It may initially be surprising to learn that calling `then...` or `catch...` on ## Lambda Captures and Thread Safety {#lambda-captures-and-thread-safety} -`AsyncSystem` is a powerful abstraction for writing safe and easy-to-understand multithreaded code. Even if so, `AsyncSystem` does not completely prevent you from creating data races. In particular, it's essential to use care and good judgement when choosing what to capture in continuation lambdas. Here are some tips: +`AsyncSystem` is a powerful abstraction for writing safe and easy-to-understand multithreaded code. Even if so, `AsyncSystem` does not completely prevent you from creating data races. In particular, it's essential to use care and good judgment when choosing what to capture in continuation lambdas. Here are some tips: * DO NOT capture by reference or pointer, unless you're certain that the object referenced is thread-safe and will still be around when the continuation is invoked. This can be difficult to achieve in practice! * DO think in terms of transferring ownership of an object to the promise chain, and transferring ownership back out at the end. This requires use of `std::move` and a `mutable` lambda (so that the captured value is not `const`). It looks like this: @@ -211,3 +196,31 @@ It may initially be surprising to learn that calling `then...` or `catch...` on * DO be aware of _when_ and _in what thread_ lambda captures are destroyed. Continuation lambda captures are destroyed immediately after the continuation runs, in whatever thread ran the continuation. If a `catch...` continuation is skipped because the `Future` to which it's attached resolved instead of rejecting, the continuation's captures are destroyed in whatever thread did the resolving. Similarly, if a `then...` continuation is skipped because the `Future` to which it's attached rejected, the continuation's captures are destroyed in whatever thread did the rejecting. * DO NOT capture an [IntrusivePointer](@ref CesiumUtility::IntrusivePointer) to a non-thread-safe object (such as one derived from `ReferenceCountedNonThreadSafe`) except in a continuation that runs in the thread that owns it. For example, in the usual case that an object is owned by the "main thread", a pointer to that object should only be captured in a lambda given to `runInMainThread`, `thenInMainThread`, or `catchInMainThread`. Furthermore, as a corollary to the item above, ensure that these `IntrusivePointer`-capturing continuations cannot be skipped when the Future is either resolved or rejected, because this could result in the `IntrusivePointer` being destroyed in the wrong thread. Failure to follow this rule can lead to corruption of the object's reference count, leading to some difficult to debug problems. In Debug builds, assertions will help to detect this sort of problem. + +## AsyncSystem and ITaskProcessor Implementation {#async-system-implementation} + +### Creating an AsyncSystem {#creating-an-asyncsystem} + +[AsyncSystem](@ref CesiumAsync::AsyncSystem) is implemented using a subclass of the [ITaskProcessor](@ref CesiumAsync::ITaskProcessor) interface class via [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection). +`ITaskProcessor` specifies a simple interface used to perform some work in a background thread. The simplest possible implementation looks like this: + +\snippet{trimleft} ExamplesAsyncSystem.cpp simplest-task-processor + +This implementation will work, but it isn't very efficient because a brand new thread is created for each task. Most applications will implement this interface using a thread pool, task graph, or similar functionality that their application already contains. + +The `AsyncSystem` could be created as follows: + +\snippet{trimleft} ExamplesAsyncSystem.cpp create-async-system + +However, Cesium Native does not contain any calls like this, other than in test code. Except under unusual circumstances, applications should construct a single `AsyncSystem` object that is copied and is used throughout. Two `AsyncSystem` objects that are created with this constructor, even if they share the same `ITaskProcessor`, will have different work queues and different notions of the main thread and, if they are used together, disaster can result. + +On the other hand, `AsyncSystem` instances have copy semantics, so it is easy to make them available wherever they're needed, including in lambda captures. In this example, `asyncSystem` is captured by value for use in the lambda. + +\snippet{trimleft} ExamplesAsyncSystem.cpp capture-by-value + +You can think of an instance of `AsyncSystem` as a reference (perhaps a "smart reference") to an underlying implementation which includes an `ITaskProcessor` and all the supporting data structures for implementing futures, promises, and other `AsyncSystem` abstractions. When we create an `AsyncSystem` using its constructor, we're creating a brand new underlying implementation. If we then copy that `AsyncSystem` (using its copy constructor or assignment operator), we're not really copying that underlying implementation, we're just creating another reference to the same one with its `ITaskProcessor` object. Only when the last `AsyncSystem` instance referencing a particular underlying implementation is destroyed is that _underlying implementation_ destroyed. + +You can copy and destroy `AsyncSystem` instances at will, but you must take care that the _last_ instance referencing a given underlying implementation is destroyed only after all of that underlying implementation's `Futures` are complete. So a common pattern is to create and store an `AsyncSystem` as a static local in an accessor function: + +\snippet{trimleft} ExamplesAsyncSystem.cpp async-system-singleton + diff --git a/doc/topics/dependencies.md b/doc/topics/dependencies.md new file mode 100644 index 000000000..b3b418f23 --- /dev/null +++ b/doc/topics/dependencies.md @@ -0,0 +1,33 @@ +# Dependencies + +Cesium Native relies on a number of third-party dependencies. These dependencies are automatically resolved and built using [vcpkg](https://vcpkg.io/) at compile time. + +| Dependency | Usage | +| ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| [Async++](https://github.com/Amanieu/asyncplusplus) | Used by CesiumAsync for cross-platform concurrency. | +| [Catch2](https://github.com/catchorg/Catch2) | Test framework used by CesiumNativeTests. | +| [draco](https://github.com/google/draco) | Required to decode meshes and point clouds compressed with Draco. | +| [earcut](https://github.com/mapbox/earcut.hpp) | Polygon triangulation library for used by CartographicPolygon. | +| [expected-lite](https://github.com/martinmoene/expected-lite) | Implementation of the `std::expected` proposal for returning either an expected value or an error value. | +| [glm](https://github.com/g-truc/glm) | C++ mathematics library powering the high-precision math needed for geospatial software. | +| [meshoptimizer](https://github.com/zeux/meshoptimizer) | Required to decode meshes compressed with meshoptimizer. | +| [httplib](https://github.com/yhirose/cpp-httplib) | Used by CesiumIonClient to interact with the Cesium ion REST API. | +| [Ktx](https://github.com/CesiumGS/KTX-Software) | Required to load KTX GPU compressed textures. | +| [libmorton](https://github.com/Forceflow/libmorton) | Implementation of Morton codes used for implicit tiling. | +| [libjpeg-turbo](https://github.com/libjpeg-turbo/libjpeg-turbo) | Decodes JPEG images. | +| [libwebp](https://github.com/webmproject/libwebp) | Decodes WebP images. | +| [modp_b64](https://github.com/chromium/chromium/tree/15996b5d2322b634f4197447b10289bddc2b0b32/third_party/modp_b64) | Decodes and encodes base64. | +| [OpenSSL](https://github.com/openssl/openssl) | Required by s2geometry, and also used to generate unique authorization tokens for authenticating with Cesium ion. | +| [PicoSHA2](https://okdshin/PicoSHA2) | Generates SHA256 hashes for use with the Cesium ion REST API. | +| [RapidJSON](https://github.com/Tencent/rapidjson) | For JSON reading and writing. | +| [s2geometry](https://github.com/google/s2geometry) | Spatial indexing library designed for geospatial use and required by some tilesets. | +| [spdlog](https://github.com/gabime/spdlog) | Logging. | +| [sqlite3](https://www.sqlite.org/index.html) | Used to cache HTTP responses. | +| [stb_image](https://github.com/nothings/stb/blob/master/stb_image.h) | A simple image loader. | +| [tinyxml2](https://github.com/leethomason/tinyxml2) | XML parser for interacting with XML APIs such as those implementing the Web Map Service standard. | +| [uriparser](https://github.com/uriparser/uriparser) | Used to parse and manipulate URIs. | +| [zlib-ng](https://github.com/zlib-ng/zlib-ng) | An optimized zlib implementation for working with Gzipped data. | + +The following chart illustrates the connections between the Cesium Native libraries and third-party dependencies: + +\svg-interactive{dependency-graph, 600px} \ No newline at end of file diff --git a/doc/topics/developer-setup.md b/doc/topics/developer-setup.md new file mode 100644 index 000000000..c9b86e682 --- /dev/null +++ b/doc/topics/developer-setup.md @@ -0,0 +1,115 @@ +# Developer Setup Guide {#developer-setup} + +This guide contains the basic setup information for developers looking to work with Cesium Native. **To follow this guide, you will need the following prerequisites:** + +* Visual Studio 2019 (or newer), GCC v11.x+, or Clang 12+ + * Other compilers are likely to work but are not regularly tested. +* CMake 3.15+ +* For best JPEG-decoding performance, you must have [nasm](https://www.nasm.us/) installed so that CMake can find it. Everything will work fine without it, just slower. + + + + + +## Table of Contents + +- [Clone the Repo](#clone-the-repo) +- [Compiling Cesium Native](#compiling-cesium-native) + - [Compile from command line](#compile-from-command-line) + - [Compile from Visual Studio Code](#compile-from-visual-studio-code) + - [Compile with any Visual Studio version using CMake generated projects](#compile-with-any-visual-studio-version-using-cmake-generated-projects) +- [Generate Documentation](#generate-documentation) +- [Regenerate glTF and 3D Tiles classes](#regenerate-gltf-and-3d-tiles-classes) +- [Regenerate Dependency Graphs](#regenerate-dependency-graphs) + + + +## Clone the Repo + +Check out the repo with: + +```bash +git clone git@github.com:CesiumGS/cesium-native.git --recurse-submodules +``` + +If you forget the `--recurse-submodules`, nothing will work because the git submodules will be missing. You should be able to fix it with: + +```bash +git submodule update --init --recursive +``` + +## Compiling Cesium Native + +### Compile from command line + +```bash +## Windows compilation using Visual Studio +cmake -B build -S . -G "Visual Studio 17 2022" -A x64 +cmake --build build --config Debug +cmake --build build --config Release + +## Linux compilation +cmake -B build -S . +cmake --build build +``` + +### Compile from Visual Studio Code + +1) Install the `CMake Tools` extension. It should prompt you to generate project files from CMake. +2) On Windows, choose `Visual Studio 2017 Release - amd64` as the kit to build. Or choose an appropriate kit for your platform. +3) Then press Ctrl-Shift-P and execute the `CMake: Build` task or press F7. + +### Compile with any Visual Studio version using CMake generated projects + +1) Open the CMake UI (cmake-gui) +2) Under "Where is the source code", point to your repo +3) Specify your output folder in "Where to build the binaries" +4) Click "Configure". +5) Under "Specify the generator for this project", choose the VS version on your system +6) Click Finish, wait for the process to finish +7) Click Generate + +Look for cesium-native.sln in your output folder. + +Unit tests can also be run from this solution, under the cesium-native-tests project. + +![image](https://github.com/CesiumGS/cesium-native/assets/130494071/4d398bfc-f770-49d4-8ef5-a995096ad4a1) + +## Generate Documentation + +* Install [Doxygen](https://www.doxygen.nl/). +* Run: `npm install` +* Run: `cmake --build build --target cesium-native-docs` +* Open `build/doc/html/index.html` + +## Regenerate glTF and 3D Tiles classes + +Much of the code in `CesiumGltf`, `Cesium3DTiles`, `CesiumGltfReader`, `CesiumGltfWriter`, `Cesium3DTilesReader`, `Cesium3DTilesWriter`, and `CesiumQuantizedMeshTerrain` is generated from the standards' JSON Schema specifications. To regenerate the code: + +* Make sure you have a relatively recent version of Node.js installed. +* Install dependencies by running: + +``` +npm install +cd tools/generate-classes +npm install +cd ../.. +``` + +* From the repo root directory, run these commands + * `npm run generate-gltf` + * `npm run generate-3d-tiles` + * `npm run generate-quantized-mesh-terrain` +* On Windows, the line endings of the generated files will be different than those checked into the repo. Just `git add` them and git will fix the line endings (no need to commit). + +## Regenerate Dependency Graphs + +The dependency graphs used in the Cesium Native documentation are generated using a script that parses CMake's GraphViz output and generates a set of Mermaid diagrams. To regenerate the graphs: + +* Make sure you have a relatively recent version of Node.js installed. +* Install dependencies by running: +``` +cd tools/dep-graph-gen +npm install +``` +* From the `tools/dep-graph-gen` directory, run `npm run generate-dep-graph` to regenerate the graphs. \ No newline at end of file diff --git a/doc/topics/developer.md b/doc/topics/developer.md new file mode 100644 index 000000000..48f23d1d3 --- /dev/null +++ b/doc/topics/developer.md @@ -0,0 +1,6 @@ +# Developer Resources {#developer-resources} + +* \subpage developer-setup +* \subpage multithreading +* \subpage style-guide +* \subpage contributing \ No newline at end of file diff --git a/doc/topics/rendering-3d-tiles.md b/doc/topics/rendering-3d-tiles.md new file mode 100644 index 000000000..2b177ec86 --- /dev/null +++ b/doc/topics/rendering-3d-tiles.md @@ -0,0 +1,66 @@ +# Rendering 3D Tiles {#rendering-3d-tiles} + +One of the main reasons to integrate Cesium Native into an application is to add support for rendering [3D Tiles](https://github.com/CesiumGS/3d-tiles). This guide explains how that can be done. + +A 3D Tiles [Tileset](@ref Cesium3DTilesSelection::Tileset) is a potentially massive 3D model - such as the entire Earth! - broken up into a bounding-volume hierarchy (BVH) of small pieces, called tiles. The main challenge of rendering a 3D Tiles tileset lies in deciding which tiles need to be loaded and rendered each frame, employing view-dependent culling and level-of-detail techniques. Fortunately, Cesium Native takes care of these details. + +It's important to understand that Cesium Native doesn't actually do any rendering itself, though. Instead, it provides each tile in the form of an in-memory [glTF](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html) model, and it's up to your integration to do the actual rendering. These glTF models are rendering-ready static meshes, so rendering them is relatively straightforward in most environments. + +## Sequence Walkthrough {#sequence-walkthrough} + +In order to understand the pieces that you will need to implement in order to complete your integration, let's walk through a sequence of render frames and show what happens along the way. In this diagram: + +* `Application` is the application you're developing. +* `Tileset` is the Cesium Native [Tileset](@ref Cesium3DTilesSelection::Tileset) class. +* `IAssetAccessor` is Cesium Native's interface to download assets, i.e., files on the file system or a web server. You must implement this interface. +* `IPrepareRendererResources` is Cesium Native's interface to create "renderer" resources on-demand for the glTF models that it provides. For example, if you're integrating Cesium Native into a game engine, the renderer resource might be an instance of the game engine's static mesh class. You must implement this interface as well. + +@mermaid{tileset-sequence-diagram-frame1} + +In Frame 1, your application calls [updateView](@ref Cesium3DTilesSelection::Tileset::updateView) on the `Tileset`. It passes in all of the [ViewStates](@ref Cesium3DTilesSelection::ViewState) from which the tileset is currently being viewed. A `ViewState` includes a position, a look direction, a camera "up" direction, a viewport width and height in pixels, and horizontal and vertical field-of-view angles. This is all the information that Cesium Native needs in order to decide which subset of the model is visible, and what level-of-detail is needed for each part. You'll likely create a `ViewState` from each camera in your scene. + +In our example, based on the `ViewStates`, Cesium Native selects tiles A and B as being needed for rendering. The details of this process are described in the [3D Tiles Selection Algorithm](@ref selection-algorithm-details), but aren't important for now. In Frame 1, no tiles are loaded yet, so `Tileset` calls [IAssetAccessor::get](@ref CesiumAsync::IAssetAccessor::get) to initiate the download of these two tiles. These downloads happen asynchronously via the [AsyncSystem](#async-system); Cesium Native doesn't wait for them to complete before continuing. + +@mermaid{tileset-sequence-diagram-frame2} + +In Frame 2, your application calls `updateView` again, as it will every frame. If any views have changed since last frame, you should provide the new views, and Cesium Native will adapt accordingly. + +At the start of the `updateView`, the `Tileset` happens to receive the asynchronous content for Tile A that it requested in Frame 1. It's entirely possible that this download could take multiple frames, or that it could complete in between calls to `updateView`, rather than completing for the next frame as we've shown here. + +`updateView` runs the selection algorithm again, and once again selects Tiles A and B. `Tileset` is still waiting for content for Tile B, so it can't do anything more there. However, it's already received the content for Tile A, so it can start the next part of the process: [prepareInLoadThread](@ref Cesium3DTilesSelection::IPrepareRendererResources::prepareInLoadThread). As the name implies, this method is invoked from a background worker thread (dispatched using [ITaskProcessor](@ref CesiumAsync::ITaskProcessor)) and gives your integration its first opportunity to do renderer resource preparation for Tile A's glTF model. + +> [!note] +> In most applications, it's possible to do some of the work necessary to prepare a static mesh for rendering in a background thread, but at least a small part of that work must be done in the application's "main" thread. That is why the glTF preparation process is split into two parts: `prepareInLoadThread`, which we've just seen, and `prepareInMainThread`, which we'll see in the next frame. Applications are free to divide the work between these two methods however they see fit. Some applications may not use one or the other of them at all. + +@mermaid{tileset-sequence-diagram-frame3} + +In Frame 3, two asynchronous operations begun in previous frames resolve (complete successfully). The first is the `prepareInLoadThread` for Tile A, and the second is the download of Tile B's content. `Tileset` runs the selection algorithm again, and happens to come up with the same answer, selecting tiles A and B. + +Now that `Tileset` has content for Tile B, it can initiate the `prepareInLoadThread` for Tile B, as it did for Tile A last frame. And now that the `prepareInLoadThread` has resolved for Tile A, `Tileset` can call [prepareInMainThread](@ref Cesium3DTilesSelection::IPrepareRendererResources::prepareInMainThread) for Tile A. Unlike `prepareInLoadThread`, `prepareInMainThread` is a synchronous operation that must complete and return before the work of `updateView` can continue. For this reason, it's important to keep `prepareInMainThread` as fast as possible! + +> [!note] +> By "main thread", we mean the thread that called `updateView`. This does not necessarily have to be the thread that your application considers to be the main one. However, you must ensure that multiple threads do not access `Tileset` simultaneously. In Debug builds of Cesium Native, assertions will prevent you from calling `updateView` from different threads even if you ensure only one thread at a time is doing so, because this usually indicates a mistake and the potential for a subtle race condition. + +`prepareInLoadThread` and `prepareInMainThread` should ensure that the renderer resources they create are initially _not_ visible in the scene. This is important because some tiles are pre-loaded, before they're actually needed for rendering. + +With Tile A selected and its loading complete, the `Tileset` will return it from `updateView` as one of the [tilesToRenderThisFrame](@ref Cesium3DTilesSelection::ViewUpdateResult::tilesToRenderThisFrame). Your application must look through the returned set of tiles and ensure that each is visible (rendered). Similarly, tiles in the [tilesFadingOut](@ref Cesium3DTilesSelection::ViewUpdateResult::tilesFadingOut) should be hidden or faded out. + +@mermaid{tileset-sequence-diagram-frame4} + +In Frame 4, the `prepareInLoadThread` initiated for Tile B in Frame 3 resolves. When `Tileset` runs the selection algorithm, it learns that, because a view has moved, only Tile B is selected now. It calls `prepareInMainThread` on Tile B to prepare it for rendering. + +`Tileset` also calls [free](@ref Cesium3DTilesSelection::IPrepareRendererResources::free) to release the renderer resources that were created for Tile A in `prepareInLoadThread` and `prepareInMainThread`. Once the renderer resources are freed, the `Tileset` will release the glTF tile content as well. In practice, this `free` may or may not actually happen this frame. Cesium Native keeps some tiles around, up to a [maximumCachedBytes](@ref Cesium3DTilesSelection::TilesetOptions::maximumCachedBytes) specified in [TilesetOptions](@ref Cesium3DTilesSelection::TilesetOptions), in case they are needed again soon. Cesium Native will ensure that the tiles it calls `free` on are not currently visible in the scene. + +With that out of the way, `Tileset` returns the new set of `tilesToRenderThisFrame` (B). It will also include Tile A in the `tilesFadingOut`. + +## Implementing 3D Tiles Rendering {#implement-3d-tiles-rendering} + +As illustrated above, integrating 3D Tiles rendering in your application requires the following: + +1. Implement [ITaskProcessor](@ref CesiumAsync::ITaskProcessor) to run jobs in background threads, preferably using a thread pool or task graph. +2. Implement [IAssetAccessor](@ref CesiumAsync::IAssetAccessor) to download resources from whatever sources your application needs to load 3D Tiles from. A possible approach is to use [libcurl](https://curl.se/libcurl/), but many applications already include file and HTTP support. +3. Implement [IPrepareRendererResources](@ref Cesium3DTilesSelection::IPrepareRendererResources) to create meshes and textures for your application from the in-memory glTF representations provided by Cesium Native. +4. When constructing a [Tileset](@ref Cesium3DTilesSelection::Tileset), pass in instances of the three implementations above as part of the [TilesetExternals](@ref Cesium3DTilesSelection::TilesetExternals). +5. Call [updateView](@ref Cesium3DTilesSelection::Tileset::updateView) on each `Tileset` each frame. Show the already-created models identified in [tilesToRenderThisFrame](@ref Cesium3DTilesSelection::ViewUpdateResult::tilesToRenderThisFrame) and hide the ones in [tilesFadingOut](@ref Cesium3DTilesSelection::ViewUpdateResult::tilesFadingOut). + +In practice, the bulk of the work is usually in item (3). While glTF is a an efficient format for rendering, implementing a robust and performant pathway from a glTF to your applications rendering system can involve a fair bit of work. It's usually possible, however, to get the basics working relatively quickly. diff --git a/doc/topics/selection-algorithm-details.md b/doc/topics/selection-algorithm-details.md new file mode 100644 index 000000000..104c967dc --- /dev/null +++ b/doc/topics/selection-algorithm-details.md @@ -0,0 +1,151 @@ +# 3D Tiles Selection Algorithm {#selection-algorithm-details} + +In [Rendering 3D Tiles](#rendering-3d-tiles), we described how Cesium Native's support for 3D Tiles rendering can be integrated into an application. Here we go deeper, describing how [Tileset::updateView](@ref Cesium3DTilesSelection::Tileset::updateView) decides which tiles to load and render. This will primarily be of interest to developers improving Cesium Native itself, or perhaps to users who want a deep understanding in order to best optimize the available [TilesetOptions](@ref Cesium3DTilesSelection::TilesetOptions) for their use-case. It is assumed that the reader has familiarity with the [3D Tiles Specification](https://github.com/CesiumGS/3d-tiles/blob/main/specification/README.adoc). + +## High-Level Overview {#high-level-overview} + +@mermaid{tileset-traversal-flowchart} + +At a high level, `updateView` works by traversing the 3D Tiles tileset's bounding-volume hierarchy (BVH) in depth-first order. This is done using recursion, starting with a call to the private `_visitTileIfNeeded` method and passing it the root tile in the BVH. `_visitTileIfNeeded` checks to see if the tile needs to be [visited](#culling). The most important reason a tile would not need to be visited is if it's outside the view frustum of _all_ of the [ViewStates](@ref Cesium3DTilesSelection::ViewState) given to `updateView`. Such a tile is not visible, so we do not need to consider it further and traversal of this branch of the BVH stops here. + +For tiles that _do_ need to be visited, `_visitTileIfNeeded` calls `_visitTile`. + +The most important job of `_visitTile` is to decide whether the current tile - which has already been deemed visible - meets the required [screen-space error (SSE)](#screen-space-error) in all views. If the algorithm considers the current level-of-detail (LOD) of this part of the model, as represented by this tile, to be sufficient for the current view(s), then the tile is _RENDERED_. The tile is added to the [tilesToRenderThisFrame](@ref Cesium3DTilesSelection::ViewUpdateResult::tilesToRenderThisFrame) and traversal of this branch of the BVH stops here. A tile without any children is always deemed to meet the required SSE. + +If a tile that is selected for rendering is not yet loaded, it is queued for loading. + +If the current tile does not provide sufficient detail for the current view(s), then `_visitTile` will instead _REFINE_, which means the algorithm will consider rendering this tile's children instead of this tile. It will call `_visitVisibleChildrenNearToFar`, which will recursively call `_visitTileIfNeeded` on this tile's children. + +At a high level, this is all there is to the Cesium Native tile selection algorithm. As we look closer, though, a lot of important details come into focus. The details are covered in the sections below. + +## Culling {#culling} + +In the [High-Level Overview](#high-level-overview), we mentioned that `_visitTileIfNeeded` determines whether a tile should be visited before calling `_visitTile`. How does it decide this? + +@mermaid{tileset-culling-flowchart} + +In general, a tile should be visited if it cannot be culled. A tile can be culled when any of these are true: + +1. It is explicitly excluded by the application via the [ITileExcluder](@ref Cesium3DTilesSelection::ITileExcluder) interface. +2. It is outside the frustums of all views. +3. It is so far away relative to the camera height that it can be considered "obscured by fog", in all views. + +A tile that is culled via (1) will never be visited. For cases (2) and (3), a culled tile may still be visited if `TilesetOptions` [enableFrustumCulling](@ref Cesium3DTilesSelection::TilesetOptions::enableFrustumCulling) or [enableFogCulling](@ref Cesium3DTilesSelection::TilesetOptions::enableFogCulling), respectively, are set to `false`. + +When both of these options are `false`, `_visitTile` will be called for all tiles that aren't explicitly excluded, so tiles covering the entire model will be selected. There will not be any pieces of the model missing once loading completes. Some parts may still be at a lower level-of-detail than other parts, however. + + + +## Screen-Space Error {#screen-space-error} + +`_visitTile` decides whether to _RENDER_ or _REFINE_ a tile based on its screen-space error (SSE). SSE is an estimate of how "wrong" a given tile will look when rendered, expressed as a distance in pixels on the screen. We can compute SSE as a function of several properties of a tile and a `ViewState`. + +Every 3D Tiles tile has a [geometricError](https://github.com/CesiumGS/3d-tiles/tree/main/specification#geometric-error) property, which expresses the error, in meters, of the tile's representation of its part of the model compared to the original, full-detail model. + +Tiles also have a [bounding volume](https://github.com/CesiumGS/3d-tiles/tree/main/specification#bounding-volumes) that contains all of the tile's triangles and other renderable content. + +`Tileset` computes SSE separately for each `ViewState`, and then uses the _largest_ screen-space error computed for any `ViewState` to drive the refinement decision. It begins by computing the distance (squared) from the `ViewState`'s position to the closest point on the tile's bounding volume using [computeDistanceSquaredToBoundingVolume](@ref Cesium3DTilesSelection::ViewState::computeDistanceSquaredToBoundingVolume). If the `ViewState` is inside the bounding volume, the distance is treated as zero, and the SSE is effectively infinite. When the viewer is outside the bounding volume, though, we can project the tile's geometric error to the screen by calling [computeScreenSpaceError](@ref Cesium3DTilesSelection::ViewState::computeScreenSpaceError) and passing the tile's distance and geometric error. + +Once we know the largest SSE of this tile as viewed from any `ViewState`, we can decide whether to refine this tile by comparing it against the [maximumScreenSpaceError](@ref Cesium3DTilesSelection::TilesetOptions::maximumScreenSpaceError) property in `TilesetOptions`. If the tile's SSE is greater than or equal to the maximum SSE, the tile will be refined in order to reduce the error on the screen. If the tile's SSE is less than the maximum SSE, it means this tile has sufficient detail for all views, so we can render it and we don't need to visit any of this tile's children. + +This basic process always works as described, but the maximum SSE that the tile SSE is compared against can vary for culled tiles. + +Normally, as described in [Culling](#culling), tiles that are culled by the view-frustum or by fog are not visited at all. However, if either `enableFrustumCulling` or `enableFogCulling` is set to `false`, then these tiles will be visited and selected. And in that case, the question becomes: what level-of-detail should they be rendered at? + +The answer is that refinement decisions for these tiles work the same way as for regular tiles, but are based on the value of the [culledScreenSpaceError](@ref Cesium3DTilesSelection::TilesetOptions::culledScreenSpaceError) property instead of `maximumScreenSpaceError`. This allows us to use a lower LOD (larger maximum SSE value) for tiles outside the view frustum or far off in the foggy distance. At an extreme, we can set the [enforceCulledScreenSpaceError](@ref Cesium3DTilesSelection::TilesetOptions::enforceCulledScreenSpaceError) property to `false` if we want to _never_ refine these tiles. This is equivalent to setting `culledScreenSpaceError` to a very large value. The non-visible tiles are selected, so all parts of the model will be represented at some level-of-detail, but the non-visible parts will use the lowest LOD that they can without having a hole in the model. + +## Selecting Loaded Tiles {#selecting-loaded-tiles} + +3D Tiles are usually streamed over the network. The entire tileset is rarely located on the local computer, and almost never loaded entirely into memory. Thus, it's inevitable that we will sometimes want to render tiles that haven't been loaded yet. + +A critical goal of the tile selection algorithm is to prevent visible detail from disappearing with camera movements. + +When the camera moves, a new section of the model might be exposed that wasn't previously visible. If the tiles for this new section are not loaded yet, then we have no choice but to leave that section of the model blank. This is a case of detail not _appearing_ right away when we move the camera. While this is not ideal, and we try to avoid it when we can, detail that was already visible _disappearing_ is much worse. + +> [!note] +> See [Forbid Holes](#forbid-holes) for details of an optional mode that will ensure that "the tiles for this new section are not loaded yet" can never happen, at the cost of additional loading time. + +Detail would disappear very frequently if the tile selection algorithm were as simple as described so far. Imagine we're looking at a model, and everything is loaded and looking great. Now imagine that the user: + +* _Zooms Out_: We suddenly want to render less detailed tiles in the same location. A simple selection algorithm would hide the detailed tiles immediately, before the less-detailed tiles are loaded. This would cause a part of the model that used to be visible to suddenly vanish, only to reappear a moment later after the new tiles were loaded. This would be extremely distracting for our users. Fortunately, this does not happen because of the [Ancestor Meets SSE](#ancestor-meets-sse) mechanism. +* _Zooms In_: More detailed tiles would suddenly be required in the same location. Once again, a simple selection algorithm would immediately hide the less detailed tiles, only to show the more detailed ones a moment later after they load. Fortunately, this does not happen because of the [Kicking](#kicking) mechanism. + +There is a simple solution to both of these problems, but Cesium Native doesn't use it. The simple solution is to arrange the selection algorithm so that a tile can only be _REFINED_ if all of its child tiles are already loaded. This is easy, and avoids the problems described in this section. The reason that Cesium Native doesn't use it is because it makes for drastically slower loading. + +Imagine a tileset organized as a quadtree, so each tile has four children. We're zoomed in close so that four tiles from level 15 of the quadtree would ideally be rendered. If we load those four tiles, we can render the scene from the current camera view, and it will look great. However, if we enforce the rule that "a tile can only be REFINED if its children are all loaded", then we would have to not only load those four tiles at level 15, we would also have to load at least four tiles at level 14, at least four more tiles at level 13, and so on all the way to the root of the tileset. Rather than loading four tiles to render this scene, we would need to load more like 60 tiles! The situation just described is a worst-case scenario, but on average, a _lot_ more tiles would need to be loaded. + +## Ancestor Meets SSE {#ancestor-meets-sse} + +The "Ancestor Meets SSE" mechanism is a feature of the tile selection algorithm that ensures detail does not disappear when the user moves away from the model. It does this by sometimes choosing to _REFINE_ a tile even though its SSE is less than the maximum, which would normally trigger a _RENDER_ instead. It is named for the `ancestorMeetsSse` flag that is set in `_visitTile` when we detect this case. + +After `_visitTile` determines that it would like to _RENDER_ the current tile because it meets the required SSE, it does an additional check by calling `mustContinueRefiningToDeeperTiles`. If this function returns `true`, then the `ancestorMeetsSse` flag will be set and this tile will be _REFINED_, instead of _RENDERED_ as originally planned. + +`mustContinueRefiningToDeeperTiles` returns `true` when the tile was _REFINED_ in the _previous_ frame AND it is not currently renderable. In other words, if descendant tiles were rendering last frame, and they can't be replaced by this tile yet because this tile isn't loaded, then we should continue giving those descendants the option to render. + + + + + + + + + + +
Zooming out without the benefit of "Ancestor Meets SSE""Ancestor Meets SSE" preserves current detail
![Zooming out without the benefit of "Ancestor Meets SSE"](without-ancestor-meets-sse.gif)!["Ancestor Meets SSE" preserves current detail until lower detail is loaded](with-ancestor-meets-sse.gif)
+ +## Kicking {#kicking} + +The _Kicking_ mechanism is a feature of the tile selection algorithm that ensures detail does not disappear when the user moves closer to the model. It does this by discarding a subtree _after_ that subtree has been traversed and some of the tiles in it have been selected for rendering. + +As mentioned previously in [Selecting Loaded Tiles](#selecting-loaded-tiles), it's very important when zooming closer to a model that the tile selection algorithm not hide the currently-shown, lower-detail tiles before the higher-detail tiles are loaded and ready to render. If it did, part of the model would momentarily blink out of existence when zooming in, which would be very distracting to the user. So, when deciding whether to _RENDER_ or _REFINE_ a tile, we may sometimes need to _RENDER_ even when the [Screen-Space Error](#screen-space-error) indicates we should _REFINE_. Specifically, this is the case when both of the following conditions are true: + +1. Any selected tile in the subtree is not yet renderable. +2. None of the selected tiles in the subtree were rendered last frame. + +Condition (1) is important because, once all of the subtree tiles are renderable, we want to render those instead of the current tile. Condition (2) is important because, if any of the subtree tiles were rendered last frame, and we stopped rendering them this frame, that would cause the scene to suddenly become less detailed while zooming in, which would also be very distracting to the user. + +When these two conditions are met for a tile's descendants, then we should not render _any_ of those descendants, and instead render this single tile. This operation is known as _Kicking_. We must, however, continue loading the selected descendants, so that we can eventually render the proper tiles for the desired level-of-detail. + +We decide whether a _Kick_ is necessary by first traversing the tile's children normally, as in a _REFINE_. Calling `_visitTileIfNeeded` on each child tile returns a `TraversalDetails` instance with three fields: + +* `allAreRenderable`: `true` if every selected tile is renderable. `false` if even one selected tile is not yet renderable. +* `anyWereRenderedLastFrame`: `true` if any selected tile was rendered last frame. `false` is none of the selected tiles were rendered last frame. +* `notYetRenderableCount`: The number of selected tiles for which `isRenderable` is false. + +The `TraversalDetails` for all children are combined in the intuitive way: `allAreRenderable` values are combined with a boolean AND, `anyWereRenderedLastFrame` values are combined with a boolean OR, and `notYetRenderableCount` values are combined by summing. + +Now, we decide whether a _Kick_ is necessary by looking at the combined `allAreRenderable` and `anyWereRenderedLastFrame` properties. If both are false, we _Kick_! + +The _Kick_ itself happens very efficiently. Before visiting this tile's children, we note the number of tiles in the render list. Visiting children will only add more tiles to this list, not remove or change any of the existing ones. So, to _Kick_, we: + +1. Walk through all of the tiles added to the render list while visiting children and mark them _Kicked_ by calling [kick](@ref Cesium3DTilesSelection::TileSelectionState::kick) on their [TileSelectionState](@ref Cesium3DTilesSelection::TileSelectionState). +2. Remove all of these added tiles from the render list. +3. Add this tile to the render list. + +When tiles are removed from the render list in favor of the current tile, they are also no longer represented in the `allAreRenderable` and `anyWereRenderedLastFrame` flags returned by `_visitTile` for the current tile. However, they _are_ represented in the current tile's `notYetRenderableCount`. This is important for computing the `loadingDescendantLimit`, as explained in the next section. + +## Loading Descendant Limit {#loading-descendant-limit} + +The [Kicking](#kicking) mechanism normally kicks tiles out of the render list, but _not_ out of the loading queues. As mentioned previously, we need those tiles to load so that we can eventually stop _Kicking_ them and start rendering them instead. However, there is one case where tiles are kicked out of the load queues, too. + +After we decide to _Kick_ descendant tiles, we check whether the total `notYetRenderableCount` for all of the descendants is greater than the [loadingDescendantLimit](@ref Cesium3DTilesSelection::TilesetOptions::loadingDescendantLimit) expressed in `TilesetOptions`. If it is, that is when we will remove all of the descendant tiles from the load queues, too. + +The purpose of this mechanism is to give the user feedback during the load process. Without it, an application starting out with a zoomed-in view, especially one that requires a lot of tiles such as a horizon view, would tend to show no tiles at all for awhile, waiting for all of the tiles necessary for the view to load. Then, once all tiles were loaded, they would appear, at full detail, all at once. This may not give the best user experience. + +The `loadingDescendantLimit` works like a heuristic for deciding when intermediate, lower-detail tiles should be loaded and shown first, in order to give the user feedback that the load process is happening. The algorithm is happy to wait for a number of tiles to load before showing a more detailed subtree. This is the purpose of the _Kicking_ mechanism. But if the number of tiles it would have to wait for is too large - larger than `loadingDescendantLimit` - then it instead won't wait for any of them. The entire subtree load queue will be thrown out, and only the current tile will be loaded. + +> [!note] +> When tiles are removed from the load queues due to exceeding the `loadingDescendantLimit`, they are also removed from representation in the `notYetRenderableCount` field. This is unlike with a normal _Kick_, where the _Kicked_ tiles are still represented in the `notYetRenderableCount`. + +Once the current tile finishes loading and is rendered, only then will the tiles deeper in the subtree be given an opportunity to load and render. This ensures that the user sees the model sooner, at the cost of loading more tiles. The idea is to strike a tunable balance between user feedback and loading efficiency. + +## Additional Topics Not Yet Covered {#additional-topics} + +Here are some additional selection algorithm topics that are not yet covered here, but should be in the future: + +* Load prioritization +* Forbid Holes {#forbid-holes} +* Unconditionally-Refined Tiles +* Occlusion Culling +* External Tilesets and Implicit Tiles +* Additive Refinement diff --git a/doc/topics/style-guide.md b/doc/topics/style-guide.md index 7a79ec07a..274461c54 100644 --- a/doc/topics/style-guide.md +++ b/doc/topics/style-guide.md @@ -7,13 +7,14 @@ This is a guide to writing C++ code for cesium-native. These guidelines are inte In all cases these are _guidelines_. There are sometimes good reasons to violate the advice given here. In particular, when writing code that is meant to integrate into another system, it is rarely a good idea to fight that other system's conventions. -**cesium-native uses ISO Standard C++17.** +**cesium-native uses ISO Standard C++20.** We follow the [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines), with a few exceptions. We suggest proceeding as follows: * Skim the sections below, which call out where (and why) our practices differ from the C++ Core Guidelines. * Skim the C++ Core Guidelines. Read sections that seem interesting or surprising. * Read the sections below more thoroughly. + ## 💄 Source Code Formatting diff --git a/package-lock.json b/package-lock.json index f02405fe3..dbd571af8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "Apache-2.0", "devDependencies": { "clang-format": "^1.5.0", + "dotparser": "^1.1.1", "doxygen-awesome-css": "https://github.com/jothepro/doxygen-awesome-css#v2.3.4" } }, @@ -57,6 +58,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/dotparser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/dotparser/-/dotparser-1.1.1.tgz", + "integrity": "sha512-8ojhUts0HbLnXJgjTiJOddwVVBUk6hg4SJ5kGiuhzgK/f+y79TiWvICwx1oCWlVbBC8YI3nEaIQg9fjGYbGBXw==", + "dev": true + }, "node_modules/doxygen-awesome-css": { "name": "@jothepro/doxygen-awesome-css", "version": "2.3.4", diff --git a/package.json b/package.json index bc9b7a12c..f9fa032a1 100644 --- a/package.json +++ b/package.json @@ -32,4 +32,4 @@ "clang-format": "^1.5.0", "doxygen-awesome-css": "https://github.com/jothepro/doxygen-awesome-css#v2.3.4" } -} +} \ No newline at end of file diff --git a/tools/dep-graph-gen/.gitignore b/tools/dep-graph-gen/.gitignore new file mode 100644 index 000000000..b512c09d4 --- /dev/null +++ b/tools/dep-graph-gen/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/tools/dep-graph-gen/index.js b/tools/dep-graph-gen/index.js new file mode 100644 index 000000000..c3ef80d87 --- /dev/null +++ b/tools/dep-graph-gen/index.js @@ -0,0 +1,137 @@ +const parse = require("dotparser"); +const fs = require("fs"); +const palette = require("google-palette"); +const yargs = require("yargs"); +const path = require("path"); + +const argv = yargs.options({ + input: { + description: "The GraphViz .dot file generated by CMake.", + demandOption: true, + type: "string", + }, + output: { + description: "The directory to write the output files to.", + demandOption: true, + type: "string" + }, + targets: { + description: "A regular expression to filter the targets that will be included. Only these targets and their direct dependencies will be listed on the graph.", + demandOption: true, + type: "string" + } +}).argv; + +if (!fs.existsSync(argv.input)) { + console.error(`Missing input file ${argv.input}`); + process.exit(1); +} + +const ast = parse(fs.readFileSync(argv.input, "utf-8")); +const nodes = ast[0].children; + +// node id -> dependency name +const dependencies = {}; +// dependency name -> [dependencies] +const dependencyLinks = {}; + +nodes.forEach(n => { + if (n.type == "node_stmt") { + const id = n.node_id.id; + const label = n.attr_list.filter(a => a.id == "label")[0].eq; + dependencies[id] = label; + } +}); + +nodes.forEach(n => { + if (n.type == "edge_stmt") { + const from = n.edge_list[0].id; + const to = n.edge_list[1].id; + const arr = dependencyLinks[dependencies[from]] || []; + arr.push(dependencies[to]); + dependencyLinks[dependencies[from]] = arr; + } +}); + +function formatLibraryNameAsId(libraryName) { + return libraryName.replace(/(::|\+\+)/g, "_"); +} + +const includedRegex = new RegExp(argv.targets); + +function generateChart(includedSet, colorLinks, useElk, title) { + let output = `--- +comment: This file was generated by dep-graph-gen. DO NOT EDIT THIS FILE! +${useElk ? `config: + layout: elk` : ``} +${title ? `title: ${title}` : ``} +--- +graph TD + classDef dependencyNode fill:#fff,stroke:#ccc,color:#666,font-weight:bold,font-size:28px + classDef libraryNode fill:#9f9,font-weight:bold,font-size:28px\n`; + + // Keep track of which nodes are in which class, so we can style them appropriately + const classes = { + "dependencyNode": {}, + "libraryNode": {} + }; + + // dependency name -> [index of link] + // We can only style links based on the order they were declared + const nodeLinks = {}; + + let linkNum = 0; + + Object.keys(includedSet).forEach(n => { + const fromNodeId = formatLibraryNameAsId(n); + (dependencyLinks[n] || []).forEach(l => { + const toNodeId = formatLibraryNameAsId(l); + const isImportant = includedRegex.test(l); + const toLabel = isImportant ? `[${l}]` : `{{${l}}}`; + output += ` ${fromNodeId}[${n}] --> ${toNodeId}${toLabel}\n`; + if (isImportant) { + classes["libraryNode"][toNodeId] = true; + } else { + classes["dependencyNode"][toNodeId] = true; + } + const arr = nodeLinks[l] || []; + arr.push(linkNum++); + nodeLinks[l] = arr; + }); + classes["libraryNode"][fromNodeId] = true; + }); + + Object.keys(classes).forEach(cl => { + if (Object.keys(classes[cl]).length > 0) { + output += ` class ${Object.keys(classes[cl]).join(",")} ${cl}\n`; + } + }); + + if (colorLinks) { + // Use a palette for link colors to assist in readability + const linkColors = palette("mpn65", Object.keys(nodeLinks).length); + let linkColorIndex = 0; + + Object.keys(nodeLinks).forEach(l => { + output += ` linkStyle ${nodeLinks[l].join(",")} stroke:#${linkColors[linkColorIndex++]},stroke-width:8px\n`; + }); + } + + return output; +} + +// dependency name -> true +const includedNodes = {}; +// We're only interested in the Cesium libraries and their direct dependencies +Object.keys(dependencyLinks).filter(d => includedRegex.test(d)).forEach(d => { + includedNodes[d] = true; +}); + +fs.writeFileSync(path.join(argv.output, "all.mmd"), generateChart(includedNodes, true, true)); +// Per-target graphs +Object.keys(includedNodes).forEach(n => { + const filename = formatLibraryNameAsId(n) + ".mmd"; + fs.writeFileSync(path.join(argv.output, filename), generateChart({ [n]: true }, false, false, `${n} Dependency Graph`)); +}); + +console.log(`Wrote generated Mermaid graphs to ${argv.output}`); \ No newline at end of file diff --git a/tools/dep-graph-gen/package-lock.json b/tools/dep-graph-gen/package-lock.json new file mode 100644 index 000000000..aadf2eafa --- /dev/null +++ b/tools/dep-graph-gen/package-lock.json @@ -0,0 +1,4216 @@ +{ + "name": "dep-graph-gen", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dep-graph-gen", + "version": "1.0.0", + "license": "UNLICENSED", + "dependencies": { + "@mermaid-js/mermaid-cli": "^11.4.2", + "dotparser": "^1.1.1", + "google-palette": "^1.1.1", + "yargs": "^17.7.2" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@antfu/install-pkg": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-0.4.1.tgz", + "integrity": "sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==", + "dependencies": { + "package-manager-detector": "^0.2.0", + "tinyexec": "^0.3.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@antfu/utils": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", + "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "peer": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "dependencies": { + "@babel/types": "^7.26.3" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.0.tgz", + "integrity": "sha512-o+UlMLt49RvtCASlOMW0AkHnabN9wR9rwCCherxO0yG4Npy34GkvrAqdXQvrhNs+jh+gkK8gB8Lf05qL/O7KWg==" + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==" + }, + "node_modules/@floating-ui/core": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", + "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", + "dependencies": { + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz", + "integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==" + }, + "node_modules/@floating-ui/vue": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@floating-ui/vue/-/vue-1.1.5.tgz", + "integrity": "sha512-ynL1p5Z+woPVSwgMGqeDrx6HrJfGIDzFyESFkyqJKilGW1+h/8yVY29Khn0LaU6wHBRwZ13ntG6reiHWK6jyzw==", + "dependencies": { + "@floating-ui/dom": "^1.0.0", + "@floating-ui/utils": "^0.2.8", + "vue-demi": ">=0.13.0" + } + }, + "node_modules/@headlessui/tailwindcss": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@headlessui/tailwindcss/-/tailwindcss-0.2.1.tgz", + "integrity": "sha512-2+5+NZ+RzMyrVeCZOxdbvkUSssSxGvcUxphkIfSVLpRiKsj+/63T2TOL9dBYMXVfj/CGr6hMxSRInzXv6YY7sA==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "tailwindcss": "^3.0" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==" + }, + "node_modules/@iconify/utils": { + "version": "2.1.33", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.1.33.tgz", + "integrity": "sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==", + "dependencies": { + "@antfu/install-pkg": "^0.4.0", + "@antfu/utils": "^0.7.10", + "@iconify/types": "^2.0.0", + "debug": "^4.3.6", + "kolorist": "^1.8.0", + "local-pkg": "^0.5.0", + "mlly": "^1.7.1" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "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==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mermaid-js/mermaid-cli": { + "version": "11.4.2", + "resolved": "https://registry.npmjs.org/@mermaid-js/mermaid-cli/-/mermaid-cli-11.4.2.tgz", + "integrity": "sha512-nBsEW1AxHsjsjTBrqFInkh91Vvb5vNPmnN7UGWkutExcQQZev6XzMlEZp0i6HYFSoGTHZT2tOT0l/KLzvDyPfg==", + "dependencies": { + "@mermaid-js/mermaid-zenuml": "^0.2.0", + "chalk": "^5.0.1", + "commander": "^12.1.0", + "import-meta-resolve": "^4.1.0", + "mermaid": "^11.0.2" + }, + "bin": { + "mmdc": "src/cli.js" + }, + "engines": { + "node": "^18.19 || >=20.0" + }, + "peerDependencies": { + "puppeteer": "^23" + } + }, + "node_modules/@mermaid-js/mermaid-zenuml": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/mermaid-zenuml/-/mermaid-zenuml-0.2.0.tgz", + "integrity": "sha512-Lv7xNlFT5y2TIlts+yYl1HfeEgjoqw5cfSZsWYejoJvt9K0QfdPBoj5D9Tft1aN0pj1mxjuTZbZQ1Anmem/RMg==", + "dependencies": { + "@zenuml/core": "^3.17.2" + }, + "peerDependencies": { + "mermaid": ">=10.0.0" + } + }, + "node_modules/@mermaid-js/parser": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.3.0.tgz", + "integrity": "sha512-HsvL6zgE5sUPGgkIDlmAWR1HTNHz2Iy11BAWPTa4Jjabkpguy4Ze2gzfLrg6pdRuBvFwgUYyxiaNqZwrEEXepA==", + "dependencies": { + "langium": "3.0.0" + } + }, + "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==", + "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==", + "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==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.5.0.tgz", + "integrity": "sha512-6TQAc/5uRILE6deixJ1CR8rXyTbzXIXNgO1D0Woi9Bqicz2FV5iKP3BHYEg6o4UATCMcbQQ0jbmeaOkn/HQk2w==", + "peer": true, + "dependencies": { + "debug": "^4.3.7", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.4.0", + "semver": "^7.6.3", + "tar-fs": "^3.0.6", + "unbzip2-stream": "^1.4.3", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.10.9", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.10.9.tgz", + "integrity": "sha512-kBknKOKzmeR7lN+vSadaKWXaLS0SZZG+oqpQ/k80Q6g9REn6zRHS/ZYdrIzHnpHgy/eWs00SujveUN/GJT2qTw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/vue-virtual": { + "version": "3.10.9", + "resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.10.9.tgz", + "integrity": "sha512-KU2quiwJQpA0sdflpXw24bhW+x8PG+FlrSJK3Ilobim671HNn4ztLVWUCEz3Inei4dLYq+GW1MK9X6i6ZeirkQ==", + "dependencies": { + "@tanstack/virtual-core": "3.10.9" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "vue": "^2.7.0 || ^3.0.0" + } + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "peer": true + }, + "node_modules/@types/assert": { + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.5.11.tgz", + "integrity": "sha512-FjS1mxq2dlGr9N4z72/DO+XmyRS3ZZIoVn998MEopAN/OmyN28F4yumRL5pOw2z+hbFLuWGYuF2rrw5p11xM5A==" + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz", + "integrity": "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "node_modules/@types/geojson": { + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" + }, + "node_modules/@types/node": { + "version": "22.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", + "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", + "optional": true, + "peer": true, + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/ramda": { + "version": "0.28.25", + "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.28.25.tgz", + "integrity": "sha512-HrQNqQAGcITpn9HAJFamDxm7iZeeXiP/95pN5OMbNniDjzCCeOHbBKNGmUy8NRi0fhYS+/cXeo91MFC+06gbow==", + "dependencies": { + "ts-toolbelt": "^6.15.1" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "optional": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "optional": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", + "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.13", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", + "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", + "dependencies": { + "@vue/compiler-core": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz", + "integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==", + "peer": true, + "dependencies": { + "@babel/parser": "^7.23.5", + "postcss": "^8.4.14", + "source-map": "^0.6.1" + }, + "optionalDependencies": { + "prettier": "^1.18.2 || ^2.0.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", + "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", + "dependencies": { + "@vue/compiler-dom": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" + }, + "node_modules/@vue/reactivity": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz", + "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==", + "dependencies": { + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz", + "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==", + "dependencies": { + "@vue/reactivity": "3.5.13", + "@vue/shared": "3.5.13" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz", + "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==", + "dependencies": { + "@vue/reactivity": "3.5.13", + "@vue/runtime-core": "3.5.13", + "@vue/shared": "3.5.13", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", + "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==" + }, + "node_modules/@zenuml/core": { + "version": "3.24.30", + "resolved": "https://registry.npmjs.org/@zenuml/core/-/core-3.24.30.tgz", + "integrity": "sha512-2VFkVw86f0i/dV0Orw5Nh7+uTyO6+2JLeD092zCWsSX/TaXs8OnjQePDVVce6AwttB2vjHXfLiYQSZ8pZrkZcA==", + "dependencies": { + "@headlessui-float/vue": "^0.14.0", + "@headlessui/tailwindcss": "^0.2.0", + "@headlessui/vue": "^1.7.16", + "@types/assert": "^1.5.6", + "@types/ramda": "^0.28.20", + "@vue/compat": "^3.2.45", + "antlr4": "~4.11.0", + "color-string": "^1.5.5", + "dom-to-image-more": "^2.13.0", + "dompurify": "^3.1.5", + "file-saver": "^2.0.5", + "highlight.js": "^10.7.3", + "html-to-image": "^1.11.3", + "lodash": "^4.17.21", + "marked": "^4.0.10", + "pino": "^8.8.0", + "postcss": "^8.4.31", + "ramda": "^0.28.0", + "tailwindcss": "^3.2.4", + "vue": "^3.2.45", + "vue-property-decorator": "^9.1.2", + "vuex": "^4.1.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@zenuml/core/node_modules/@headlessui-float/vue": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/@headlessui-float/vue/-/vue-0.14.4.tgz", + "integrity": "sha512-MSyWCxUTueeex+veRCf++q4KM/fa4HOe9HDttzGrtgVDBULkGduFK6ItJh7EHJp2U/dY7qpyDUqp2KCHpCEplw==", + "dependencies": { + "@floating-ui/core": "^1.5.3", + "@floating-ui/dom": "^1.5.4", + "@floating-ui/vue": "^1.0.3" + }, + "peerDependencies": { + "@headlessui/vue": "^1.0.0", + "vue": "^3.0.0" + } + }, + "node_modules/@zenuml/core/node_modules/@headlessui/vue": { + "version": "1.7.23", + "resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.7.23.tgz", + "integrity": "sha512-JzdCNqurrtuu0YW6QaDtR2PIYCKPUWq28csDyMvN4zmGccmE7lz40Is6hc3LA4HFeCI7sekZ/PQMTNmn9I/4Wg==", + "dependencies": { + "@tanstack/vue-virtual": "^3.0.0-beta.60" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@zenuml/core/node_modules/@vue/compat": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compat/-/compat-3.5.13.tgz", + "integrity": "sha512-Q3xRdTPN4l+kddxU98REyUBgvc0meAo9CefCWE2lW8Fg3dyPn3vSCce52b338ihrJAx1RQQhO5wMWhJ/PAKUpA==", + "dependencies": { + "@babel/parser": "^7.25.3", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + }, + "peerDependencies": { + "vue": "3.5.13" + } + }, + "node_modules/@zenuml/core/node_modules/@vue/compiler-sfc": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", + "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.13", + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.11", + "postcss": "^8.4.48", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@zenuml/core/node_modules/@vue/server-renderer": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz", + "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==", + "dependencies": { + "@vue/compiler-ssr": "3.5.13", + "@vue/shared": "3.5.13" + }, + "peerDependencies": { + "vue": "3.5.13" + } + }, + "node_modules/@zenuml/core/node_modules/vue": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz", + "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==", + "dependencies": { + "@vue/compiler-dom": "3.5.13", + "@vue/compiler-sfc": "3.5.13", + "@vue/runtime-dom": "3.5.13", + "@vue/server-renderer": "3.5.13", + "@vue/shared": "3.5.13" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@zenuml/core/node_modules/vuex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz", + "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==", + "dependencies": { + "@vue/devtools-api": "^6.0.0-beta.11" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "peer": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antlr4": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.11.0.tgz", + "integrity": "sha512-GUGlpE2JUjAN+G8G5vY+nOoeyNhHsXoIJwP1XF1oRw89vifA1K46T6SEkwLwr7drihN7I/lf0DIjKc4OZvBX8w==", + "engines": { + "node": ">=14" + } + }, + "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==" + }, + "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==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "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==" + }, + "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==", + "peer": true + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "peer": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "peer": true + }, + "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==" + }, + "node_modules/bare-events": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz", + "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==", + "optional": true, + "peer": true + }, + "node_modules/bare-fs": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.5.tgz", + "integrity": "sha512-SlE9eTxifPDJrT6YgemQ1WGFleevzwY+XAP1Xqgl56HtcrisC2CHCZ2tq6dBpcH2TnNxwUEUGhweo+lrQtYuiw==", + "optional": true, + "peer": true, + "dependencies": { + "bare-events": "^2.0.0", + "bare-path": "^2.0.0", + "bare-stream": "^2.0.0" + } + }, + "node_modules/bare-os": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.4.tgz", + "integrity": "sha512-z3UiI2yi1mK0sXeRdc4O1Kk8aOa/e+FNWZcTiPB/dfTWyLypuE99LibgRaQki914Jq//yAWylcAt+mknKdixRQ==", + "optional": true, + "peer": true + }, + "node_modules/bare-path": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", + "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", + "optional": true, + "peer": true, + "dependencies": { + "bare-os": "^2.1.0" + } + }, + "node_modules/bare-stream": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.4.2.tgz", + "integrity": "sha512-XZ4ln/KV4KT+PXdIWTKjsLY+quqCaEtqqtgGJVPw9AoM73By03ij64YjepK0aQvHSWDb6AfAZwqKaFu68qkrdA==", + "optional": true, + "peer": true, + "dependencies": { + "streamx": "^2.20.0" + } + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "peer": true, + "engines": { + "node": ">=10.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==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "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==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "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==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "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/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==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chromium-bidi": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.8.0.tgz", + "integrity": "sha512-uJydbGdTw0DEUjhoogGveneJVWX/9YuqkWePzMmkBYwtdAqo5d3J/ovNKFr+/2hWXYmYCr6it8mSSTIj6SS6Ug==", + "peer": true, + "dependencies": { + "mitt": "3.0.1", + "urlpattern-polyfill": "10.0.0", + "zod": "3.23.8" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "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==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "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==", + "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==" + }, + "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==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "engines": { + "node": ">=18" + } + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==" + }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "dependencies": { + "layout-base": "^1.0.0" + } + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "peer": true, + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "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==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/cytoscape": { + "version": "3.30.4", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.4.tgz", + "integrity": "sha512-OxtlZwQl1WbwMmLiyPSEBuzeTIQnwZhJYYWFzZ2PhEHVFwpeaqNIkUzSiso00D98qk60l8Gwon2RP304d3BJ1A==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==" + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.11.tgz", + "integrity": "sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw==", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "peer": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "peer": true, + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1367902", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1367902.tgz", + "integrity": "sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==", + "peer": true + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/dom-to-image-more": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/dom-to-image-more/-/dom-to-image-more-2.16.0.tgz", + "integrity": "sha512-RyjtkaM/zVy90uJ20lT+/G7MwBZx6l/ePliq5CQOeAnPeew7aUGS6IqRWBkHpstU+POmhaKA8A9H9qf476gisQ==" + }, + "node_modules/dompurify": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.2.tgz", + "integrity": "sha512-YMM+erhdZ2nkZ4fTNRTSI94mb7VG7uVF5vj5Zde7tImgnhZE3R6YW/IACGIHb2ux+QkEXMhe591N+5jWOmL4Zw==", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/dotparser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/dotparser/-/dotparser-1.1.1.tgz", + "integrity": "sha512-8ojhUts0HbLnXJgjTiJOddwVVBUk6hg4SJ5kGiuhzgK/f+y79TiWvICwx1oCWlVbBC8YI3nEaIQg9fjGYbGBXw==" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "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==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "peer": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "peer": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "peer": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "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==", + "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "peer": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "peer": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "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.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/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==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "peer": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, + "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==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "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==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "peer": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", + "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", + "peer": true, + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/google-palette": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/google-palette/-/google-palette-1.1.1.tgz", + "integrity": "sha512-yZiM5oLl8lCZzf06IMOGdDkxqvCMd9HNFcCiOMqWgGGiGzC22vWBVhKJNvykXXbeC0NAElNH97jA/y0bq6TCrA==" + }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "engines": { + "node": "*" + } + }, + "node_modules/html-to-image": { + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.11.tgz", + "integrity": "sha512-9gux8QhvjRO/erSnDPv28noDZcPZmYE7e1vFsBLKLlRlKDSqNJYebj6Qz1TGd5lsRV+X+xYyjCKjuZdABinWjA==" + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "peer": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "peer": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "peer": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "peer": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "peer": true + }, + "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==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dependencies": { + "hasown": "^2.0.2" + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "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==", + "peer": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "peer": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "peer": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "peer": true + }, + "node_modules/katex": { + "version": "0.16.11", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz", + "integrity": "sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==" + }, + "node_modules/langium": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/langium/-/langium-3.0.0.tgz", + "integrity": "sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg==", + "dependencies": { + "chevrotain": "~11.0.3", + "chevrotain-allstar": "~0.3.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.0.8" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==" + }, + "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==", + "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==" + }, + "node_modules/local-pkg": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", + "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", + "dependencies": { + "mlly": "^1.7.3", + "pkg-types": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/magic-string": { + "version": "0.30.14", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz", + "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/mermaid": { + "version": "11.4.1", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.4.1.tgz", + "integrity": "sha512-Mb01JT/x6CKDWaxigwfZYuYmDZ6xtrNwNlidKZwkSrDaY9n90tdrJTV5Umk+wP1fZscGptmKFXHsXMDEVZ+Q6A==", + "dependencies": { + "@braintree/sanitize-url": "^7.0.1", + "@iconify/utils": "^2.1.32", + "@mermaid-js/parser": "^0.3.0", + "@types/d3": "^7.4.3", + "cytoscape": "^3.29.2", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.11", + "dayjs": "^1.11.10", + "dompurify": "^3.2.1", + "katex": "^0.16.9", + "khroma": "^2.1.0", + "lodash-es": "^4.17.21", + "marked": "^13.0.2", + "roughjs": "^4.6.6", + "stylis": "^4.3.1", + "ts-dedent": "^2.2.0", + "uuid": "^9.0.1" + } + }, + "node_modules/mermaid/node_modules/marked": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz", + "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "peer": true + }, + "node_modules/mlly": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.3.tgz", + "integrity": "sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==", + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^1.1.2", + "pkg-types": "^1.2.1", + "ufo": "^1.5.4" + } + }, + "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==" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "peer": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "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==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "engines": { + "node": ">=14.0.0" + } + }, + "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==", + "peer": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", + "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", + "peer": true, + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.5", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "peer": true, + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "node_modules/package-manager-detector": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.6.tgz", + "integrity": "sha512-9vPH3qooBlYRJdmdYP00nvjZOulm40r5dhtal8st18ctf+6S1k7pi5yIHLvI4w5D70x0Y+xdVD9qITH0QO/A8A==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "peer": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==" + }, + "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==", + "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==" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==" + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "peer": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pino": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.21.0.tgz", + "integrity": "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.6.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-types": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.1.tgz", + "integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.2", + "pathe": "^1.1.2" + } + }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "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" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "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==", + "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.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "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==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "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==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "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==" + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "optional": true, + "peer": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-agent": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "peer": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "peer": true + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "peer": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/puppeteer": { + "version": "23.10.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.10.1.tgz", + "integrity": "sha512-kbcO+vu91fgUyBzEwByPe4q5lEEuBq4cuOZnZeRL42G7r5UrfbUFlxBJayXBLBsD6pREdk/92ZFwFQq3MaN6ww==", + "hasInstallScript": true, + "peer": true, + "dependencies": { + "@puppeteer/browsers": "2.5.0", + "chromium-bidi": "0.8.0", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1367902", + "puppeteer-core": "23.10.1", + "typed-query-selector": "^2.12.0" + }, + "bin": { + "puppeteer": "lib/cjs/puppeteer/node/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer-core": { + "version": "23.10.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.10.1.tgz", + "integrity": "sha512-ey6NwixHYEUnhCA/uYi7uQQ4a0CZw4k+MatbHXGl5GEzaiRQziYUxc2HGpdQZ/gnh4KQWAKkocyIg1/dIm5d0g==", + "peer": true, + "dependencies": { + "@puppeteer/browsers": "2.5.0", + "chromium-bidi": "0.8.0", + "debug": "^4.3.7", + "devtools-protocol": "0.0.1367902", + "typed-query-selector": "^2.12.0", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=18" + } + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "peer": true + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, + "node_modules/ramda": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.28.0.tgz", + "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "peer": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "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==", + "engines": { + "node": ">=8" + } + }, + "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==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "peer": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "peer": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "peer": true, + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/sonic-boom": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", + "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "peer": true + }, + "node_modules/streamx": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.0.tgz", + "integrity": "sha512-Qz6MsDZXJ6ur9u+b+4xCG18TluU7PGlRfXVAAjNiGsFrBUt/ioyLkxbFaKJygoPs+/kW4VyBj0bSj89Qu0IGyg==", + "peer": true, + "dependencies": { + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, + "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==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "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==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "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==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylis": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz", + "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==" + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "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": ">=16 || 14 >=14.17" + } + }, + "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==", + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.16", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.16.tgz", + "integrity": "sha512-TI4Cyx7gDiZ6r44ewaJmt0o6BrMCT5aK5e0rmJ/G9Xq3w7CX/5VXl/zIPEJZFUK5VEqwByyhqNPycPlvcK4ZNw==", + "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/tar-fs": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", + "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", + "peer": true, + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "peer": true, + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/text-decoder": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.1.tgz", + "integrity": "sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ==", + "peer": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "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==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/thread-stream": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", + "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "peer": true + }, + "node_modules/tinyexec": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==" + }, + "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==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "engines": { + "node": ">=6.10" + } + }, + "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==" + }, + "node_modules/ts-toolbelt": { + "version": "6.15.5", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz", + "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==" + }, + "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==", + "peer": true + }, + "node_modules/typed-query-selector": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", + "peer": true + }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==" + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "peer": true, + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/unbzip2-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "optional": true, + "peer": true + }, + "node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "peer": true + }, + "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==" + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" + }, + "node_modules/vue": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz", + "integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==", + "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.", + "peer": true, + "dependencies": { + "@vue/compiler-sfc": "2.7.16", + "csstype": "^3.1.0" + } + }, + "node_modules/vue-class-component": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-7.2.6.tgz", + "integrity": "sha512-+eaQXVrAm/LldalI272PpDe3+i4mPis0ORiMYxF6Ae4hyuCh15W8Idet7wPUEs4N4YptgFHGys4UrgNQOMyO6w==", + "peer": true, + "peerDependencies": { + "vue": "^2.0.0" + } + }, + "node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vue-property-decorator": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-9.1.2.tgz", + "integrity": "sha512-xYA8MkZynPBGd/w5QFJ2d/NM0z/YeegMqYTphy7NJQXbZcuU6FC6AOdUAcy4SXP+YnkerC6AfH+ldg7PDk9ESQ==", + "peerDependencies": { + "vue": "*", + "vue-class-component": "*" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "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==", + "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/wrap-ansi-cjs": { + "name": "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==", + "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/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "peer": true + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "peer": true, + "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/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "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==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "peer": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/tools/dep-graph-gen/package.json b/tools/dep-graph-gen/package.json new file mode 100644 index 000000000..ce4235b36 --- /dev/null +++ b/tools/dep-graph-gen/package.json @@ -0,0 +1,17 @@ +{ + "name": "dep-graph-gen", + "version": "1.0.0", + "description": "Parses and filters a CMake graphviz dependency graph", + "main": "index.js", + "scripts": { + "generate-dep-graph": "cd ../.. && cmake -B build -S . --graphviz=dependency-graph.dot && cd tools/dep-graph-gen && node index.js --input ../../dependency-graph.dot --output ../../doc/diagrams/dependencies --targets Cesium* && mmdc -i ../../doc/diagrams/dependencies/all.mmd -o ../../doc/img/dependency-graph.svg -b transparent && rm ../../dependency-graph.dot" + }, + "author": "CesiumGS, Inc. and Contributors", + "license": "Apache-2.0", + "dependencies": { + "@mermaid-js/mermaid-cli": "^11.4.2", + "dotparser": "^1.1.1", + "google-palette": "^1.1.1", + "yargs": "^17.7.2" + } +} \ No newline at end of file diff --git a/tools/generate-classes/package.json b/tools/generate-classes/package.json index 99e70956c..4e5135e26 100644 --- a/tools/generate-classes/package.json +++ b/tools/generate-classes/package.json @@ -8,8 +8,8 @@ "generate-gltf": "node index.js --schemas https://raw.githubusercontent.com/CesiumGS/glTF/cesium-native/specification/2.0/schema/glTF.schema.json --output ../../CesiumGltf --readerOutput ../../CesiumGltfReader --writerOutput ../../CesiumGltfWriter --extensions https://raw.githubusercontent.com/CesiumGS/glTF/cesium-native/extensions/2.0/ --namespace CesiumGltf --readerNamespace CesiumGltfReader --writerNamespace CesiumGltfWriter --config glTF.json", "generate-quantized-mesh-terrain": "node index.js --schemas ../../CesiumQuantizedMeshTerrain/schema/layer.schema.json --output ../../CesiumQuantizedMeshTerrain --readerOutput ../../CesiumQuantizedMeshTerrain --writerOutput ../../CesiumQuantizedMeshTerrain --extensions ../../CesiumQuantizedMeshTerrain/schema/extensions --namespace CesiumQuantizedMeshTerrain --readerNamespace CesiumQuantizedMeshTerrain --writerNamespace CesiumQuantizedMeshTerrain --config QuantizedMeshTerrain.json" }, - "author": "CesiumGS, Inc.", - "license": "UNLICENSED", + "author": "CesiumGS, Inc. and Contributors", + "license": "Apache-2.0", "dependencies": { "lodash": "^4.17.20", "sync-request": "^6.1.0", @@ -18,4 +18,4 @@ "devDependencies": { "prettier": "^2.2.1" } -} +} \ No newline at end of file