From 15600de3d2e12133161b27933b0b8f326bffeb8f Mon Sep 17 00:00:00 2001 From: Alexandru RADOVICI Date: Sat, 19 Jul 2025 13:52:31 +0300 Subject: [PATCH 01/14] add the Tock Workshop inital track --- docs/tock_workshop/_category_.json | 9 +++++++++ docs/tock_workshop/index.md | 3 +++ 2 files changed, 12 insertions(+) create mode 100644 docs/tock_workshop/_category_.json create mode 100644 docs/tock_workshop/index.md diff --git a/docs/tock_workshop/_category_.json b/docs/tock_workshop/_category_.json new file mode 100644 index 0000000..bf86bcd --- /dev/null +++ b/docs/tock_workshop/_category_.json @@ -0,0 +1,9 @@ +{ + "position": 7, + "label": "Tock Workshop", + "collapsible": true, + "collapsed": true, + "customProps": { + "description": "TockWorld Europ's Workshop, learn how to use Tock and write drivers." + } +} diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md new file mode 100644 index 0000000..b382a27 --- /dev/null +++ b/docs/tock_workshop/index.md @@ -0,0 +1,3 @@ +# Intorduction + + From 5009c8b845a68b592f9aee741dde5392c96ff68c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George-D=C4=83nu=C8=9B=20Aldea?= Date: Sun, 27 Jul 2025 22:32:12 +0300 Subject: [PATCH 02/14] added prerequisites --- docs/tock_workshop/index.md | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index b382a27..d666788 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -1,3 +1,63 @@ # Intorduction +## Prerequisites +### Rust Toolchain + +You will need to install the Rust toolchain. To do so, you can follow the instructions on the [Getting started](https://www.rust-lang.org/learn/get-started) page of the Rust Language website. + +:::info Windows Install Tips +If you are using Windows, you may be prompted to install [Visual Studio C++ Build tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/). If so, follow the instructions from the previous link. + +Even if Visual Studio is already on your machine, rustup will not verify if the required components are present. If you experience issues with the `rustup` installation on Windows, please follow [these instructions](https://rust-lang.github.io/rustup/installation/windows-msvc.html) to manually add the missing components. +::: + +To verify that the installation, open a terminal and run `rustup --version`. If everything went well, you should see an output similar to this: + +```shell +rustup 1.28.1 (f9edccde0 2025-03-05) +info: This is the version for the rustup toolchain manager, not the rustc compiler. +info: The currently active `rustc` version is `rustc 1.86.0 (05f9846f8 2025-03-31)` +``` + +### `probe-rs` install + +This tool is an embedded debugging and target interaction toolkit. It enables its user to program and debug microcontrollers via a debug probe. + +The simplest installation method involves using the `cargo` packet manager: + +```shell +cargo install probe-rs-tools --locked +``` + +If you are using Linux, you will also need to add this [udev](https://probe.rs/files/69-probe-rs.rules) file in `/etc/udev/rules.d`. Then, run: + +```shell +udevadm control --reload # to ensure the new rules are used. +udevadm trigger # to ensure the new rules are applied to already added devices. +``` + +### `arm-none-eabi` toolchain + +You will need to install the ARM toolchain in order to compile applications written in C. You can find the pre-built binary archives on the ARM [Downloads Page](https://developer.arm.com/downloads/-/gnu-rm). Alternatively, if you are on Linux, you can install it by running the following command in terminal: + +```shell +sudo apt install gcc-arm-none-eabi +``` + +### `tockloader` + +The `tockloader` tool is a useful and versatile tool for managing and installing applications on Tock. In order to install it, you will need to have Python installed. You can download the latest version of on the [official website](https://www.python.org/downloads/). You will also need to install `pipx`, following the [installation guide](https://pipx.pypa.io/stable/installation/). Then you can install it by running: + +```shell +pipx install tockloader +pipx ensurepath +``` + +## CY8CPROTO-062-4343W board + +TODO: add board description and features + +## Tock OS + +TODO: add overview From 86ba8b144e2800ceeafb124d0104280ecb90499f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George-D=C4=83nu=C8=9B=20Aldea?= Date: Mon, 28 Jul 2025 11:03:40 +0300 Subject: [PATCH 03/14] fixed introduction typo --- docs/tock_workshop/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index d666788..5ddb3b5 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -1,4 +1,4 @@ -# Intorduction +# Introduction ## Prerequisites From a23b2d33e6667b58a927118d1d2626a98592b0f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George-D=C4=83nu=C8=9B=20Aldea?= Date: Mon, 28 Jul 2025 15:45:48 +0300 Subject: [PATCH 04/14] architecture WIP --- docs/tock_workshop/index.md | 63 +++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index 5ddb3b5..ba15e42 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -58,6 +58,65 @@ pipx ensurepath TODO: add board description and features -## Tock OS +## Tock -TODO: add overview +Tock is an open-source embedded operating system for microcontrollers written in Rust. The operating system is designed to isolate components so untrusted third-party applications can run in a protected environment. Tock supports multiple platforms, such as RISC-V, Cortex-M or X86. + +### Architecture + +Tock uses a microkernel architecture: complex drivers and services are often implemented as untrusted processes, which other processes, such as applications, can invoke through inter-process communication (IPC). +Tock supports running multiple, independent applications written in any compiled language. + +![Tock stack](https://book.tockos.org/imgs/tock-stack.png) + +The above Figure shows Tock's architecture. Code falls into one of three categories: the **core kernel**, **capsules**, and **processes**. + +The core kernel and capsules are both written in Rust. Rust is a type-safe systems language; other documents discuss the language and its implications to kernel design in greater detail, but the key idea is that Rust code can't use memory differently than intended (e.g., overflow buffers, forge pointers, or have pointers to dead stack frames). Because these restrictions prevent many things that an OS kernel has to do (such as access a peripheral that exists at a memory address specified in a datasheet), the very small core kernel is allowed to break them by using *"unsafe"* Rust code. Capsules, however, cannot use unsafe features. This means that the core kernel code is very small and carefully written, while new capsules added to the kernel are safe code and so do not have to be trusted. + +Processes can be written in any language. The kernel protects itself and other processes from bad process code by using a hardware memory protection unit (MPU). If a process tries to access memory it's not allowed to, this triggers an exception. The kernel handles this exception and kills the process. + +The kernel provides four major system calls: + +* `command`: makes a call from the process into the kernel +* `subscribe`: registers a callback in the process for an upcall from the kernel +* `allow`: gives kernel access to memory in the process +* `yield`: suspends process until after a callback is invoked + +Every system call except yield is non-blocking. Commands that might take a long time (such as sending a message over a UART) return immediately and issue a callback when they complete. The yield system call blocks the process until a callback is invoked; userland code typically implements blocking functions by invoking a command and then using yield to wait until the callback completes. + +The command, subscribe, and allow system calls all take a driver ID as their first parameter. This indicates which driver in the kernel that system call is intended for. Drivers are capsules that implement the system call. + +### Capsule + +A capsule is a kernel component acting as a device driver, or system service capsule. Capsules sit between the low-level drivers of the core kernel and use the HIL traits to interact with them, and the userspace applications, which utilize the `Syscall` interface. + +## Hands-on Workshop + +### Flashing the kernel + +Initially, you will need to clone the Tock [repository](https://example.com). To compile the board kernel, you can use the `cargo flash` utility. + +```shell +cd boards/cy8cproto_62_4343_w +cargo flash +``` + +If you did everything correctly, you should be able to use the `tockloader listen` command to interact with the kernel. When prompted to select a serial port, pick the one that ends with `KitProg3 CMSIS-DAP`. + +```shell +tockloader listen +[INFO ] No device name specified. Using default name "tock". +[INFO ] No serial port with device name "tock" found. +[INFO ] Found 2 serial ports. +Multiple serial port options found. Which would you like to use? +[0] /dev/cu.debug-console - n/a +[1] /dev/cu.usbmodem1103 - KitProg3 CMSIS-DAP + +Which option? [0] 1 +[INFO ] Using "/dev/cu.usbmodem1103 - KitProg3 CMSIS-DAP". +[INFO ] Listening for serial output + +$tock +``` + +### Compiling an application From 236f8858724877c327bbb0af83f43a1ac9efa8eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George-D=C4=83nu=C8=9B=20Aldea?= Date: Wed, 30 Jul 2025 13:50:06 +0300 Subject: [PATCH 05/14] added build capsule task --- docs/tock_workshop/index.md | 126 ++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 5 deletions(-) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index ba15e42..520dab1 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -86,21 +86,19 @@ Every system call except yield is non-blocking. Commands that might take a long The command, subscribe, and allow system calls all take a driver ID as their first parameter. This indicates which driver in the kernel that system call is intended for. Drivers are capsules that implement the system call. -### Capsule - -A capsule is a kernel component acting as a device driver, or system service capsule. Capsules sit between the low-level drivers of the core kernel and use the HIL traits to interact with them, and the userspace applications, which utilize the `Syscall` interface. - ## Hands-on Workshop ### Flashing the kernel -Initially, you will need to clone the Tock [repository](https://example.com). To compile the board kernel, you can use the `cargo flash` utility. +Initially, you will need to clone the Tock [repository](https://example.com). The configuration for the various boards supported can be found in the `boards` directory. To compile the kernel, you can use the `cargo flash` utility. ```shell cd boards/cy8cproto_62_4343_w cargo flash ``` +Alternatively, you can use the `make flash` while inside the board's directory. + If you did everything correctly, you should be able to use the `tockloader listen` command to interact with the kernel. When prompted to select a serial port, pick the one that ends with `KitProg3 CMSIS-DAP`. ```shell @@ -120,3 +118,121 @@ $tock ``` ### Compiling an application + +For this task, you will have to clone the [`libtock-c`](https://example.com) repository first. Navigate to the `examples/blink` folder and take a look at the C application structure found in `main.c`. To compile the application, simply run `make`. This command will built the example applications for all target architectures supported by the library. Apps are compiled into TBFs (Tock Binary Format), and can be found in the `build/` sub-directories. Tock also generates an archive of the same app, compiled for multiple architectures, for ease of use and portability, called a TAB(Tock Application Bundle) which can be loaded using the `tockloader` utility. + +### Flashing the application + +Unfortunately, the board is not currently supported by the `tockloader` project, so we will have to resort to bundling the kernel and application in a single binary and flashing it. The board you are using is a dual-core, with Tock running on the **CortexM0+** core, so the correct TBF can be found at `examples/blink/build/cortex-m0/cortex-m0.tbf`. You will need to specify the path to the compiled application in the board's `Makefile`. + +```Makefile +APP=../../libtock-c/examples/sensors/build/cortex-m0/cortex-m0.tbf +``` + +Then, run the `make program` command in terminal. It will use the `arm-none-eabi-objcopy` to merge the two binaries, and load it on the board. After the binary is flashed, you should see the on board LED blinking, and you should be able to see `blink` in the apps list, using `tockloader listen`. + +```sh +tockloader listen +[INFO ] No device name specified. Using default name "tock". +[INFO ] No serial port with device name "tock" found. +[INFO ] Found 2 serial ports. +Multiple serial port options found. Which would you like to use? +[0] /dev/cu.debug-console - n/a +[1] /dev/cu.usbmodem1103 - KitProg3 CMSIS-DAP + +Which option? [0] 1 +[INFO ] Using "/dev/cu.usbmodem1103 - KitProg3 CMSIS-DAP". +[INFO ] Listening for serial output + +$tock list + +TODO: add app list output +``` + +### Building a capsule + +A capsule is a kernel component acting as a device driver, or system service capsule. Capsules sit between the low-level drivers of the core kernel and use the HIL traits to interact with them, and the userspace applications, which utilizes its `SyscallDriver` interface. For this task, we will build a `MockCapsule`, that will print a debug message on application command. + +The first step is to define the `MockCapsule` driver, and implement the `SyscallDriver`. You can create a new module in the `capsules/extra` crate named `mock.rs`. We also will need to chose an unused driver number to use (`0x9000A` will work). + +```Rust title="capsule/extra/mock.rs" +use kernel::{ + syscall::{CommandReturn, SyscallDriver}, + ErrorCode, +}; + +const DRIVER_NUM: usize = 0x9000A; + +struct MockCapsule; + +impl SyscallDriver for MockCapsule { + fn command( + &self, + command_num: usize, + _: usize, + _: usize, + _process_id: kernel::ProcessId, + ) -> kernel::syscall::CommandReturn { + match command_num { + _ => CommandReturn::failure(ErrorCode::NOSUPPORT), + } + } + + fn allocate_grant(&self, _process_id: kernel::ProcessId) -> Result<(), kernel::process::Error> { + // No-op implementation + Ok(()) + } +} +``` + +:::note Module definition +Do not forget to add `pub mod mock;` in the crate's `lib.rs` file. +::: + +The next step is to implement the handling of specific commands. The convention is that the first command (`0`) to be an *"exists"* command, that is usually used to check wether a driver is present or not in the board configuration, and it should simply return a `CommandReturn::success()`. + +We also need to add our print command, on command number `1`. For serial debug printing, the kernel exposes two macros, `kernel::debug!` and `kernel::debug_verbose!`. Try to use both of them and spot the difference. + +With our capsule implementation done, we need to add it to the board's configuration. We need to add a field for the capsule in the board's `Cy8cproto0624343w` structure. + +```rust title="boards/cy8cproto_62_4343_w/main.rs" +/// Supported drivers by the platform +pub struct Cy8cproto0624343w { + // ... Previous lines removed for simplicity + systick: cortexm0p::systick::SysTick, + // highlight-next-line + mock_capsule: &'static capsules_extra::mock::MockCapsule, +} + +impl SyscallDriverLookup for Cy8cproto0624343w { + fn with_driver(&self, driver_num: usize, f: F) -> R + where + F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R, + { + match driver_num { + // ... + capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)), + // highlight-next-line + capsules_extra::mock::DRIVER_NUM => f(Some(self.mock_capsule)), + _ => f(None), + } + } +} + +// ... + +pub unsafe fn main() { + // ... + + let cy8cproto0624343w = Cy8cproto0624343w { + // ... + gpio, + // Currently, the CPU runs at 8MHz, that being the frequency of the IMO. + systick: cortexm0p::systick::SysTick::new_with_calibration(8_000_000), + // highlight-next-line + mock_capsule: &capsules_extra::mock::MockCapsule, + }; + + // ... +} +``` From a4a18b0a9f23da4fbbe044d44b5f2e471e51ef75 Mon Sep 17 00:00:00 2001 From: Darius-Andrei Jipa Date: Wed, 30 Jul 2025 14:52:15 +0300 Subject: [PATCH 06/14] Small fixes This commit adds the prerequisites for `probe-rs` and adds some clarifications regarding some of the necessary actions. --- docs/tock_workshop/index.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index 520dab1..17f22b4 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -24,13 +24,22 @@ info: The currently active `rustc` version is `rustc 1.86.0 (05f9846f8 2025-03-3 This tool is an embedded debugging and target interaction toolkit. It enables its user to program and debug microcontrollers via a debug probe. -The simplest installation method involves using the `cargo` packet manager: +The simplest installation method involves using the `cargo` packet manager, but first you have to install the prerequisites: + +- On Debian-based Linux, use the following command: +```shell +sudo apt install -y pkg-config libudev-dev cmake git +``` + +- On Mac OS and Windows, no additional setup is needed. + +After that, use `cargo` to install `probe-rs`: ```shell cargo install probe-rs-tools --locked ``` -If you are using Linux, you will also need to add this [udev](https://probe.rs/files/69-probe-rs.rules) file in `/etc/udev/rules.d`. Then, run: +If you are using Linux, you will also need to add this [udev](https://probe.rs/files/69-probe-rs.rules) file in `/etc/udev/rules.d`. Then, run as root: ```shell udevadm control --reload # to ensure the new rules are used. @@ -186,7 +195,7 @@ impl SyscallDriver for MockCapsule { ``` :::note Module definition -Do not forget to add `pub mod mock;` in the crate's `lib.rs` file. +Do not forget to add `pub mod mock;` in `capsules/extra/src/lib.rs`. ::: The next step is to implement the handling of specific commands. The convention is that the first command (`0`) to be an *"exists"* command, that is usually used to check wether a driver is present or not in the board configuration, and it should simply return a `CommandReturn::success()`. From 099fe3b0a2f312e13ee95b25031402bc1c6ed625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George-D=C4=83nu=C8=9B=20Aldea?= Date: Wed, 30 Jul 2025 14:01:12 +0300 Subject: [PATCH 07/14] fix: added list output --- docs/tock_workshop/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index 17f22b4..5ee2f26 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -154,8 +154,8 @@ Which option? [0] 1 [INFO ] Listening for serial output $tock list - -TODO: add app list output + PID ShortID Name Quanta Syscalls Restarts Grants State + 0 Unique blink 0 84 0 1/ 8 Yielded ``` ### Building a capsule From 225d1dbb2fb788a4c5708c5d984b39538af89d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George-D=C4=83nu=C8=9B=20Aldea?= Date: Wed, 30 Jul 2025 15:15:08 +0300 Subject: [PATCH 08/14] added test application task --- docs/tock_workshop/index.md | 66 +++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index 5ee2f26..7b2019e 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -245,3 +245,69 @@ pub unsafe fn main() { // ... } ``` + +### Writing an application + +To test the capsule we just created, we will need an application. This app will check if the driver is present in the kernel configuration, then it will issue a *"print"* command to the driver every second. + +The simplest way to do this is to create a new entry in the `examples` directory, then import the `Makefile` from the `blink` example. We will also need to create an API for issuing commands to the capsule. This is usually done in a separate `.c` file, and further exposed in a header file to be used by application developers, but for the task at hand, defining them in `main.c` will work. + +```c title="examples/ws-mock-test/main.c" +#include + +#define MOCK_DRIVER_NUM 0x9000A +#define MOCK_EXIST 0x0 +#define MOCK_PRINT 0x1 + +int check_mock_driver_exists(void); +int mock_print(void); + +int check_mock_driver_exists(void) { + syscall_return_t ret = command(MOCK_DRIVER_NUM, MOCK_EXIST, 0, 0); + return tock_command_return_novalue_to_returncode(ret); +} + +int mock_print(void) { + syscall_return_t ret = command(MOCK_DRIVER_NUM, MOCK_PRINT, 0, 0); + return tock_command_return_novalue_to_returncode(ret); +} + +int main(void) { +} +``` + +:::note `tock.h` API +The `syscall_return_t` type is the representation of the `CommandReturn` type seen in kernel. Tock supports returning either a success or error response to system calls, along with a payload of up to two `u32`s in size. The developer must be aware of the return type used by a respective command of a driver to correctly decode the response message. In our case, both commands used return no payload so the `tock_command_return_novalue_to_returncode`. +::: + +Now, we need to complete the implementation of the main function. + +```c title="example/ws-mock-test/main.c" +#include + +#include + +// Headers for `printf` +#include +#include +#include +#include + +// ... + +int main(void) { + printf("Mock capsule test\n"); + + int err = check_mock_driver_exists(); + if (err < 0) { + printf("Mock capsule missing"); + return err; + } + + while (true) { + mock_print(); + // This delay uses an underlying alarm in the kernel. + libtocksync_alarm_delay_ms(1000); + } +} +``` From 9828bf6abd17004f0ecef00feb200cb880c1aa7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George-D=C4=83nu=C8=9B=20Aldea?= Date: Wed, 30 Jul 2025 15:16:37 +0300 Subject: [PATCH 09/14] nit: fixed format on list --- docs/tock_workshop/index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index 7b2019e..aef5d73 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -26,12 +26,13 @@ This tool is an embedded debugging and target interaction toolkit. It enables it The simplest installation method involves using the `cargo` packet manager, but first you have to install the prerequisites: -- On Debian-based Linux, use the following command: +* On Debian-based Linux, use the following command: + ```shell sudo apt install -y pkg-config libudev-dev cmake git ``` -- On Mac OS and Windows, no additional setup is needed. +* On Mac OS and Windows, no additional setup is needed. After that, use `cargo` to install `probe-rs`: From f4ae7640d92f51bbb88a3a9b050ba7db3c6b3bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George-D=C4=83nu=C8=9B=20Aldea?= Date: Fri, 1 Aug 2025 15:25:54 +0300 Subject: [PATCH 10/14] added periodic print task --- docs/tock_workshop/index.md | 188 +++++++++++++++++++++++++++++++++++- 1 file changed, 187 insertions(+), 1 deletion(-) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index aef5d73..8f1507c 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -205,7 +205,7 @@ We also need to add our print command, on command number `1`. For serial debug p With our capsule implementation done, we need to add it to the board's configuration. We need to add a field for the capsule in the board's `Cy8cproto0624343w` structure. -```rust title="boards/cy8cproto_62_4343_w/main.rs" +```rust title="boards/cy8cproto_62_4343_w/src/main.rs" /// Supported drivers by the platform pub struct Cy8cproto0624343w { // ... Previous lines removed for simplicity @@ -312,3 +312,189 @@ int main(void) { } } ``` + +To test the application, run the `make` command in the example's root directory, change the `APP` Makefile variable in the board's directory and run `make program`. + +### Periodic Print + +We want to modify the capsule now, so that it prints a message every second, without the application's intervention. First we must modify the `Mock` capsule structure, to include a reference to an *"Alarm source"*. To do so, we should make the structure generic over any implementor of the `hil` + +```rust title="capsules/extra/src/mock.rs" +use kernel::hil::time; + +pub struct MockCapsule<'a, A: time::Alarm<'a>> { + alarm: &'a A, +} + +impl<'a, A: time::Alarm<'a>> MockCapsule<'a, A> { + pub fn new(alarm: &'a A) -> Self { + Self { alarm } + } +} + +// ... +``` + +:::note `impl` block +Do not forget to change the `SyscallDriver` implementation block to use the newly added generic and lifetime. +::: + +#### Tock `Alarm` design + +Tock is asynchronous by design, and any time consuming operation, such as adding delays in code, must not block the execution of the kernel. Non-blocking delays using a callback based mechanism, where the piece of code that must await a period of time arms an alarm using the interface exposed by the `time::Alarm` trait, and the underlying alarm will call a previously defined function at the expiration moment. The function to be invoked is specified by implementing the `time::AlarmClient`, and is the sole method `alarm`. + +In our case, the implementation is straight forward. The capsule will print a message, and then re-arm the alarm: + +```rust title="capsules/extra/src/mock.rs" +use kernel::hil::time::ConvertTicks; + +// ... + +impl<'a, A: time::Alarm<'a>> MockCapsule<'a, A> { + pub fn new(alarm: &'a A) -> Self { /* ... */} + + // We must also add an `init` function to start this cycle. + pub fn init(&'a self) { + let dt = self.alarm.ticks_from_seconds(1); + self.alarm.set_alarm(self.alarm.now(), dt); + } +} + +impl<'a, A: time::Alarm<'a>> AlarmClient for MockCapsule<'a, A> { + fn alarm(&self) { + kernel::debug!("Periodic \"hi\" message"); + let dt = self.alarm.ticks_from_seconds(1); + self.alarm.set_alarm(self.alarm.now(), dt); + } +} +``` + +#### `Component` system + +In Tock, initializing a board mainly consists of three steps: + +1. Setting any MCU-specific configurations necessary for the MCU to operate correctly. +2. Statically declaring memory for various kernel resources (i.e. capsules) and configuring the capsules correctly. +3. Loading processes, configuring the core kernel, and starting the kernel. + +Components are designed to simplify the second step (configuring capsules) while also reducing the chance for misconfiguration or other setup errors. A component encapsulates peripheral-specific and capsule-specific initialization for the Tock kernel in a factory method, which reduces repeated code and simplifies the boot sequence. + +The `Component` trait encapsulates all of the initialization and configuration of a kernel extension inside the `Component::finalize()` function call. The `Component::Output` type defines what type this component generates. Note that instantiating a component does not instantiate the underlying `Component::Output` type; instead, the memory is statically allocated and provided as an argument to the `Component::finalize()` method, which correctly initializes the memory to instantiate the `Component::Output` object. If instantiating and initializing the `Component::Output` type requires parameters, these should be passed in the component's `new()` function. + +Using a component is as follows: + +```rust +let obj = CapsuleComponent::new(configuration, required_hw) + .finalize(capsule_component_static!()); +``` + +All required resources and configuration is passed via the constructor, and all required static memory is defined by the `[name]_component_static!()` macro and passed to the `finalize()` method. + +As mentioned before, the capsule will need an alarm source. Most microcontrollers do not have an abundance of hardware sources to fulfill the needs of every scenario, so there is a need to multiplex one or more time-sources to be able to configure multiple alarms. Tock has support for this through `VirtualMuxAlarms` which act as alarm sources but all multiplex a single `MuxAlarm`, backed by a board's peripheral. + +The component must receive a **static** reference to a generic `MuxAlarm`, and should create and setup a new virtual alarm instance, whose client must be the mock capsule it will generate. As a result, the component will need a static memory regions (`StaticInput` type) for both the `MockCapsule` and the `VirtualMuxAlarm`. + +```rust title="boards/components/src/mock.rs" +pub struct MockCapsuleComponent> { + alarm_mux: &'static MuxAlarm<'static, A>, +} + +impl> MockCapsuleComponent { + pub fn new(alarm_mux: &'static MuxAlarm<'static, A>) -> Self { + Self { alarm_mux } + } +} + +impl> Component for MockCapsuleComponent { + type StaticInput = ( + &'static mut MaybeUninit>, + &'static mut MaybeUninit>>, + ); + + type Output = &'static MockCapsule<'static, VirtualMuxAlarm<'static, A>>; + + fn finalize(self, static_memory: Self::StaticInput) -> Self::Output { + let virtual_alarm = static_memory.0.write(VirtualMuxAlarm::new(self.alarm_mux)); + virtual_alarm.setup(); + + let mock = static_memory.1.write(MockCapsule::new(virtual_alarm)); + virtual_alarm.set_alarm_client(mock); + + mock + } +} +``` + +The allocation of the memory segments is usually done through a marco. It is out of this workshop's scope to dive into writing macros, but the macro bellow takes a `type` that must implement the `hil::time::Alarm` trait and returns a tuple of static mutable references to `MaybeUninit` wrappers of the `VirtualMuxAlarm` nad the `MockCapsule`. + +```rust title="boards/components/src/mock.rs" +// ... + +#[macro_export] +macro_rules! mock_component_static { + ($A:ty $(,)?) => {{ + let virtual_alarm = kernel::static_buf!( + capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A> + ); + + let mock = kernel::static_buf!( + capsules_extra::mock::MockCapsule<'static, VirtualMuxAlarm<'static, $A>> + ); + + (virtual_alarm, mock) + };}; +} +``` + +:::note `MaybeUninit` +`MaybeUninit` in Rust is a special wrapper type that allows you to safely work with memory that has not been initialized yet. Normally, Rust enforces that all variables are fully initialized before use to maintain memory safety. However, some situations require allocating memory first and filling it later. +::: + +#### Refactor board's configuration + +Because we made fundamental changes to the capsule, we need to make a few modifications in order to run the kernel. + +```rust title="boards/cy8cproto_62_4343_w/src/main.rs" +/// Supported drivers by the platform +pub struct Cy8cproto0624343w { + // ... + systick: cortexm0p::systick::SysTick, + // highlight-start + mock_capsule: &'static capsules_extra::mock::MockCapsule< + 'static, + VirtualMuxAlarm<'static, psoc62xa::tcpwm::Tcpwm0<'static>>, + >, + // highlight-end +} + +// ... + +pub unsafe fn main() { + // ... + + // highlight-start + let mock_capsule = components::mock::MockCapsuleComponent::new(mux_alarm) + .finalize(components::mock_component_static!(psoc62xa::tcpwm::Tcpwm0)); + mock_capsule.init(); + // highlight-end + + let cy8cproto0624343w = Cy8cproto0624343w { + // ... + gpio, + // Currently, the CPU runs at 8MHz, that being the frequency of the IMO. + systick: cortexm0p::systick::SysTick::new_with_calibration(8_000_000), + // highlight-next-line + mock_capsule + }; + + // ... + +} +``` + +To test our modifications, as now we no longer need an application, run: + +```shell +probe-rs erase --chip CY8C624ABZI-S2D44 +make flash +``` From 1e93f7e966bfc6e6551e842b97802da08c24d708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George-D=C4=83nu=C8=9B=20Aldea?= Date: Tue, 5 Aug 2025 16:10:42 +0300 Subject: [PATCH 11/14] added thermistor task --- docs/tock_workshop/assets/Thermistor.webp | Bin 0 -> 7728 bytes docs/tock_workshop/index.md | 395 +++++ docusaurus.config.ts | 19 + package-lock.json | 1662 ++++++++++++++++++++- package.json | 5 +- 5 files changed, 2035 insertions(+), 46 deletions(-) create mode 100644 docs/tock_workshop/assets/Thermistor.webp diff --git a/docs/tock_workshop/assets/Thermistor.webp b/docs/tock_workshop/assets/Thermistor.webp new file mode 100644 index 0000000000000000000000000000000000000000..617f5e256c7c3ab1aada0f7c52a39b41e7258e6f GIT binary patch literal 7728 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 literal 0 HcmV?d00001 diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index 8f1507c..0d7f683 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -498,3 +498,398 @@ To test our modifications, as now we no longer need an application, run: probe-rs erase --chip CY8C624ABZI-S2D44 make flash ``` + +### Temperature Sensor Capsule + +For this task, we will have to read the ambient temperature using the onboard thermistor. A thermistor is a temperature-sensitive resistor in which resistance varies with temperature. The thermistor is in a voltage divider configuration which can be seen bellow: + +![Thermistor Configuration](./assets/Thermistor.webp) + +Given that the current flowing through $R_{ref}$ also flows through the thermistor: + +$$ +\frac{V_1 - V_0}{R_{therm}} = \frac{V_2 - V_1}{R_{ref}} +$$ + +The [Steinhart-Hart](https://en.wikipedia.org/wiki/Steinhart–Hart_equation) equation describes the resistance change of a semiconductor thermistor as related to its temperature. The following equation shows it to be a third-order logarithmic polynomial using three constants. + +$$ +\frac{1}{T_K} = A + B \cdot \ln(R) + C \cdot \ln(R)^3 +$$ + +Where $A$, $B$ and $C$ are empirical constants, $R$ is the thermistor's resistance in $\Omega$ and $T_k$ is the temperature in kelvin. + +Consulting the [board's manual](https://www.infineon.com/assets/row/public/documents/30/44/infineon-cy8cproto-062-4343w-psoc-6-wi-fi-bt-prototyping-kit-guide-usermanual-en.pdf), we can see that the voltage divider uses a `10K` resistor, so $R_{ref} = 10000\Omega$. + +#### Current state + +The underlying ADC peripheral implementation has two channels configured (`AdcChannel0` and `AdcChannel1`) to sample on demand the two voltage drops on the resistor and thermistor. Also, the four pins mentioned in the schematic are properly setup by the board configuration, in the `TEMPERATURE` section. + +#### `TemperatureSensor` in Tock + +Tock already has an implementation for a `SyscallDriver` capsule for reading the temperature. It can be found in the `capsules/extra/src/temperature.rs` module. It utilizes a trait for interacting with various temperature sensors called `TemperatureDriver`, that works in the same notification based paradigm as the `Alarm`, notifying the client when the temperature measurement is complete. Our goal will be to implement this trait for our new `Cy8cprotoThermistor` capsule. + +As before, the first step will be to define our new module, `cy8cproto_thermistor.rs` and define the structure of our capsule. The capsule will need references to both `AdcChannel`s, and will need to hold a client reference, to notify them. + +```rust title="capsules/extra/scr/cy8cproto_thermistor.rs" +pub struct Cy8cprotoThermistor<'a, A: adc::AdcChannel<'a>> { + thermistor_adc: &'a A, + resistor_adc: &'a A, + client: OptionalCell<&'a dyn sensors::TemperatureClient>, +} +``` + +We need to implement the `TemperatureDriver` trait for our thermistor capsule. The implementation for the `set_client` method is straight-forward, and the `read_temperature` would, in theory, need to start the sampling of both channels. + +```rust title="capsules/extra/scr/cy8cproto_thermistor.rs" +impl<'a, A: adc::AdcChannel<'a>> TemperatureDriver<'a> for Cy8cprotoThermistor<'a, A> { + fn set_client(&self, client: &'a dyn sensors::TemperatureClient) { + self.client.set(client); + } + + fn read_temperature(&self) -> Result<(), kernel::ErrorCode> { + self.thermistor_adc.sample(); + self.resistor_adc.sample(); + Ok(()) + } +} +``` + +:::warning Error handling +This implementation disregards error handling for education purposes, both sample functions may fail, and need proper handling. +::: + +This capsule will be a client to both the `AdcChannel`s, so the next logical step is to implement the `AdcClient` trait. + +```rust title="capsules/extra/scr/cy8cproto_thermistor.rs" +impl<'a, A: adc::AdcChannel<'a>> adc::Client for Cy8cprotoThermistor<'a, A> { + fn sample_ready(&self, sample: u16) { + todo!() + } +} +``` + +This is where we encounter our first issue. Both channels will use the same interface, and therefore the same method implementation when the sampling is done. This means that the capsule has no way of distinguishing between the samples. + +#### State machine design + +One viable alternative would be implementing a state machine for sampling both channels and computing the temperature. + +```mermaid +--- +config: + theme: redux +--- +flowchart TD + A(["Idle"]) -- read_temperature() --> B{"Sample Resistor"} + B -- Error --> D(["Report Error"]) + B -- Await sample result --> C{"Sample Thermistor"} + C -- Error --> D + C -- Await sample result --> F(["Report Temperature"]) + F --> A + D --> A +``` + +We need to define the internal state of the capsule, and to do that, we will use an `enum`. We will also need to store the result of the resistor sample in capsule. + +```rust title="capsules/extra/scr/cy8cproto_thermistor.rs" +#[derive(Clone, Copy)] +enum Status { + Idle, + AwaitingThermistorReading, + AwaitingResistorReading, +} + +pub struct Cy8cprotoThermistor<'a, A: adc::AdcChannel<'a>> { + thermistor_adc: &'a A, + resistor_adc: &'a A, + resistor_sample: OptionalCell, + status: Cell, + client: OptionalCell<&'a dyn sensors::TemperatureClient>, +} + +impl<'a, A: adc::AdcChannel<'a>> Cy8cprotoThermistor<'a, A> { + pub fn new(thermistor_adc: &'a A, resistor_adc: &'a A) -> Self { + Self { + thermistor_adc, + resistor_adc, + resistor_sample: OptionalCell::empty(), + status: Cell::new(Status::Idle), + client: OptionalCell::empty(), + } + } +} +``` + +The `read_temperature` method will start the resistor measurement and will change the inner state. + +```rust title="capsules/extra/scr/cy8cproto_thermistor.rs" +impl<'a, A: adc::AdcChannel<'a>> TemperatureDriver<'a> for Cy8cprotoThermistor<'a, A> { + fn set_client(&self, client: &'a dyn sensors::TemperatureClient) { + self.client.set(client); + } + + fn read_temperature(&self) -> Result<(), kernel::ErrorCode> { + let res = self.thermistor_adc.sample(); + if res.is_ok() { + self.status.set(Status::AwaitingThermistorReading); + } + res + } +} +``` + +The implementation of the `AdcClient` sole method, `sample_ready` will have to take into account the current state. If the method is called after the first reading (`status` is `Status::AwaitingResistorReading`), the capsule must store the result and start the thermistor sampling. If the method is called after both readings are performed, then the capsule must perform the computations mentioned above, to report the measured temperature in hundredths of degrees Celsius (centiCelsius). + +:::note Error handling + +Handle all possible errors that the `sample` calls may yield by resetting both the thermistor state to `Status::Idle` and the `resistor_sample`, and reporting the error to the client. + +```rust title="Reporting the result of a temperature reading" +self.client.map(|client| client.callback(temp_reading_result)) +``` + +In our case, the `temp_reading_result` will be the sample error. +::: + +#### Computing the temperature + +Based on the [Infineon documentation](https://www.infineon.com/assets/row/public/documents/30/42/infineon-an2017-psoc-1-temperature-measurement-with-thermistor-applicationnotes-en.pdf?fileId=8ac78c8c7cdc391c017d072814bc4c7b), the empirical constants' values for the thermistor used by our board are: + +```rust +/// Reference Resistor value in Ohms +const R_REF: f64 = 10_000.0; + +const A: f64 = 0.000891358; +const B: f64 = 0.000250618; +const C: f64 = 0.000000197; +``` + +To convert from the numerical values to voltages, we need to understand how ADCs work. Every ADC will have a resolution, which is the number of bits which can be used to store the sample result, and a sampling range which is the minimum-to-maximum input voltage it can measure. Our ADC has a resolution of 11 bits (based on the current configuration of the peripheral) and a input range of 0-3.3 Volts, meaning that the result can rage from `0`, which represents the 0V potential to `2047` ($2^{11} - 1$) which will represent 3V3. + +Based on this, we can define a function that takes the discrete value of the sample and returns the voltage. + +```rust +fn convert(sample: u16) -> f64 { + ((sample as f64) * 3.3) / 2047.0 +} +``` + +Our implementation of the `sample_ready` function should now be complete + +```rust title="capsules/extra/scr/cy8cproto_thermistor.rs" +impl<'a, A: adc::AdcChannel<'a>> adc::Client for Cy8cprotoThermistor<'a, A> { + fn sample_ready(&self, sample: u16) { + match self.status.get() { + Status::Idle => (), + Status::AwaitingResistorReading => { + // ... Store the sample + } + Status::AwaitingThermistorReading => { + let sample_0 = self.resistor_sample.take().unwrap(); + let sample_1 = sample; + + let v1_0 = convert(sample_0); + let v2_1 = convert(sample_1); + + let r_therm = R_REF * (v2_1 / v1_0); + + let logarithm = libm::log(r_therm); + let logarithm3 = logarithm * logarithm * logarithm; + + let temp_k = 1.0f64 / (A + B * logarithm + C * logarithm3); + + let temp_celsius = temp_k - 273.15; + + self.status.set(Status::Idle); + self.client + .map(|client| client.callback(Ok((temp_celsius * 100.0) as i32))); + } + } + } +} +``` + +#### Defining the component + +As before, we need to ensure the capsule can be easily configured by implementing a new `Component`. You can name the module `cyc8cproto_thermistor.rs`. + +We should start from the bottom up, considering what should be needed to instantiate this capsule. These are the `AdcChannel`s and an `MuxAdc`, to be able to multiplex an ADC peripheral to sample multiple channels. + +```rust title="boards/components/src/cyc8proto_thermistor.rs" +// This will be the output type of the component +pub type Cy8cprotoThermistorComponentType = + capsules_extra::cy8cproto_thermistor::Cy8cprotoThermistor<'static, A>; + +pub struct Cy8cprotoThermistorComponent> { + adc_mux: &'static capsules_core::virtualizers::virtual_adc::MuxAdc<'static, A>, + thermistor_channel: A::Channel, + resistor_channel: A::Channel, +} + +impl> Cy8cprotoThermistorComponent { + pub fn new( + adc_mux: &'static capsules_core::virtualizers::virtual_adc::MuxAdc<'static, A>, + thermistor_channel: A::Channel, + resistor_channel: A::Channel, + ) -> Self { + Self { + adc_mux, + thermistor_channel, + resistor_channel, + } + } +} +``` + +The `finalize` implementation of the `Component` trait will need to create the two virtual `AdcDevices` that multiplex the peripheral, and therefore, the static memory needed must accommodate the two devices, and the thermistor capsule. + +```rust title="boards/components/src/cyc8proto_thermistor.rs" +impl> Component for Cy8cprotoThermistorComponent { + type StaticInput = ( + &'static mut MaybeUninit>, + &'static mut MaybeUninit>, + &'static mut MaybeUninit>>, + ); + + type Output = &'static Cy8cprotoThermistorComponentType>; + + fn finalize(self, static_memory: Self::StaticInput) -> Self::Output { + let thermistor_device = + crate::adc::AdcComponent::new(self.adc_mux, self.thermistor_channel) + .finalize(static_memory.0); + + let resistor_device = crate::adc::AdcComponent::new(self.adc_mux, self.resistor_channel) + .finalize(static_memory.1); + + let cy8cproto_thermistor = static_memory.2.write(Cy8cprotoThermistorComponentType::new( + thermistor_device, + resistor_device, + )); + + thermistor_device.set_client(cy8cproto_thermistor); + resistor_device.set_client(cy8cproto_thermistor); + cy8cproto_thermistor + } +} +``` + +The macro should look like this: + +```rust title="boards/components/src/cyc8proto_thermistor.rs" +#[macro_export] +macro_rules! cy8cproto_thermistor_component_static { + ($A:ty $(,)?) => {{ + let thermistor_device = components::adc_component_static!($A); + let resistor_device = components::adc_component_static!($A); + let cy8cproto_thermistor = kernel::static_buf!( + capsules_extra::cy8cproto_thermistor::Cy8cprotoThermistor< + 'static, + capsules_core::virtualizers::virtual_adc::AdcDevice<'static, $A>, + > + ); + + (thermistor_device, resistor_device, cy8cproto_thermistor) + };}; +} +``` + +#### Adding the capsule to the board + +The final step is to add the newly defined capsule to the board's configuration. To do that, we must add the capsule +to the `Cy8cproto0624343w` structure, and to the `SyscallDriverLookup` implementation, and configure it in the `main` function. + +```rust title="boards/cy8cproto_62_4343_w/src/main.rs" +/// Supported drivers by the platform +pub struct Cy8cproto0624343w { + // ... + systick: cortexm0p::systick::SysTick, + // highlight-start + temp: &'static capsules_extra::temperature::TemperatureSensor< + 'static, + capsules_extra::cy8cproto_thermistor::Cy8cprotoThermistor< + 'static, + capsules_core::virtualizers::virtual_adc::AdcDevice<'static, Adc<'static>>, + >, + >, + // highlight-end +} + +impl SyscallDriverLookup for Cy8cproto0624343w { + fn with_driver(&self, driver_num: usize, f: F) -> R + where + F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R, + { + match driver_num { + // ... + capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)), + // highlight-next-line + capsules_extra::temperature::DRIVER_NUM => f(Some(self.temp)), + _ => f(None), + } + } +} + +// ... + +pub unsafe fn main() { + // ... + + //-------------------------------------------------------------------------- + // TEMPERATURE + //-------------------------------------------------------------------------- + + // ... Pin configurations + + let mux_adc = components::adc::AdcMuxComponent::new(&peripherals.adc) + .finalize(components::adc_mux_component_static!(sar::Adc)); + + // highlight-start + let thermistor = components::cy8cproto_thermistor::Cy8cprotoThermistorComponent::new( + mux_adc, + sar::AdcChannel::Channel0, + sar::AdcChannel::Channel1, + ) + .finalize(cy8cproto_thermistor_component_static!(psoc62xa::sar::Adc)); + + let temp = components::temperature::TemperatureComponent::new( + board_kernel, + capsules_extra::temperature::DRIVER_NUM, + thermistor, + ) + .finalize(components::temperature_component_static!( + capsules_extra::cy8cproto_thermistor::Cy8cprotoThermistor< + 'static, + capsules_core::virtualizers::virtual_adc::AdcDevice<'static, Adc<'static>>, + > + )); + // highlight-end + + // ... +} +``` + +#### Sensors application + +Fortunately, `libtock-c` already has a modular example that reads multiple sensors. This example can be found in the `examples/sensors` subdirectory. To enable the temperature readings, we must set the `temperature` variable. + +```c title="examples/sensors/main.c" +// ... +#include + +static libtock_alarm_t alarm; +static bool light = false; +// highlight-next-line +static bool temperature = true; +static bool humidity = false; +static bool ninedof = false; +static bool ninedof_accel = false; +static bool ninedof_mag = false; +static bool ninedof_gyro = false; +static bool proximity = false; +static bool sound_pressure = false; +static bool moisture = false; +static bool rainfall = false; +``` + +Then, compile the application, and flash it along the kernel. Do not forget to update the `APP` variable in the board's `Makefile`. diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 73ec0b4..6a37d8c 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -1,6 +1,8 @@ import {themes as prismThemes} from 'prism-react-renderer'; import type {Config} from '@docusaurus/types'; import type * as Preset from '@docusaurus/preset-classic'; +import remarkMath from 'remark-math'; +import rehypeKatex from 'rehype-katex'; // This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) @@ -46,6 +48,8 @@ const config: Config = { // Remove this to remove the "edit this page" links. editUrl: 'https://github.com/ipworkshop/ipworkshop.github.io/edit/main/', + remarkPlugins: [remarkMath], + rehypePlugins: [rehypeKatex], }, blog: { showReadingTime: true, @@ -69,6 +73,21 @@ const config: Config = { ], ], + stylesheets: [ + { + href: 'https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css', + type: 'text/css', + integrity: + 'sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM', + crossorigin: 'anonymous', + }, + ], + + markdown: { + mermaid: true, + }, + themes: ['@docusaurus/theme-mermaid'], + themeConfig: { // Replace with your project's social card image: 'img/docusaurus-social-card.jpg', diff --git a/package-lock.json b/package-lock.json index 9cc4b73..e7196be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,11 +10,14 @@ "dependencies": { "@docusaurus/core": "3.8.1", "@docusaurus/preset-classic": "3.8.1", + "@docusaurus/theme-mermaid": "^3.8.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "rehype-katex": "^7.0.1", + "remark-math": "^6.0.0" }, "devDependencies": { "@docusaurus/module-type-aliases": "3.8.1", @@ -270,6 +273,28 @@ "node": ">=6.0.0" } }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@antfu/utils": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz", + "integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -1970,6 +1995,51 @@ "node": ">=6.9.0" } }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz", + "integrity": "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==", + "license": "MIT" + }, + "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==", + "license": "Apache-2.0", + "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==", + "license": "Apache-2.0", + "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==", + "license": "Apache-2.0" + }, + "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==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "license": "Apache-2.0" + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -3704,6 +3774,28 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, + "node_modules/@docusaurus/theme-mermaid": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.8.1.tgz", + "integrity": "sha512-IWYqjyTPjkNnHsFFu9+4YkeXS7PD1xI3Bn2shOhBq+f95mgDfWInkpfBN4aYvx4fTT67Am6cPtohRdwh4Tidtg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "mermaid": ">=11.6.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, "node_modules/@docusaurus/theme-search-algolia": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.8.1.tgz", @@ -3869,6 +3961,28 @@ "@hapi/hoek": "^9.0.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==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz", + "integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^1.0.0", + "@antfu/utils": "^8.1.0", + "@iconify/types": "^2.0.0", + "debug": "^4.4.0", + "globals": "^15.14.0", + "kolorist": "^1.8.0", + "local-pkg": "^1.0.0", + "mlly": "^1.7.4" + } + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -4002,6 +4116,15 @@ "react": ">=16" } }, + "node_modules/@mermaid-js/parser": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.2.tgz", + "integrity": "sha512-+PO02uGF6L6Cs0Bw8RpGhikVvMWEysfAyl27qTlroUB8jSWr1lL0Sf6zi78ZxlSnmgSY2AMMKVgghnN9jTtwkQ==", + "license": "MIT", + "dependencies": { + "langium": "3.3.1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -4450,6 +4573,259 @@ "@types/node": "*" } }, + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -4530,6 +4906,12 @@ "@types/send": "*" } }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT" + }, "node_modules/@types/gtag.js": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", @@ -4608,6 +4990,12 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT" }, + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", + "license": "MIT" + }, "node_modules/@types/mdast": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", @@ -4766,6 +5154,13 @@ "@types/node": "*" } }, + "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==", + "license": "MIT", + "optional": true + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -5851,6 +6246,32 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "license": "Apache-2.0", + "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==", + "license": "MIT", + "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", @@ -6142,6 +6563,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "license": "MIT" + }, "node_modules/config-chain": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", @@ -6354,6 +6781,15 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, + "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==", + "license": "MIT", + "dependencies": { + "layout-base": "^1.0.0" + } + }, "node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", @@ -6839,70 +7275,596 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", - "license": "MIT" + "node_modules/cytoscape": { + "version": "3.33.0", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.0.tgz", + "integrity": "sha512-2d2EwwhaxLWC8ahkH1PpQwCyu6EY3xDRdcEJXrLTb4fOUtVc+YWQalHU67rFS1a6ngj1fgv9dQLtJxP/KAFZEw==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "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==", "license": "MIT", "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" + "cose-base": "^1.0.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "peerDependencies": { + "cytoscape": "^3.2.0" } }, - "node_modules/decode-named-character-reference": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", - "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "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==", "license": "MIT", "dependencies": { - "character-entities": "^2.0.0" + "cose-base": "^2.2.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "peerDependencies": { + "cytoscape": "^3.2.0" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "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==", "license": "MIT", "dependencies": { - "mimic-response": "^3.1.0" + "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==", + "license": "MIT" + }, + "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==", + "license": "ISC", + "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": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "license": "MIT", - "engines": { - "node": ">=10" + "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==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=12" } }, - "node_modules/deep-extend": { + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-dsv/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==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "license": "BSD-3-Clause", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "BSD-3-Clause", + "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==", + "license": "BSD-3-Clause", + "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==", + "license": "BSD-3-Clause" + }, + "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==", + "license": "BSD-3-Clause", + "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==", + "license": "ISC" + }, + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "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==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", @@ -6984,6 +7946,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -7122,6 +8093,15 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz", + "integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", @@ -7716,6 +8696,12 @@ "node": ">= 0.6" } }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "license": "MIT" + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -8244,6 +9230,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -8371,6 +9369,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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==", + "license": "MIT" + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -8434,6 +9438,55 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-from-dom": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz", + "integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==", + "license": "ISC", + "dependencies": { + "@types/hast": "^3.0.0", + "hastscript": "^9.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html-isomorphic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz", + "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-dom": "^5.0.0", + "hast-util-from-html": "^2.0.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-from-parse5": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", @@ -8454,6 +9507,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-parse-selector": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", @@ -8576,6 +9642,22 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", @@ -9076,6 +10158,15 @@ "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", "license": "MIT" }, + "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==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -9526,6 +10617,31 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/katex": { + "version": "0.16.22", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz", + "integrity": "sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -9535,6 +10651,11 @@ "json-buffer": "3.0.1" } }, + "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/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -9553,6 +10674,28 @@ "node": ">=6" } }, + "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==", + "license": "MIT" + }, + "node_modules/langium": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", + "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "license": "MIT", + "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/latest-version": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", @@ -9578,6 +10721,12 @@ "shell-quote": "^1.8.1" } }, + "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==", + "license": "MIT" + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -9628,6 +10777,23 @@ "node": ">=8.9.0" } }, + "node_modules/local-pkg": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz", + "integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==", + "license": "MIT", + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.0.1", + "quansync": "^0.2.8" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", @@ -9649,6 +10815,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "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==", + "license": "MIT" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -9741,6 +10913,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/marked": { + "version": "16.1.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.1.2.tgz", + "integrity": "sha512-rNQt5EvRinalby7zJZu/mB+BvaAY2oz3wCuCjt1RDrWNpS1Pdf9xqMOeC9Hm5adBdcV/3XZPJpG58eT+WBc0XQ==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -10006,6 +11190,25 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-math": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", + "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "longest-streak": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.1.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-mdx": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", @@ -10203,6 +11406,47 @@ "node": ">= 8" } }, + "node_modules/mermaid": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.9.0.tgz", + "integrity": "sha512-YdPXn9slEwO0omQfQIsW6vS84weVQftIyyTGAZCwM//MGhPzL1+l6vO6bkf0wnP4tHigH1alZ5Ooy3HXI2gOag==", + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^7.0.4", + "@iconify/utils": "^2.1.33", + "@mermaid-js/parser": "^0.6.2", + "@types/d3": "^7.4.3", + "cytoscape": "^3.29.3", + "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.13", + "dompurify": "^3.2.5", + "katex": "^0.16.22", + "khroma": "^2.1.0", + "lodash-es": "^4.17.21", + "marked": "^16.0.0", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0" + } + }, + "node_modules/mermaid/node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -10805,6 +12049,81 @@ ], "license": "MIT" }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "license": "MIT", + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math/node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-math/node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-math/node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, "node_modules/micromark-extension-mdx-expression": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", @@ -12110,6 +13429,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mlly": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", + "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^2.0.1", + "pkg-types": "^1.3.0", + "ufo": "^1.5.4" + } + }, + "node_modules/mlly/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==", + "license": "MIT" + }, + "node_modules/mlly/node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -12589,6 +13937,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-manager-detector": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz", + "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==", + "license": "MIT" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -12716,6 +14070,12 @@ "tslib": "^2.0.3" } }, + "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==", + "license": "MIT" + }, "node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -12773,6 +14133,12 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -12806,6 +14172,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pkg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.2.0.tgz", + "integrity": "sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==", + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -14410,6 +15803,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quansync": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz", + "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -14839,6 +16248,25 @@ "node": ">=6" } }, + "node_modules/rehype-katex": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz", + "integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/katex": "^0.16.0", + "hast-util-from-html-isomorphic": "^2.0.0", + "hast-util-to-text": "^4.0.0", + "katex": "^0.16.0", + "unist-util-visit-parents": "^6.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-raw": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", @@ -14944,6 +16372,22 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-math": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", + "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-math": "^3.0.0", + "micromark-extension-math": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-mdx": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz", @@ -15229,6 +16673,24 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense" + }, + "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==", + "license": "MIT", + "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/rtlcss": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz", @@ -15270,6 +16732,12 @@ "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==", + "license": "BSD-3-Clause" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -16094,6 +17562,12 @@ "postcss": "^8.4.31" } }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -16272,6 +17746,12 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", "license": "MIT" }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "license": "MIT" + }, "node_modules/tinypool": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", @@ -16331,6 +17811,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "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==", + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -16406,6 +17895,12 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "license": "MIT" + }, "node_modules/undici-types": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", @@ -16495,6 +17990,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-is": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", @@ -16534,6 +18043,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", @@ -16900,6 +18423,55 @@ "url": "https://opencollective.com/unified" } }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "license": "MIT" + }, "node_modules/watchpack": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", diff --git a/package.json b/package.json index 0096a11..659a847 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,14 @@ "dependencies": { "@docusaurus/core": "3.8.1", "@docusaurus/preset-classic": "3.8.1", + "@docusaurus/theme-mermaid": "^3.8.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "rehype-katex": "^7.0.1", + "remark-math": "^6.0.0" }, "devDependencies": { "@docusaurus/module-type-aliases": "3.8.1", From 2f5a6b663cf3c2810eeba06e62a4b5036ec146f7 Mon Sep 17 00:00:00 2001 From: Darius-Andrei Jipa Date: Wed, 6 Aug 2025 11:55:04 +0300 Subject: [PATCH 12/14] Add GitHub links for the repositories --- docs/tock_workshop/index.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index 0d7f683..13edd75 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -100,7 +100,14 @@ The command, subscribe, and allow system calls all take a driver ID as their fir ### Flashing the kernel -Initially, you will need to clone the Tock [repository](https://example.com). The configuration for the various boards supported can be found in the `boards` directory. To compile the kernel, you can use the `cargo flash` utility. +Initially, you will need to clone the `Tock` repository: + +```shell +git clone https://github.com/OxidosAutomotive/tock.git --branch=psoc6-workshop +cd tock +``` + +The configuration for the various boards supported can be found in the `boards` directory. To compile the kernel, you can use the `cargo flash` utility. ```shell cd boards/cy8cproto_62_4343_w @@ -129,7 +136,14 @@ $tock ### Compiling an application -For this task, you will have to clone the [`libtock-c`](https://example.com) repository first. Navigate to the `examples/blink` folder and take a look at the C application structure found in `main.c`. To compile the application, simply run `make`. This command will built the example applications for all target architectures supported by the library. Apps are compiled into TBFs (Tock Binary Format), and can be found in the `build/` sub-directories. Tock also generates an archive of the same app, compiled for multiple architectures, for ease of use and portability, called a TAB(Tock Application Bundle) which can be loaded using the `tockloader` utility. +For this task, you will have to clone the `libtock-c` repository: + +```shell +git clone https://github.com/ipworkshop/libtock-c.git --branch=remove-risc +cd libtock-c +``` + +Navigate to the `examples/blink` folder and take a look at the C application structure found in `main.c`. To compile the application, simply run `make`. This command will built the example applications for all target architectures supported by the library. Apps are compiled into TBFs (Tock Binary Format), and can be found in the `build/` sub-directories. Tock also generates an archive of the same app, compiled for multiple architectures, for ease of use and portability, called a TAB(Tock Application Bundle) which can be loaded using the `tockloader` utility. ### Flashing the application From 07dcd7fe85ef0f41f5ad4226a93992d5886a02b2 Mon Sep 17 00:00:00 2001 From: Darius-Andrei Jipa Date: Wed, 6 Aug 2025 17:19:10 +0300 Subject: [PATCH 13/14] Small fixes This commit adds small fixes based on the received feedback. --- docs/tock_workshop/index.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index 13edd75..b4d352e 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -111,10 +111,10 @@ The configuration for the various boards supported can be found in the `boards` ```shell cd boards/cy8cproto_62_4343_w -cargo flash +make flash ``` -Alternatively, you can use the `make flash` while inside the board's directory. +Alternatively, you can use the `cargo flash` while inside the board's directory. If you did everything correctly, you should be able to use the `tockloader listen` command to interact with the kernel. When prompted to select a serial port, pick the one that ends with `KitProg3 CMSIS-DAP`. @@ -185,9 +185,9 @@ use kernel::{ ErrorCode, }; -const DRIVER_NUM: usize = 0x9000A; +pub const DRIVER_NUM: usize = 0x9000A; -struct MockCapsule; +pub struct MockCapsule; impl SyscallDriver for MockCapsule { fn command( @@ -439,6 +439,10 @@ impl> Component for MockCapsuleComponent { } ``` +:::note Module definition +Do not forget to add `pub mod mock;` in `boards/components/src/lib.rs`. +::: + The allocation of the memory segments is usually done through a marco. It is out of this workshop's scope to dive into writing macros, but the macro bellow takes a `type` that must implement the `hil::time::Alarm` trait and returns a tuple of static mutable references to `MaybeUninit` wrappers of the `VirtualMuxAlarm` nad the `MockCapsule`. ```rust title="boards/components/src/mock.rs" @@ -726,7 +730,7 @@ impl<'a, A: adc::AdcChannel<'a>> adc::Client for Cy8cprotoThermistor<'a, A> { #### Defining the component -As before, we need to ensure the capsule can be easily configured by implementing a new `Component`. You can name the module `cyc8cproto_thermistor.rs`. +As before, we need to ensure the capsule can be easily configured by implementing a new `Component`. You can name the module `cy8cproto_thermistor.rs`. We should start from the bottom up, considering what should be needed to instantiate this capsule. These are the `AdcChannel`s and an `MuxAdc`, to be able to multiplex an ADC peripheral to sample multiple channels. @@ -758,7 +762,7 @@ impl> Cy8cprotoThermistorComponent { The `finalize` implementation of the `Component` trait will need to create the two virtual `AdcDevices` that multiplex the peripheral, and therefore, the static memory needed must accommodate the two devices, and the thermistor capsule. -```rust title="boards/components/src/cyc8proto_thermistor.rs" +```rust title="boards/components/src/cy8cproto_thermistor.rs" impl> Component for Cy8cprotoThermistorComponent { type StaticInput = ( &'static mut MaybeUninit>, @@ -790,7 +794,7 @@ impl> Component for Cy8cprotoThermistorComponent< The macro should look like this: -```rust title="boards/components/src/cyc8proto_thermistor.rs" +```rust title="boards/components/src/cy8cproto_thermistor.rs" #[macro_export] macro_rules! cy8cproto_thermistor_component_static { ($A:ty $(,)?) => {{ From 43508d871ff0a464c23698e147af8ceb37f7bf13 Mon Sep 17 00:00:00 2001 From: Darius-Andrei Jipa Date: Mon, 11 Aug 2025 15:54:14 +0300 Subject: [PATCH 14/14] Add NixOS alternative for TockWorld. This commit adds a NixOS VM alternative for Windows users or user that don't want to follow the prerequisites. The text of the workshop has been modified to reflect this addition. --- docs/tock_workshop/index.md | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/docs/tock_workshop/index.md b/docs/tock_workshop/index.md index b4d352e..431b9bf 100644 --- a/docs/tock_workshop/index.md +++ b/docs/tock_workshop/index.md @@ -2,16 +2,18 @@ ## Prerequisites +:::note Windows Users or participants that are willing to use a VM +This workshop will not work on Windows systems. +You can try following the guide using a Linux VM/WSL2, +or you can use the NixOS VM we provide [here](https://drive.google.com/file/d/1-jOsuWdSnOlmyupMWb3Vw4oG_t77BnwQ/view?usp=sharing) (only works on VirtualBox). +The username and password are both `ipwembedded`. +If you will be using the NixOS VM, you can skip the prerequisites. +::: + ### Rust Toolchain You will need to install the Rust toolchain. To do so, you can follow the instructions on the [Getting started](https://www.rust-lang.org/learn/get-started) page of the Rust Language website. -:::info Windows Install Tips -If you are using Windows, you may be prompted to install [Visual Studio C++ Build tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/). If so, follow the instructions from the previous link. - -Even if Visual Studio is already on your machine, rustup will not verify if the required components are present. If you experience issues with the `rustup` installation on Windows, please follow [these instructions](https://rust-lang.github.io/rustup/installation/windows-msvc.html) to manually add the missing components. -::: - To verify that the installation, open a terminal and run `rustup --version`. If everything went well, you should see an output similar to this: ```shell @@ -32,7 +34,7 @@ The simplest installation method involves using the `cargo` packet manager, but sudo apt install -y pkg-config libudev-dev cmake git ``` -* On Mac OS and Windows, no additional setup is needed. +* On Mac OS, no additional setup is needed. After that, use `cargo` to install `probe-rs`: @@ -107,6 +109,11 @@ git clone https://github.com/OxidosAutomotive/tock.git --branch=psoc6-workshop cd tock ``` +:::note NixOS VM users +You don't have to clone the Tock OS repository, it is already cloned in the home directory. +You will have to run `nix-shell` once you enter the `tock` directory. +::: + The configuration for the various boards supported can be found in the `boards` directory. To compile the kernel, you can use the `cargo flash` utility. ```shell @@ -118,6 +125,11 @@ Alternatively, you can use the `cargo flash` while inside the board's directory. If you did everything correctly, you should be able to use the `tockloader listen` command to interact with the kernel. When prompted to select a serial port, pick the one that ends with `KitProg3 CMSIS-DAP`. +:::note NixOS VM users +Currently, `tockloader` doesn't work on NixOS, but we have included the program `picocom` +which you can use with the following command: `picocom -b 115200 /dev/ttyACM0`. (use `sudo` if it gives an error about permissions) +::: + ```shell tockloader listen [INFO ] No device name specified. Using default name "tock". @@ -131,7 +143,7 @@ Which option? [0] 1 [INFO ] Using "/dev/cu.usbmodem1103 - KitProg3 CMSIS-DAP". [INFO ] Listening for serial output -$tock +tock$ ``` ### Compiling an application @@ -143,6 +155,12 @@ git clone https://github.com/ipworkshop/libtock-c.git --branch=remove-risc cd libtock-c ``` +:::note NixOS VM users +You don't have to clone the libtock-c repository, it is already cloned in the home directory. +You will have to run `nix-shell` once you enter the `libtock-c` directory. +Make sure you don't run that command if you already ran `nix-shell` inside another directory (either run `exit` before, or use another shell). +::: + Navigate to the `examples/blink` folder and take a look at the C application structure found in `main.c`. To compile the application, simply run `make`. This command will built the example applications for all target architectures supported by the library. Apps are compiled into TBFs (Tock Binary Format), and can be found in the `build/` sub-directories. Tock also generates an archive of the same app, compiled for multiple architectures, for ease of use and portability, called a TAB(Tock Application Bundle) which can be loaded using the `tockloader` utility. ### Flashing the application @@ -168,7 +186,7 @@ Which option? [0] 1 [INFO ] Using "/dev/cu.usbmodem1103 - KitProg3 CMSIS-DAP". [INFO ] Listening for serial output -$tock list +tock$ list PID ShortID Name Quanta Syscalls Restarts Grants State 0 Unique blink 0 84 0 1/ 8 Yielded ```