From 40508daa5b0e668d6d744804ed959520d5aa256f Mon Sep 17 00:00:00 2001 From: Lazaro Alonso Date: Mon, 19 Feb 2024 16:54:06 +0100 Subject: [PATCH 1/2] revamp docs again :D --- .github/workflows/Documenter.yml | 62 +- .gitignore | 12 + Project.toml | 2 +- docs/Project.toml | 2 +- docs/_overrides/partials/source.html | 30 - docs/examples/HowdoI/howdoi.jl | 171 - docs/examples/HowdoI/switchtodimarray.jl | 30 - docs/examples/UserGuide/applyfunctions.jl | 137 - docs/examples/UserGuide/create_from_func.jl | 57 - docs/examples/UserGuide/creating.jl | 124 - docs/examples/UserGuide/distributed.jl | 59 - .../examples/UserGuide/indexing_subsetting.jl | 65 - docs/examples/UserGuide/openNetCDF.jl | 26 - docs/examples/UserGuide/openZarr.jl | 4 - docs/examples/UserGuide/saving.jl | 57 - docs/examples/UserGuide/setchuncks.jl | 66 - docs/examples/contribute/contribute.jl | 44 - docs/genfiles.jl | 35 - docs/make.jl | 83 +- docs/package-lock.json | 2893 +++++++++++++++++ docs/package.json | 13 + docs/src/.vitepress/config.mts | 100 + docs/src/.vitepress/theme/index.ts | 21 + docs/src/.vitepress/theme/style.css | 173 + docs/src/HowdoI/contribute.md | 56 + docs/src/HowdoI/howdoi.md | 257 ++ docs/src/UserGuide/applyfunctions.md | 75 + .../UserGuide/create_cube_from_function.md | 81 + docs/src/UserGuide/creating.md | 183 ++ docs/src/UserGuide/distributed.md | 67 + docs/src/UserGuide/indexing_subsetting.md | 90 + docs/src/UserGuide/openNetCDF.md | 47 + docs/src/UserGuide/openZarr.md | 21 + docs/src/UserGuide/saving.md | 107 + docs/src/UserGuide/setchuncks.md | 90 + docs/src/assets/view-grid-plus-outline.svg | 1 - docs/src/components/AsideTrustees.vue | 132 + docs/src/getting_started.md | 102 + docs/src/index.md | 80 +- docs/src/javascripts/mathjax.js | 16 - docs/src/{assets => public}/logo.png | Bin docs/src/{assets => public}/logo.svg | 0 docs/src/stylesheets/custom.css | 157 - .../tutorials}/examples_from_esdl_study_1.jl | 0 .../tutorials}/examples_from_esdl_study_2.jl | 0 .../tutorials}/examples_from_esdl_study_3.jl | 114 +- .../tutorials}/examples_from_esdl_study_4.jl | 0 docs/src/tutorials/mean_seasonal_cycle.md | 110 + .../tutorials/plottingmaps.md} | 53 +- src/Cubes/Cubes.jl | 16 +- 50 files changed, 4882 insertions(+), 1239 deletions(-) delete mode 100644 docs/_overrides/partials/source.html delete mode 100644 docs/examples/HowdoI/howdoi.jl delete mode 100644 docs/examples/HowdoI/switchtodimarray.jl delete mode 100644 docs/examples/UserGuide/applyfunctions.jl delete mode 100644 docs/examples/UserGuide/create_from_func.jl delete mode 100644 docs/examples/UserGuide/creating.jl delete mode 100644 docs/examples/UserGuide/distributed.jl delete mode 100644 docs/examples/UserGuide/indexing_subsetting.jl delete mode 100644 docs/examples/UserGuide/openNetCDF.jl delete mode 100644 docs/examples/UserGuide/openZarr.jl delete mode 100644 docs/examples/UserGuide/saving.jl delete mode 100644 docs/examples/UserGuide/setchuncks.jl delete mode 100644 docs/examples/contribute/contribute.jl delete mode 100644 docs/genfiles.jl create mode 100644 docs/package-lock.json create mode 100644 docs/package.json create mode 100644 docs/src/.vitepress/config.mts create mode 100644 docs/src/.vitepress/theme/index.ts create mode 100644 docs/src/.vitepress/theme/style.css create mode 100644 docs/src/HowdoI/contribute.md create mode 100644 docs/src/HowdoI/howdoi.md create mode 100644 docs/src/UserGuide/applyfunctions.md create mode 100644 docs/src/UserGuide/create_cube_from_function.md create mode 100644 docs/src/UserGuide/creating.md create mode 100644 docs/src/UserGuide/distributed.md create mode 100644 docs/src/UserGuide/indexing_subsetting.md create mode 100644 docs/src/UserGuide/openNetCDF.md create mode 100644 docs/src/UserGuide/openZarr.md create mode 100644 docs/src/UserGuide/saving.md create mode 100644 docs/src/UserGuide/setchuncks.md delete mode 100644 docs/src/assets/view-grid-plus-outline.svg create mode 100644 docs/src/components/AsideTrustees.vue create mode 100644 docs/src/getting_started.md delete mode 100644 docs/src/javascripts/mathjax.js rename docs/src/{assets => public}/logo.png (100%) rename docs/src/{assets => public}/logo.svg (100%) delete mode 100644 docs/src/stylesheets/custom.css rename docs/{examples/UserGuide => src/tutorials}/examples_from_esdl_study_1.jl (100%) rename docs/{examples/UserGuide => src/tutorials}/examples_from_esdl_study_2.jl (100%) rename docs/{examples/UserGuide => src/tutorials}/examples_from_esdl_study_3.jl (53%) rename docs/{examples/UserGuide => src/tutorials}/examples_from_esdl_study_4.jl (100%) create mode 100644 docs/src/tutorials/mean_seasonal_cycle.md rename docs/{examples/Gallery/simplemaps.jl => src/tutorials/plottingmaps.md} (73%) diff --git a/.github/workflows/Documenter.yml b/.github/workflows/Documenter.yml index 60416b26..8f743c08 100644 --- a/.github/workflows/Documenter.yml +++ b/.github/workflows/Documenter.yml @@ -1,40 +1,64 @@ +# Sample workflow for building and deploying a VitePress site to GitHub Pages +# name: Documenter + on: + # Runs on pushes targeting the `main` branch. Change this to `master` if you're + # using the `master` branch as the default branch. push: branches: - master - tags: '*' + tags: ['*'] pull_request: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: write + pages: write + id-token: write + statuses: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} + group: pages + cancel-in-progress: false + jobs: + # Build job build: - permissions: - contents: write - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest env: DISPLAY: ':0' steps: - - uses: actions/checkout@v3 - - uses: julia-actions/setup-julia@v1 - - uses: julia-actions/cache@v1 + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Node + uses: actions/setup-node@v3 with: - cache-registries: "true" - - name: Install documentation dependencies + node-version: 20 + cache: npm # or pnpm / yarn + cache-dependency-path: 'docs/package-lock.json' # this should be a package-lock.json file + - name: Setup Julia + uses: julia-actions/setup-julia@v1 + - name: Pull Julia cache + uses: julia-actions/cache@v1 + - name: Install documentation dependencies # for GLMakie plots run: sudo apt-get update && sudo apt-get install -y xorg-dev mesa-utils xvfb libgl1 freeglut3-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev - - name: Install pkgs dependencies - run: DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24' julia --project=docs -e 'using Pkg; Pkg.instantiate(); Pkg.precompile(); pkg"dev ."; pkg"add DiskArrayTools#master"' - - name: Build and deploy + - name: Install documentation dependencies + run: DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24' julia --project=docs -e 'using Pkg; pkg"add https://github.com/LuxDL/DocumenterVitepress.jl.git"; pkg"dev ."; pkg"add DimensionalData#main"; Pkg.instantiate(); Pkg.precompile(); Pkg.status()' + - name: Instantiate NPM + run: cd docs/; npm i; cd .. + #- name: Creating new mds from src + - name: Build and deploy docs env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # For authentication with GitHub Actions token DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # For authentication with SSH deploy key - GKSwstype: "100" # https://discourse.julialang.org/t/generation-of-documentation-fails-qt-qpa-xcb-could-not-connect-to-display/60988 + GKSwstype: "100" # for Plots.jl plots (if you have them) JULIA_DEBUG: "Documenter" DATADEPS_ALWAYS_ACCEPT: true run: | - DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24' julia --code-coverage=user --project=docs/ --color=yes docs/genfiles.jl - DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24' julia --code-coverage=user --project=docs/ --color=yes docs/make.jl \ No newline at end of file + DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24' julia --project=docs/ --color=yes docs/make.jl \ No newline at end of file diff --git a/.gitignore b/.gitignore index 583f1f48..42d4f85c 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,15 @@ bonito /benchmark/*.json .benchmarkci coverage/lcov.info +node_modules +docs/node_modules + +.DS_Store +docs/src/.vitepress/cache +docs/src/.vitepress/dist +docs/Manifest.toml +docs/.vscode +docs/node_modules +docs/.vitepress/cache +docs/.vitepress/dist +docs/.DS_Store diff --git a/Project.toml b/Project.toml index 8b69cbd4..799ad28a 100644 --- a/Project.toml +++ b/Project.toml @@ -36,7 +36,7 @@ CFTime = "0.0, 0.1" DataStructures = "0.17, 0.18" DimensionalData = "0.24, 0.25" DiskArrayTools = "0.1" -DiskArrays = "0.3" +DiskArrays = "0.3,0.4" DocStringExtensions = "0.8, 0.9" Glob = "1.3" Interpolations = "0.12, 0.13, 0.14, 0.15" diff --git a/docs/Project.toml b/docs/Project.toml index 2edc8456..e584de44 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -8,7 +8,7 @@ DimensionalData = "0703355e-b756-11e9-17c0-8b28908087d0" DiskArrayTools = "fcd2136c-9f69-4db6-97e5-f31981721d63" DiskArrays = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -DocumenterMarkdown = "997ab1e6-3595-5248-9280-8efb232c3433" +DocumenterVitepress = "4710194d-e776-4893-9690-8d956a29c365" Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" diff --git a/docs/_overrides/partials/source.html b/docs/_overrides/partials/source.html deleted file mode 100644 index 41304445..00000000 --- a/docs/_overrides/partials/source.html +++ /dev/null @@ -1,30 +0,0 @@ -{% import "partials/language.html" as lang with context %} - -
- {% set icon = config.theme.icon.repo or "fontawesome/brands/git-alt" %} - {% include ".icons/" ~ icon ~ ".svg" %} -
-
- {{ config.repo_name }} -
-
-{% if config.theme.twitter_url %} - -
- {% include ".icons/fontawesome/brands/twitter.svg" %} -
-
- {{ config.theme.twitter_name }} -
-
-{% endif %} -{% if config.theme.sponsor_url %} - -
- {% include ".icons/fontawesome/regular/heart.svg" %} -
-
- {{ config.theme.sponsor_name }} -
-
-{% endif %} \ No newline at end of file diff --git a/docs/examples/HowdoI/howdoi.jl b/docs/examples/HowdoI/howdoi.jl deleted file mode 100644 index fb4ec300..00000000 --- a/docs/examples/HowdoI/howdoi.jl +++ /dev/null @@ -1,171 +0,0 @@ -# The purpose of this section is to do a collection of small -# convinient pieces of code on how to do simple things. - -# !!! question - -# ## Extract the axes names from a Cube - -using YAXArrays -using DimensionalData -c = YAXArray(rand(10, 10, 5)) - -caxes(c) - -# !!! question - -# ## Obtain values from axes and data from the cube - -# There are two options to collect values from axes. In this examples the axis ranges from 1 to 10. - -## this two examples bring the same result -collect(getAxis("Dim_1", c).val) -collect(c.axes[1].val) - -## to collect data from a cube works exactly the same as doing it from an array -c[:, :, 1] - - - -# ## Concatenate cubes - -# It is possible to concatenate several cubes that shared the same dimensions using the [`concatenatecubes`]@ref function. - -# let's create two dummy cubes - -using YAXArrays - -axlist = ( - Dim{:time}(range(1, 20, length=20)), - Dim{:lon}(range(1, 10, length=10)), - Dim{:lat}(range(1, 5, length=15)) - ) - -data1 = rand(20, 10, 15) -ds1 = YAXArray(axlist, data1) - -data2 = rand(20, 10, 15) -ds2 = YAXArray(axlist, data2) - -# Now we can concatenate ```ds1``` and ```ds2``` cubes: - -dsfinal = concatenatecubes([ds1, ds2], Dim{:Variables}(["var1", "var2"])) -dsfinal - - -# ## How do I subset a Cube? - -# Let's start by creating a dummy cube - -## define the time span of the cube -using Dates -t = Date("2020-01-01"):Month(1):Date("2022-12-31") - -## create cube axes -axes = (Dim{:Lon}(1:10), Dim{:Lat}(1:10), Dim{:Time}(t)) - -## assign values to a cube -c = YAXArray(axes, reshape(1:3600, (10, 10, 36))) - -# Now we subset the cube by any dimension - -## subset cube by years -ctime = c[Time=Between(Date(2021,1,1), Date(2021,12,31))] - -## subset cube by a specific date and date range -ctime2 = c[Time=At(Date("2021-05-01"))] -ctime3 = c[Time=Date("2021-05-01") .. Date("2021-12-01")] - -## subset cube by longitude and latitude -clonlat = c[Lon=1 .. 5, Lat=5 .. 10] # check even numbers range, it is ommiting them - - -# ## How do I apply map algebra? -# Our next step is map algebra computations. This can be done effectively using the 'map' function. For example: - -## multiplying cubes with only spatio-temporal dimensions -map((x, y) -> x * y, ds1, ds2) - -## cubes with more than 3 dimensions -map((x, y) -> x * y, dsfinal[Variables=At("var1")], dsfinal[Variables=At("var2")]) - -# To add some complexity, we will multiply each value for π and then divided for the sum of each time step. We will use the `ds1` cube for this purpose. -mapslices(ds1, dims=("Lon", "Lat")) do xin - (xin * π) ./ maximum(skipmissing(xin)) -end - -# ## How do I use the CubeTable function? -# The function "CubeTable" creates an iterable table and the result is a DataCube. It is therefore very handy for grouping data and computing statistics by class. It uses `OnlineStats.jl` to calculate statistics, and weighted statistics can be calculated as well. - -# Here we will use the `ds1` Cube defined previously and we create a mask for data classification. - -## cube containing a mask with classes 1, 2 and 3 -classes = YAXArray((getAxis("lon", dsfinal), getAxis("lat", dsfinal)), rand(1:3, 10, 15)) - -using GLMakie -GLMakie.activate!() -# This is how our classification map looks like -fig, ax, obj = heatmap(classes; - colormap=Makie.Categorical(cgrad([:grey15, :orangered, :snow3]))) -cbar = Colorbar(fig[1,2], obj) -fig - -# Now we define the input cubes that will be considered for the iterable table -t = CubeTable(values=ds1, classes=classes) - -using DataFrames -using OnlineStats -## visualization of the CubeTable -c_tbl = DataFrame(t[1]) -first(c_tbl, 5) - -# In this line we calculate the `Mean` for each class -fitcube = cubefittable(t, Mean, :values, by=(:classes)) - -# We can also use more than one criteria for grouping the values. In the next example, the mean is calculated for each class and timestep. -fitcube = cubefittable(t, Mean, :values, by=(:classes, :time)) - -# !!! question - -# ## convertions types `DimArray` & `YAXArray` - -using YAXArrays, YAXArrayBase -using DimensionalData - -# ### `DimArray` to `YAXArray` -dim_arr = rand(X(1:5), Y(10.0:15.0), metadata = Dict{String, Any}()) - -# !!! warning "metadata" -# Note the `metadata` argument. Needed by `yaxconvert`. - -yax_arr = yaxconvert(YAXArray, dim_arr) - -# And saving it: -using Zarr, NetCDF -savecube(yax_arr, "yax_arr.nc", driver=:netcdf) - -# or as a `zarr` file - -savecube(yax_arr, "yax_arr.zarr", driver=:zarr) - - -# And going back to the DimArray type is also possible. - -# ### `YAXArray` into a `DimArray` -dim_arr = yaxconvert(DimArray, yax_arr) - -# at the moment there is no support to save a DimArray directly into disk as a `NetCDF` or a `Zarr` file. - -# !!! question - -# ## Assing variable names to `YAXArrays` in a `Dataset` - -# ### One variable name - -ds = YAXArrays.Dataset(; (:a => YAXArray(rand(10)),)...) - -# ### Multiple variable names -keylist = (:a, :b, :c) -varlist = (YAXArray(rand(10)), YAXArray(rand(10,5)), YAXArray(rand(2,5))) - -ds = YAXArrays.Dataset(; (keylist .=> varlist)...) - diff --git a/docs/examples/HowdoI/switchtodimarray.jl b/docs/examples/HowdoI/switchtodimarray.jl deleted file mode 100644 index 184e753f..00000000 --- a/docs/examples/HowdoI/switchtodimarray.jl +++ /dev/null @@ -1,30 +0,0 @@ -# The purpose of this section is to show how to switch from the native `YAXArray` type to the new type based on `DimensionalData.jl` - -# ## Axis lists have to be Tuples instead of Vector - -# When you want to define a YAXArray from scratch the list of Axis has to be given as a Tuple instead of a vector. -# Otherwise you would run into a DimensionMismatch error. - - -# ## Dim instead of RangeAxis and CategoricalAxis -# The dimensions of a YAXArray are now `Dimension` types from DimensionalData -# and there is no difference anymore in the construction for categorical or - - -# ## Get the axes of a YAXArray -# To get the axes of a YAXArray use the `dims` function instead of the `caxes` function -using DimensionalData -using YAXArrays - -axes = (Dim{:Lon}(1:10), Dim{:Lat}(1:10), Dim{:Time}(1:100)) -arr = YAXArray(axes, reshape(1:10000, (10,10,100))) -dims(arr) - -# ## Copy an axes with the same name but different values -# Use __`DD.rebuild(ax, values)`__ instead of `axcopy(ax, values)`. - - -# ## Subsetting is **including** not excluding -# Beware that the subsets in DimensionalData include the bounds. -# Thereby the size of the subset can differ by one on every bound -# `a[X=1..4]`. diff --git a/docs/examples/UserGuide/applyfunctions.jl b/docs/examples/UserGuide/applyfunctions.jl deleted file mode 100644 index 9cd4a8c7..00000000 --- a/docs/examples/UserGuide/applyfunctions.jl +++ /dev/null @@ -1,137 +0,0 @@ -# How to apply functions on YAXArrays - -# To apply user defined functions on a YAXArray data type we can use the [`map`](@ref) function, -# [`mapslices`](@ref) function or the [`mapCube`](@ref) function. Which of these functions should -# be used depends on the layout of the data, that the user defined function should be applied on. - -# ## Apply a function on every element of a datacube - -# The `map` function can be used to apply a function on every entry of a YAXArray without taking -# the dimensions into account. This will lazily register the mapped function which is applied when -# the YAXArray is either accessed or when more involved computations are made. - -#If we set up a dummy data cube which has all numbers between 1 and 10000. - -using YAXArrays -using DimensionalData -axes = (Dim{:Lon}(1:10), Dim{:Lat}(1:10), Dim{:Time}(1:100)) -original = YAXArray(axes, reshape(1:10000, (10,10,100))) - -# with one at the first position: - -original[1,:,1] - -# now we can substract `1` from all elements of this cube -substracted = map(x-> x-1, original) - -# `substracted` is a cube of the same size as `original`, and the applied function is registered, -# so that it is applied as soon as the elements of `substracted` are either accessed or further used -# in other computations. -substracted[1,:,1] - -# ## Apply a function along dimensions of a single cube - -# If an function should work along a certain dimension of the data you can use the 'mapslices' function -# to easily apply this function. This doesn't give you the flexibility of the `mapCube` function but it -# is easier to use for simple functions. - -# If we set up a dummy data cube which has all numbers between 1 and 10000. -axes = (Dim{:Lon}(1:10), Dim{:Lat}(1:10), Dim{:Time}(1:100)) -original = YAXArray(axes, reshape(1:10000, (10,10,100))) - -# and then we would like to compute the sum over the Time dimension: -timesum = mapslices(sum, original, dims="Time") - -# this reduces over the time dimension and gives us the following values -timesum[:,:] - -# You can also apply a function along multiple dimensions of the same data cube. -lonlatsum = mapslices(sum, original, dims=("Lon", "Lat")) - -# ## How to combine multiple cubes in one computation - - -# ## Compute the Mean Seasonal Cycle for one sigle pixel -using CairoMakie -CairoMakie.activate!() -using Dates -using Statistics - -# We define the data span. For simplicity, three non-leap years were selected. -t = Date("2021-01-01"):Day(1):Date("2023-12-31") -NpY = 3 -## create some seasonal dummy data -x = repeat(range(0, 2π, length=365), NpY) -var = @. sin(x) + 0.1 * randn() - -lines(1:length(t), var; color = :purple, linewidth=1.25, - axis=(; xlabel="Time", ylabel="Variable"), - figure = (; resolution = (600,400)) - ) - - # Currently makie doesn't support time axis natively, but the following function can do the work for now. -function time_ticks(dates; frac=8) - tempo = string.(dates) - lentime = length(tempo) - slice_dates = range(1, lentime, step=lentime ÷ frac) - return slice_dates, tempo[slice_dates] -end - -xpos, ticks = time_ticks(t; frac=8) - -# In order to apply the previous output, we split the plotting function into his 3 components, `figure`, `axis` and `plotted object`, namely - -fig, ax, obj = lines(1:length(t), var; color = :purple, linewidth=1.25, - axis=(; xlabel="Time", ylabel="Variable"), - figure = (; resolution = (600,400)) - ) -ax.xticks = (xpos, ticks) -ax.xticklabelrotation = π / 4 -ax.xticklabelalign = (:right, :center) -fig - -# ## Define the cube -axes = (Dim{:Time}(t),) -c = YAXArray(axes, var) - -# Let's calculate the mean seasonal cycle of our dummy variable 'var' - -function mean_seasonal_cycle(c; ndays = 365) - ## filterig by month-day - monthday = map(x->Dates.format(x, "u-d"), collect(c.Time)) - datesid = unique(monthday) - ## number of years - NpY = Int(size(monthday,1)/ndays) - idx = Int.(zeros(ndays, NpY)) - ## get the day-month indices for data subsetting - for i in 1:ndays - idx[i,:] = Int.(findall(x-> x == datesid[i], monthday)) - end - ## compute the mean seasonal cycle - mscarray = map(x->var[x], idx) - msc = mapslices(mean, mscarray, dims=2) - return msc -end - -msc = mean_seasonal_cycle(c); - -# ## Plot results: mean seasonal cycle - -xpos, ticks = time_ticks(t[1:365]; frac=8) - -fig, ax, obj = lines(1:365, var[1:365]; label="2021", color=:black, - linewidth=2.0, linestyle=:dot, - axis = (; xlabel="Time", ylabel="Variable"), - figure=(; resolution = (600,400)) - ) -lines!(1:365, var[366:730], label="2022", color=:brown, - linewidth=1.5, linestyle=:dash - ) -lines!(1:365, msc[:,1]; label="MSC", color=:dodgerblue, lw=2.5) -axislegend() -ax.xticks = (xpos, ticks) -ax.xticklabelrotation = π / 4 -ax.xticklabelalign = (:right, :center) -fig -current_figure() - diff --git a/docs/examples/UserGuide/create_from_func.jl b/docs/examples/UserGuide/create_from_func.jl deleted file mode 100644 index 9c73bbcc..00000000 --- a/docs/examples/UserGuide/create_from_func.jl +++ /dev/null @@ -1,57 +0,0 @@ -using YAXArrays, Zarr -using Dates - -# Define function in space and time - -f(lo, la, t) = (lo + la + Dates.dayofyear(t)) - -# ## Wrap function for mapCube output - -function g(xout,lo,la,t) - xout .= f.(lo,la,t) -end - -# Note the applied `.` after `f`, this is because we will slice/broadcasted across time. - -# ## Create Cube's Axes - -# We wrap the dimensions of every axis into a YAXArray to use them in the mapCube function. -lon = YAXArray(Dim{:lon}(range(1, 15))) -lat = YAXArray(Dim{:lat}(range(1, 10))) -# # And a time axis -tspan = Date("2022-01-01"):Day(1):Date("2022-01-30") -time = YAXArray(Dim{:time}( tspan)) - - -# ## Generate Cube from function -# The following generates a new `cube` using `mapCube` and saving the output directly to disk. - -gen_cube = mapCube(g, (lon, lat, time); - indims = (InDims(), InDims(), InDims("time")), - outdims = OutDims("time", overwrite=true, - path = "my_gen_cube.zarr", backend=:zarr, outtype=Float32), - ## max_cache=1e9 - ) - -# !!! warning "time axis is first" -# Note that currently the `time` axis in the output cube goes first. - -# Check that it is working - -gen_cube.data[1,:,:] - -# ## Generate Cube: change output order - -# The following generates a new `cube` using `mapCube` and saving the output directly to disk. - -gen_cube = mapCube(g, (lon, lat, time); - indims = (InDims("lon"), InDims(), InDims()), - outdims = OutDims("lon", overwrite=true, - path = "my_gen_cube.zarr", backend=:zarr, outtype=Float32), - ## max_cache=1e9 - ) - -# !!! info "slicing dim" -# Note that now the broadcasted dimension is `lon`. - -gen_cube.data[:, :, 1] diff --git a/docs/examples/UserGuide/creating.jl b/docs/examples/UserGuide/creating.jl deleted file mode 100644 index b208ce3c..00000000 --- a/docs/examples/UserGuide/creating.jl +++ /dev/null @@ -1,124 +0,0 @@ -# # Creating YAXArrays and Datasets - -# ## Creating a YAXArray - -using YAXArrays -using DimensionalData: DimensionalData as DD -using DimensionalData -a = YAXArray(rand(10, 20, 5)) - -# if no names are defined then default ones will be used, i.e. `Dim_1`, `Dim_2`. - -## Get data from each Dimension with -a.Dim_1 - -# or with - -getproperty(a, :Dim_1) - -# or even better with the `DD` `lookup` function - -lookup(a, :Dim_1) - -# ## Creating a YAXArray with named axis - -# The two most used axis are `RangeAxis` and `CategoricalAxis`. Here, we use a combination of them -# to create a `time`, `lon` and `lat` axis and a Categorical Axis for two variables. - -# ### Axis definitions -using Dates -axlist = ( - Dim{:time}(Date("2022-01-01"):Day(1):Date("2022-01-30")), - Dim{:lon}(range(1, 10, length=10)), - Dim{:lat}(range(1, 5, length=15)), - Dim{:Variable}(["var1", "var2"]) - ) - -# And the corresponding data - -data = rand(30, 10, 15, 2) -ds = YAXArray(axlist, data) - -# ### Select variables - -ds[Variable = At("var1"), lon = DD.Between(1,2.1)] - -# !!! info -# Please note that selecting elements in YAXArrays is done via the `DimensionalData.jl` syntax. -# For more information checkout the [docs](https://rafaqz.github.io/DimensionalData.jl/). - - -subset = ds[ - time = DD.Between( Date("2022-01-01"), Date("2022-01-10")), - lon=DD.Between(1,2), - Variable = At("var2") - ] - - -# ### Properties / Attributes - -# You might also want to add additional properties to your YAXArray. -# This can be done via a Dictionary, namely - -props = Dict( - "time" => "days", - "lon" => "longitude", - "lat" => "latitude", - "var1" => "first variable", - "var2" => "second variable", -) - -# Then the `yaxarray` with properties is assemble with -ds = YAXArray(axlist, data, props) - -# Access these properties with - -ds.properties - -# Note that this properties are shared for both variables `var1` and `var2`. -# Namely, this are global properties for your yaxarray. -# However, in most cases you will want to pass properties for each variable, -# here we will do this via Datasets. - -# ## Creating a Dataset -# Let's define first some range axis -axs = ( - Dim{:lon}(range(0,1, length=10)), - Dim{:lat}(range(0,1, length=5)), -) - -# And two toy random `YAXArrays` to assemble our dataset - -t2m = YAXArray(axs, rand(10,5), Dict("units" => "K", "reference" => "your references")) -prec = YAXArray(axs, rand(10,5), Dict("units" => "mm", "reference" => "your references")) - -ds = Dataset(t2m=t2m, prec= prec, num = YAXArray(rand(10)), - properties = Dict("space"=>"lon/lat", "reference" => "your global references")) - -# Note that the YAXArrays used not necessarily shared the same dimensions. -# Hence, using a Dataset if more versatile than a plain YAXArray. - -# ### Selected Variables into a Data Cube -# Being able to collect variables that share dimensions into a data cube is possible with - -c = Cube(ds[["t2m", "prec"]]) - -# or simply the one that does not share all dimensions - -Cube(ds[["num"]]) - -# ### Variable properties - -## Access to variables properties is done via -Cube(ds[["t2m"]]).properties - -# and - -Cube(ds[["prec"]]).properties - -# Note also that the global properties for the Dataset are accessed with - -ds.properties - -# Saving and different chunking modes are discussed in [here](). - diff --git a/docs/examples/UserGuide/distributed.jl b/docs/examples/UserGuide/distributed.jl deleted file mode 100644 index 30e4eee2..00000000 --- a/docs/examples/UserGuide/distributed.jl +++ /dev/null @@ -1,59 +0,0 @@ -# # How to calculate a time mean - -using YAXArrays, Statistics, Zarr -using DimensionalData -using Dates -axlist = ( - Dim{:time}(Date("2022-01-01"):Day(1):Date("2022-01-10")), - Dim{:lon}(range(1, 10, length=10)), - Dim{:lat}(range(1, 5, length=15)), - Dim{:Variable}(["var1", "var2"]) - ) -# # And the corresponding data -data = rand(10, 10, 15, 2) -ds = YAXArray(axlist, data) - -c = ds[Variable = At("var1")] # see OpenNetCDF to get the file -mapslices(mean ∘ skipmissing, c, dims="Time") - -# ## Distributed calculations -# It is possible to distribute the calculations over multiple process. The following code -# does a time mean over all grid points using multiple CPU over a local machine. - -# -# ````julia -# using Distributed -# addprocs(2) -# @everywhere begin -# using NetCDF -# using YAXArrays -# using Statistics -# using Zarr -# end -# @everywhere function mymean(output, pixel) -# @show "doing a mean" -# output[:] .= mean(pixel) -# end -# indims = InDims("time") -# outdims = OutDims() -# resultcube = mapCube(mymean, c, indims=indims, outdims=outdims) -# ```` -# - -# In the last example, `mapCube` was used to map the `mymean` function. `mapslices` is a convenient function -# that can replace `mapCube`, where you can omit defining an extra function with the output argument -# as an input (e.g. `mymean`). It is possible to simply use `mapslice` - -resultcube = mapslices(mean ∘ skipmissing, c, dims="time") - - -# It is also possible to distribute easily the workload on a cluster, with little modification to the code. -# To do so, we use the `ClusterManagers` package. - -# -# ````julia -# using Distributed -# using ClusterManagers -# addprocs(SlurmManager(10)) -# ```` -# diff --git a/docs/examples/UserGuide/indexing_subsetting.jl b/docs/examples/UserGuide/indexing_subsetting.jl deleted file mode 100644 index 974ffabb..00000000 --- a/docs/examples/UserGuide/indexing_subsetting.jl +++ /dev/null @@ -1,65 +0,0 @@ -# # Indexing, subsetting and selectors -using YAXArrays, Dates - -## Define a toy cube -t = Date("2020-01-01"):Month(1):Date("2022-12-31") -axes = (Dim{:lon}(-9:10), Dim{:lat}(-5:15), Dim{:time}(t)) -c = YAXArray(axes, reshape(1:20*21*36, (20, 21, 36))) - -# A very convinient selector is `lookup`, getting for example the values for `lon` and `time`: -lon = lookup(c, :lon) -# -tempo = lookup(c, :time) - -# ## lookup -Docs.doc(lookup) # hide - -# ## `At` value - -c[time = At(Date("2021-05-01"))] - -# ## `At` vector of values - -c[time = At([Date("2021-05-01"), Date("2021-06-01")])] - -# similarly for any of the spatial dimensions: - -c[lon = At([-9,-5])] - -# ## `At` values with tolerance (`atol`, `rtol`) - -c[lon = At([-10, 11]; atol = 1)] - -# ## Between -# Altought a `Between(a,b)` function is available in DimensionalData, is recommended to use instead the `a .. b` notation: - -c[lon = -9 .. -7] # close interval, all points included. - -# More selectors from DimensionalData are available: - -# ## DD Selectors -# ### Touches -Docs.doc(Touches) # hide - -# ### Near -Docs.doc(Near) # hide - -# ### Where -Docs.doc(Where) # hide - -# ### Contains -Docs.doc(Contains) # hide - - -# ## Open/Close Intervals - -using IntervalSets - -c[lon = OpenInterval(-9, -7)] -# -c[lon = ClosedInterval(-9, -7)] -# -c[lon =Interval{:open,:closed}(-9,-7)] -# -c[lon =Interval{:closed,:open}(-9,-7)] - diff --git a/docs/examples/UserGuide/openNetCDF.jl b/docs/examples/UserGuide/openNetCDF.jl deleted file mode 100644 index a006a4b8..00000000 --- a/docs/examples/UserGuide/openNetCDF.jl +++ /dev/null @@ -1,26 +0,0 @@ -# In this example we are going to use a `NetCDF` file but this should be very similar for other data backends. -# To open a single data file we first need to load the appropriate backend package via `using NetCDF`. - -# ## One variable -using YAXArrays, NetCDF -using Downloads -url = "https://www.unidata.ucar.edu/software/netcdf/examples/tos_O1_2001-2002.nc" -filename = Downloads.download(url, "tos_O1_2001-2002.nc") # you pick your own path -c = Cube(filename) - -# ## Multiple variables, mixed dimensions - -# When the dataset contains variables with different dimensions you should use `open_dataset` as in - -path2file = "https://www.unidata.ucar.edu/software/netcdf/examples/sresa1b_ncar_ccsm3-example.nc" -filename = Downloads.download(path2file, "sresa1b_ncar_ccsm3-example.nc") -c = open_dataset(filename) - -# Afterwards, selecting a variable as usual works, i.e. -c["ua"] - -# or - -c["tas"] - -# Note that their output is a YAXArray. diff --git a/docs/examples/UserGuide/openZarr.jl b/docs/examples/UserGuide/openZarr.jl deleted file mode 100644 index 92c8d92e..00000000 --- a/docs/examples/UserGuide/openZarr.jl +++ /dev/null @@ -1,4 +0,0 @@ -using Zarr, YAXArrays -store ="gs://cmip6/CMIP6/ScenarioMIP/DKRZ/MPI-ESM1-2-HR/ssp585/r1i1p1f1/3hr/tas/gn/v20190710/" -g = open_dataset(zopen(store, consolidated=true)) -c = g["tas"] \ No newline at end of file diff --git a/docs/examples/UserGuide/saving.jl b/docs/examples/UserGuide/saving.jl deleted file mode 100644 index 73e60464..00000000 --- a/docs/examples/UserGuide/saving.jl +++ /dev/null @@ -1,57 +0,0 @@ -# # Saving YAXArrays and Datasets - -# Is possible to save datasets and YAXArray directly to zarr files. - -# ## Saving a YAXArray to Zarr -# One can save any `YAXArray` using the `savecube` function. -# Simply add a path as an argument and the cube will be saved. - -using YAXArrays, Zarr -a = YAXArray(rand(10,20)) -f = tempname() -savecube(a,f,driver=:zarr) - -# ## Saving a YAXArray to NetCDF -# Saving to NetCDF works exactly the same way. - -using YAXArrays, Zarr, NetCDF -a = YAXArray(rand(10,20)) -f = tempname() -savecube(a,f,driver=:netcdf) - -# ## Saving a Dataset - -# Saving Datasets can be done using the `savedataset` function. -using YAXArrays, Zarr -ds = Dataset(x = YAXArray(rand(10,20)), y = YAXArray(rand(10))); -f = tempname(); -savedataset(ds,path=f,driver=:zarr) -# ## Overwriting a Dataset -# If a path already exists, an error will be thrown. Set `overwrite=true` to delete the existing dataset -savedataset(ds,path=f,driver=:zarr, overwrite=true) - -# Look at the docs for more information - -Docs.doc(savedataset) # hide - -# ## Appending to a Dataset -# New variables can be added to an existing dataset using the `append=true` keyword. -ds2 = Dataset(z = YAXArray(rand(10,20,5))) -savedataset(ds2, path=f,backend=:zarr,append=true) -open_dataset(f, driver=:zarr) - -# ## Datacube Skeleton without the actual data -# Sometimes one merely wants to create a datacube "Skeleton" on disk and gradually fill it with data. -# Here we make use of FillArrays to create a YAXArray and write only the axis data and array metadata to disk, -# while no actual array data is copied: - -using YAXArrays, Zarr, FillArrays -a = YAXArray(Zeros(Union{Missing, Int32},10,20)) -f = tempname(); -r = savecube(a,f,driver=:zarr,skeleton=true); -all(ismissing,r[:,:]) - -# If using FillArrays is not possible, using the `zeros` function works as well, though it does allocate the array -# in memory. - -# The `skeleton` argument is also available for `savedataset`. diff --git a/docs/examples/UserGuide/setchuncks.jl b/docs/examples/UserGuide/setchuncks.jl deleted file mode 100644 index ae6eb0e9..00000000 --- a/docs/examples/UserGuide/setchuncks.jl +++ /dev/null @@ -1,66 +0,0 @@ -# # Set chunks - -# To determine the chunk size of the array representation on disk, -# call the `setchunks` function prior to saving. - -# ## Chunking YAXArrays - -using YAXArrays, Zarr -a = YAXArray(rand(10,20)) -a_chunked = setchunks(a, (5,10)) -a_chunked.chunks - -# And the saved file is also splitted into Chunks. -f = tempname() -savecube(a_chunked, f, backend=:zarr) -Cube(f).chunks - -# Alternatively chunk sizes can be given by dimension name, so the following results in the same chunks: - -a_chunked = setchunks(a, (Dim_2=10, Dim_1=5)) -a_chunked.chunks - -# ## Chunking Datasets -# ### Set Chunks by Axis - -# Set chunk size for each axis occuring in a dataset. This will be applied to all variables in the dataset: - - -using YAXArrays, Zarr -ds = Dataset(x = YAXArray(rand(10,20)), y = YAXArray(rand(10)), z = YAXArray(rand(10,20,5))) -dschunked = setchunks(ds, Dict("Dim_1"=>5, "Dim_2"=>10, "Dim_3"=>2)) -Cube(dschunked).chunks - -# Saving... - -f = tempname() -savedataset(dschunked, path=f,driver=:zarr) - -# ### Set chunking by Variable - -# The following will set the chunk size for each Variable separately -# and results in exactly the same chunking as the example above - -using YAXArrays, Zarr -ds = Dataset(x = YAXArray(rand(10,20)), y = YAXArray(rand(10)), z = YAXArray(rand(10,20,5))) -dschunked = setchunks(ds,(x = (5,10), y = Dict("Dim_1"=>5), z = (Dim_1 = 5, Dim_2 = 10, Dim_3 = 2))) -Cube(dschunked).chunks - -# saving... - -f = tempname() -savedataset(dschunked,path=f,driver=:zarr) - -# ### Set chunking for all variables - -# The following code snippet only works when all member variables of the dataset have the same shape and sets the output chunks for all arrays. - -using YAXArrays, Zarr -ds = Dataset(x = YAXArray(rand(10,20)), y = YAXArray(rand(10,20)), z = YAXArray(rand(10,20))) -dschunked = setchunks(ds,(5,10)) -Cube(dschunked).chunks - -# saving... - -f = tempname() -savedataset(dschunked,path=f,driver=:zarr) \ No newline at end of file diff --git a/docs/examples/contribute/contribute.jl b/docs/examples/contribute/contribute.jl deleted file mode 100644 index bb661561..00000000 --- a/docs/examples/contribute/contribute.jl +++ /dev/null @@ -1,44 +0,0 @@ -# ## Contribute to Documentation -# Contributing with examples can be done by first creating a new file example -# [here](https://github.com/JuliaDataCubes/YAXArrays.jl/tree/master/docs/examples/UserGuide) - -# !!! info "new file" -# - `your_new_file.jl` at `docs/examples/UserGuide/` - -# Once this is done you need to add a new entry [here](https://github.com/JuliaDataCubes/YAXArrays.jl/blob/master/docs/mkdocs.yml) -# at the bottom and the appropriate level. - -# !!! info "add entry to docs" -# Your new entry should look like: -# - `"Your title example" : "examples/generated/UserGuide/your_new_file.md"` - -# ## Build docs locally -# If you want to take a look at the docs locally before doing a PR -# follow the next steps: - -# !!! warning "build docs locally" -# Install the following dependencies in your system via pip, i.e. -# - `pip install mkdocs pygments python-markdown-math` -# - `pip install mkdocs-material pymdown-extensions mkdocstrings` -# - `pip mknotebooks pytkdocs_tweaks mkdocs_include_exclude_files jinja2 mkdocs-video` - -# Then simply go to your `docs` env and activate it, i.e. - -# `docs> julia` - -# `julia> ]` - -# `(docs) pkg> activate .` - -# Next, run the scripts: -# !!! info "Julia env: docs" -# Generate files and build docs by running: -# - `include("genfiles.jl")` -# - `include("make.jl")` - -# Now go to your `terminal` in the same path `docs>` and run: - -# `mkdocs serve` - -# This should ouput `http://127.0.0.1:8000`, copy/paste this into your -# browser and you are all set. \ No newline at end of file diff --git a/docs/genfiles.jl b/docs/genfiles.jl deleted file mode 100644 index b735e194..00000000 --- a/docs/genfiles.jl +++ /dev/null @@ -1,35 +0,0 @@ -using Documenter, DocumenterMarkdown -using Literate - -get_example_path(p) = joinpath(@__DIR__, ".", "examples", p) -OUTPUT = joinpath(@__DIR__, "src", "examples", "generated") - -folders = readdir(joinpath(@__DIR__, ".", "examples")) -setdiff!(folders, [".DS_Store", "tos_O1_2001-2002.nc"]) - -function getfiles() - srcsfiles = [] - for f in folders - names = readdir(joinpath(@__DIR__, ".", "examples", f)) - setdiff!(names, [".DS_Store", - "examples_from_esdl_study_1.jl", - "examples_from_esdl_study_2.jl", - "examples_from_esdl_study_3.jl", - "examples_from_esdl_study_4.jl", - ] - ) - fpaths = "$(f)/" .* names - srcsfiles = vcat(srcsfiles, fpaths...) - end - return srcsfiles -end - -srcsfiles = getfiles() - -for (d, paths) in (("tutorial", srcsfiles),) - for p in paths - Literate.markdown(get_example_path(p), joinpath(OUTPUT, dirname(p)); - documenter=true) - end - -end \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index 859f90df..e6fe2441 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,26 +1,63 @@ -using YAXArrays, Documenter, DocumenterMarkdown +using Documenter +using DocumenterVitepress +# add https://github.com/LuxDL/DocumenterVitepress.jl.git +# add DimensionalData#main +using YAXArrays -makedocs( - modules = [YAXArrays], - clean = true, - doctest=true, - #format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"), - sitename = "YAXArrays.jl", - authors = "Fabian Gans et al.", - strict=[ - :doctest, - :linkcheck, - :parse_error, - :example_block, - # Other available options are - # :autodocs_block, :cross_references, :docs_block, :eval_block, :example_block, - # :footnote, :meta_block, :missing_docs, :setup_block - ], checkdocs=:all, format=Markdown(), draft=false, - build=joinpath(@__DIR__, "docs") +makedocs(; sitename="YAXArrays.jl", + authors="Fabian Gans et al.", + modules=[YAXArrays], + warnonly = true, + checkdocs=:all, + format=DocumenterVitepress.MarkdownVitepress(), + draft=false, + source="src", + build=joinpath(@__DIR__, "build") + ) + +# To edit the sidebar, you must edit `docs/src/.vitepress/config.mts`. + +# We manually obtain the Documenter deploy configuration, +# so we can use it to set Vitepress's settings. +# TODO: make this better / encapsulate it in `makedocs` +# so the user does not need to know! +deploy_config = Documenter.auto_detect_deploy_system() +deploy_decision = Documenter.deploy_folder( + deploy_config; + repo="github.com/JuliaDataCubes/YAXArrays.jl.git", # this must be the full URL! + devbranch="master", + devurl = "dev", + push_preview=true, +) + +# VitePress relies on its config file in order to understand where files will exist. +# We need to modify this file to reflect the correct base URL, however, Documenter +# only knows about the base URL at the time of deployment. + +# So, after building the Markdown, we need to modify the config file to reflect the +# correct base URL, and then build the VitePress site. +folder = deploy_decision.subfolder +println("Deploying to $folder") +vitepress_config_file = joinpath(@__DIR__, "build", ".vitepress", "config.mts") +config = read(vitepress_config_file, String) +new_config = replace( + config, + "base: 'REPLACE_ME_WITH_DOCUMENTER_VITEPRESS_BASE_URL_WITH_TRAILING_SLASH'" => "base: '/YAXArrays.jl/$(folder)$(isempty(folder) ? "" : "/")'" ) +write(vitepress_config_file, new_config) + +# Build the docs using `npm` - we are assuming it's installed here! +haskey(ENV, "CI") && begin + cd(@__DIR__) do + run(`npm run docs:build`) + end + touch(joinpath(@__DIR__, "build", ".vitepress", "dist", ".nojekyll")) +end -deploydocs(; repo="github.com/JuliaDataCubes/YAXArrays.jl.git", push_preview=true, - deps=Deps.pip("mkdocs", "pygments", "python-markdown-math", "mkdocs-material", - "pymdown-extensions", "mkdocstrings", "mknotebooks", - "pytkdocs_tweaks", "mkdocs_include_exclude_files", "jinja2", "mkdocs-video"), - make=() -> run(`mkdocs build`), target="site", devbranch="master") \ No newline at end of file +deploydocs(; + repo="github.com/JuliaDataCubes/YAXArrays.jl.git", # this must be the full URL! + target="build/.vitepress/dist", # this is where Vitepress stores its output + branch = "gh-pages", + devbranch="master", + push_preview = true +) \ No newline at end of file diff --git a/docs/package-lock.json b/docs/package-lock.json new file mode 100644 index 00000000..c7c11620 --- /dev/null +++ b/docs/package-lock.json @@ -0,0 +1,2893 @@ +{ + "name": "docs", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "markdown-it": "^14.0.0", + "markdown-it-mathjax3": "^4.3.2", + "vitepress-plugin-tabs": "^0.5.0", + "vitest": "^1.3.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", + "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", + "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", + "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", + "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.22.1.tgz", + "integrity": "sha512-Sw6IAmOCvvP6QNgY9j+Hv09mvkvEIDKjYW8ow0UDDAxSXy664RBNQk3i/0nt7gvceOJ6jGmOTimaZoY1THmU7g==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/cache-common": "4.22.1" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.22.1.tgz", + "integrity": "sha512-TJMBKqZNKYB9TptRRjSUtevJeQVXRmg6rk9qgFKWvOy8jhCPdyNZV1nB3SKGufzvTVbomAukFR8guu/8NRKBTA==", + "dev": true, + "peer": true + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.22.1.tgz", + "integrity": "sha512-ve+6Ac2LhwpufuWavM/aHjLoNz/Z/sYSgNIXsinGofWOysPilQZPUetqLj8vbvi+DHZZaYSEP9H5SRVXnpsNNw==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/cache-common": "4.22.1" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.22.1.tgz", + "integrity": "sha512-k8m+oegM2zlns/TwZyi4YgCtyToackkOpE+xCaKCYfBfDtdGOaVZCM5YvGPtK+HGaJMIN/DoTL8asbM3NzHonw==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/client-common": "4.22.1", + "@algolia/client-search": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.22.1.tgz", + "integrity": "sha512-1ssi9pyxyQNN4a7Ji9R50nSdISIumMFDwKNuwZipB6TkauJ8J7ha/uO60sPJFqQyqvvI+px7RSNRQT3Zrvzieg==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/client-common": "4.22.1", + "@algolia/client-search": "4.22.1", + "@algolia/requester-common": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, + "node_modules/@algolia/client-common": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.22.1.tgz", + "integrity": "sha512-IvaL5v9mZtm4k4QHbBGDmU3wa/mKokmqNBqPj0K7lcR8ZDKzUorhcGp/u8PkPC/e0zoHSTvRh7TRkGX3Lm7iOQ==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/requester-common": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.22.1.tgz", + "integrity": "sha512-sl+/klQJ93+4yaqZ7ezOttMQ/nczly/3GmgZXJ1xmoewP5jmdP/X/nV5U7EHHH3hCUEHeN7X1nsIhGPVt9E1cQ==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/client-common": "4.22.1", + "@algolia/requester-common": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, + "node_modules/@algolia/client-search": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.22.1.tgz", + "integrity": "sha512-yb05NA4tNaOgx3+rOxAmFztgMTtGBi97X7PC3jyNeGiwkAjOZc2QrdZBYyIdcDLoI09N0gjtpClcackoTN0gPA==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/client-common": "4.22.1", + "@algolia/requester-common": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, + "node_modules/@algolia/logger-common": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.22.1.tgz", + "integrity": "sha512-OnTFymd2odHSO39r4DSWRFETkBufnY2iGUZNrMXpIhF5cmFE8pGoINNPzwg02QLBlGSaLqdKy0bM8S0GyqPLBg==", + "dev": true, + "peer": true + }, + "node_modules/@algolia/logger-console": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.22.1.tgz", + "integrity": "sha512-O99rcqpVPKN1RlpgD6H3khUWylU24OXlzkavUAMy6QZd1776QAcauE3oP8CmD43nbaTjBexZj2nGsBH9Tc0FVA==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/logger-common": "4.22.1" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.22.1.tgz", + "integrity": "sha512-dtQGYIg6MteqT1Uay3J/0NDqD+UciHy3QgRbk7bNddOJu+p3hzjTRYESqEnoX/DpEkaNYdRHUKNylsqMpgwaEw==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/requester-common": "4.22.1" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.22.1.tgz", + "integrity": "sha512-dgvhSAtg2MJnR+BxrIFqlLtkLlVVhas9HgYKMk2Uxiy5m6/8HZBL40JVAMb2LovoPFs9I/EWIoFVjOrFwzn5Qg==", + "dev": true, + "peer": true + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.22.1.tgz", + "integrity": "sha512-JfmZ3MVFQkAU+zug8H3s8rZ6h0ahHZL/SpMaSasTCGYR5EEJsCc8SI5UZ6raPN2tjxa5bxS13BRpGSBUens7EA==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/requester-common": "4.22.1" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.22.1.tgz", + "integrity": "sha512-kzWgc2c9IdxMa3YqA6TN0NW5VrKYYW/BELIn7vnLyn+U/RFdZ4lxxt9/8yq3DKV5snvoDzzO4ClyejZRdV3lMQ==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/cache-common": "4.22.1", + "@algolia/logger-common": "4.22.1", + "@algolia/requester-common": "4.22.1" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "dev": true, + "peer": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.5.2.tgz", + "integrity": "sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==", + "dev": true, + "peer": true + }, + "node_modules/@docsearch/js": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.5.2.tgz", + "integrity": "sha512-p1YFTCDflk8ieHgFJYfmyHBki1D61+U9idwrLh+GQQMrBSP3DLGKpy0XUJtPjAOPltcVbqsTjiPFfH7JImjUNg==", + "dev": true, + "peer": true, + "dependencies": { + "@docsearch/react": "3.5.2", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/react": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.5.2.tgz", + "integrity": "sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.5.2", + "algoliasearch": "^4.19.1" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz", + "integrity": "sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.0.tgz", + "integrity": "sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.0.tgz", + "integrity": "sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.0.tgz", + "integrity": "sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.0.tgz", + "integrity": "sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.0.tgz", + "integrity": "sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.0.tgz", + "integrity": "sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.0.tgz", + "integrity": "sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.0.tgz", + "integrity": "sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.0.tgz", + "integrity": "sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.0.tgz", + "integrity": "sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.0.tgz", + "integrity": "sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.0.tgz", + "integrity": "sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.1.3.tgz", + "integrity": "sha512-1QWSvWcPbvZXsDxB1F7ejW+Kuxp3z/JHs944hp/f8BYOlFd5gplzseFIkE/GTu/qytFef3zNME4qw1oHbQ0j2A==", + "dev": true, + "peer": true + }, + "node_modules/@shikijs/transformers": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.1.3.tgz", + "integrity": "sha512-jv71dQFTucv2RK2pafAxca4hgKP6Uv5ukKrVjH/vGZ8jGH0j2AcLVCcM76ieamwJ1p5WkZcA0X/Bq2qpjhEUSg==", + "dev": true, + "peer": true, + "dependencies": { + "shiki": "1.1.3" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/linkify-it": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", + "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==", + "dev": true, + "peer": true + }, + "node_modules/@types/markdown-it": { + "version": "13.0.7", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-13.0.7.tgz", + "integrity": "sha512-U/CBi2YUUcTHBt5tjO2r5QV/x0Po6nsYwQU4Y04fBS6vfoImaiZ6f8bi3CjTCxBPQSO1LMyUqkByzi8AidyxfA==", + "dev": true, + "peer": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz", + "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==", + "dev": true, + "peer": true + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", + "dev": true, + "peer": true + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz", + "integrity": "sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==", + "dev": true, + "peer": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vitest/expect": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.3.0.tgz", + "integrity": "sha512-7bWt0vBTZj08B+Ikv70AnLRicohYwFgzNjFqo9SxxqHHxSlUJGSXmCRORhOnRMisiUryKMdvsi1n27Bc6jL9DQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.3.0", + "@vitest/utils": "1.3.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.3.0.tgz", + "integrity": "sha512-1Jb15Vo/Oy7mwZ5bXi7zbgszsdIBNjc4IqP8Jpr/8RdBC4nF1CTzIAn2dxYvpF1nGSseeL39lfLQ2uvs5u1Y9A==", + "dev": true, + "dependencies": { + "@vitest/utils": "1.3.0", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.3.0.tgz", + "integrity": "sha512-swmktcviVVPYx9U4SEQXLV6AEY51Y6bZ14jA2yo6TgMxQ3h+ZYiO0YhAHGJNp0ohCFbPAis1R9kK0cvN6lDPQA==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.3.0.tgz", + "integrity": "sha512-AkCU0ThZunMvblDpPKgjIi025UxR8V7MZ/g/EwmAGpjIujLVV2X6rGYGmxE2D4FJbAy0/ijdROHMWa2M/6JVMw==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.3.0.tgz", + "integrity": "sha512-/LibEY/fkaXQufi4GDlQZhikQsPO2entBKtfuyIpr1jV4DpaeasqkeHjhdOhU24vSHshcSuEyVlWdzvv2XmYCw==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.19.tgz", + "integrity": "sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/parser": "^7.23.9", + "@vue/shared": "3.4.19", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.0.2" + } + }, + "node_modules/@vue/compiler-core/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "peer": true + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.19.tgz", + "integrity": "sha512-vm6+cogWrshjqEHTzIDCp72DKtea8Ry/QVpQRYoyTIg9k7QZDX6D8+HGURjtmatfgM8xgCFtJJaOlCaRYRK3QA==", + "dev": true, + "peer": true, + "dependencies": { + "@vue/compiler-core": "3.4.19", + "@vue/shared": "3.4.19" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.19.tgz", + "integrity": "sha512-LQ3U4SN0DlvV0xhr1lUsgLCYlwQfUfetyPxkKYu7dkfvx7g3ojrGAkw0AERLOKYXuAGnqFsEuytkdcComei3Yg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/parser": "^7.23.9", + "@vue/compiler-core": "3.4.19", + "@vue/compiler-dom": "3.4.19", + "@vue/compiler-ssr": "3.4.19", + "@vue/shared": "3.4.19", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.6", + "postcss": "^8.4.33", + "source-map-js": "^1.0.2" + } + }, + "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "peer": true + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.19.tgz", + "integrity": "sha512-P0PLKC4+u4OMJ8sinba/5Z/iDT84uMRRlrWzadgLA69opCpI1gG4N55qDSC+dedwq2fJtzmGald05LWR5TFfLw==", + "dev": true, + "peer": true, + "dependencies": { + "@vue/compiler-dom": "3.4.19", + "@vue/shared": "3.4.19" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.0.15.tgz", + "integrity": "sha512-kgEYWosDyWpS1vFSuJNNWUnHkP+VkL3Y+9mw+rf7ex41SwbYL/WdC3KXqAtjiSrEs7r/FrHmUTh0BkINJPFkbA==", + "dev": true, + "peer": true, + "dependencies": { + "@vue/devtools-kit": "^7.0.15" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.0.15.tgz", + "integrity": "sha512-dT7OeCe1LUCIhHIb/yRR6Hn+XHh73r1o78onqCrxEKHdoZwBItiIeVnmJZPEUDFstIxfs+tJL231mySk3laTow==", + "dev": true, + "peer": true, + "dependencies": { + "@vue/devtools-shared": "^7.0.15", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.0.15.tgz", + "integrity": "sha512-fpfvMVvS7aDgO7x2JPFiTQ1MHcCc63/bE7yTgs278gMBybuO9b3hdiZ/k0Pw1rN+RefaU9yQiFA+5CCFc1D+6w==", + "dev": true, + "peer": true, + "dependencies": { + "rfdc": "^1.3.1" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.19.tgz", + "integrity": "sha512-+VcwrQvLZgEclGZRHx4O2XhyEEcKaBi50WbxdVItEezUf4fqRh838Ix6amWTdX0CNb/b6t3Gkz3eOebfcSt+UA==", + "dev": true, + "peer": true, + "dependencies": { + "@vue/shared": "3.4.19" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.19.tgz", + "integrity": "sha512-/Z3tFwOrerJB/oyutmJGoYbuoadphDcJAd5jOuJE86THNZji9pYjZroQ2NFsZkTxOq0GJbb+s2kxTYToDiyZzw==", + "dev": true, + "peer": true, + "dependencies": { + "@vue/reactivity": "3.4.19", + "@vue/shared": "3.4.19" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.19.tgz", + "integrity": "sha512-IyZzIDqfNCF0OyZOauL+F4yzjMPN2rPd8nhqPP2N1lBn3kYqJpPHHru+83Rkvo2lHz5mW+rEeIMEF9qY3PB94g==", + "dev": true, + "peer": true, + "dependencies": { + "@vue/runtime-core": "3.4.19", + "@vue/shared": "3.4.19", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.19.tgz", + "integrity": "sha512-eAj2p0c429RZyyhtMRnttjcSToch+kTWxFPHlzGMkR28ZbF1PDlTcmGmlDxccBuqNd9iOQ7xPRPAGgPVj+YpQw==", + "dev": true, + "peer": true, + "dependencies": { + "@vue/compiler-ssr": "3.4.19", + "@vue/shared": "3.4.19" + }, + "peerDependencies": { + "vue": "3.4.19" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", + "integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==", + "dev": true, + "peer": true + }, + "node_modules/@vueuse/core": { + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.7.2.tgz", + "integrity": "sha512-AOyAL2rK0By62Hm+iqQn6Rbu8bfmbgaIMXcE3TSr7BdQ42wnSFlwIdPjInO62onYsEMK/yDMU8C6oGfDAtZ2qQ==", + "dev": true, + "peer": true, + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "10.7.2", + "@vueuse/shared": "10.7.2", + "vue-demi": ">=0.14.6" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "dev": true, + "hasInstallScript": true, + "peer": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/integrations": { + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-10.7.2.tgz", + "integrity": "sha512-+u3RLPFedjASs5EKPc69Ge49WNgqeMfSxFn+qrQTzblPXZg6+EFzhjarS5edj2qAf6xQ93f95TUxRwKStXj/sQ==", + "dev": true, + "peer": true, + "dependencies": { + "@vueuse/core": "10.7.2", + "@vueuse/shared": "10.7.2", + "vue-demi": ">=0.14.6" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "*", + "axios": "*", + "change-case": "*", + "drauu": "*", + "focus-trap": "*", + "fuse.js": "*", + "idb-keyval": "*", + "jwt-decode": "*", + "nprogress": "*", + "qrcode": "*", + "sortablejs": "*", + "universal-cookie": "*" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/integrations/node_modules/vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "dev": true, + "hasInstallScript": true, + "peer": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.7.2.tgz", + "integrity": "sha512-kCWPb4J2KGrwLtn1eJwaJD742u1k5h6v/St5wFe8Quih90+k2a0JP8BS4Zp34XUuJqS2AxFYMb1wjUL8HfhWsQ==", + "dev": true, + "peer": true, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.7.2.tgz", + "integrity": "sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==", + "dev": true, + "peer": true, + "dependencies": { + "vue-demi": ">=0.14.6" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "dev": true, + "hasInstallScript": true, + "peer": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/algoliasearch": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.22.1.tgz", + "integrity": "sha512-jwydKFQJKIx9kIZ8Jm44SdpigFwRGPESaxZBaHSV0XWN2yBJAOT4mT7ppvlrpA4UGzz92pqFnVKr/kaZXrcreg==", + "dev": true, + "peer": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.22.1", + "@algolia/cache-common": "4.22.1", + "@algolia/cache-in-memory": "4.22.1", + "@algolia/client-account": "4.22.1", + "@algolia/client-analytics": "4.22.1", + "@algolia/client-common": "4.22.1", + "@algolia/client-personalization": "4.22.1", + "@algolia/client-search": "4.22.1", + "@algolia/logger-common": "4.22.1", + "@algolia/logger-console": "4.22.1", + "@algolia/requester-browser-xhr": "4.22.1", + "@algolia/requester-common": "4.22.1", + "@algolia/requester-node-http": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "dev": true, + "dependencies": { + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", + "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", + "dev": true, + "dependencies": { + "css-select": "^4.3.0", + "css-what": "^6.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.3.1", + "domutils": "^2.8.0" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "peer": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/escape-goat": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz", + "integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/focus-trap": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", + "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", + "dev": true, + "peer": true, + "dependencies": { + "tabbable": "^6.2.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "peer": true + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz", + "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==", + "dev": true + }, + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true + }, + "node_modules/juice": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/juice/-/juice-8.1.0.tgz", + "integrity": "sha512-FLzurJrx5Iv1e7CfBSZH68dC04EEvXvvVvPYB7Vx1WAuhCp1ZPIMtqxc+WTWxVkpTIC2Ach/GAv0rQbtGf6YMA==", + "dev": true, + "dependencies": { + "cheerio": "1.0.0-rc.10", + "commander": "^6.1.0", + "mensch": "^0.3.4", + "slick": "^1.12.2", + "web-resource-inliner": "^6.0.1" + }, + "bin": { + "juice": "bin/juice" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dev": true, + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/magic-string": { + "version": "0.30.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", + "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true, + "peer": true + }, + "node_modules/markdown-it": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.0.0.tgz", + "integrity": "sha512-seFjF0FIcPt4P9U39Bq1JYblX0KZCjDLFFQPHpL5AzHpqPEKtosxmdq/LTVZnjfH7tjt9BxStm+wXcDBNuYmzw==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.0.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-mathjax3": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/markdown-it-mathjax3/-/markdown-it-mathjax3-4.3.2.tgz", + "integrity": "sha512-TX3GW5NjmupgFtMJGRauioMbbkGsOXAAt1DZ/rzzYmTHqzkO1rNAdiMD4NiruurToPApn2kYy76x02QN26qr2w==", + "dev": true, + "dependencies": { + "juice": "^8.0.0", + "mathjax-full": "^3.2.0" + } + }, + "node_modules/mathjax-full": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.2.tgz", + "integrity": "sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==", + "dev": true, + "dependencies": { + "esm": "^3.2.25", + "mhchemparser": "^4.1.0", + "mj-context-menu": "^0.6.1", + "speech-rule-engine": "^4.0.6" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true + }, + "node_modules/mensch": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/mensch/-/mensch-0.3.4.tgz", + "integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/mhchemparser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.2.1.tgz", + "integrity": "sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==", + "dev": true + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minisearch": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-6.3.0.tgz", + "integrity": "sha512-ihFnidEeU8iXzcVHy74dhkxh/dn8Dc08ERl0xwoMMGqp4+LvRSCgicb+zGqWthVokQKvCSxITlh3P08OzdTYCQ==", + "dev": true, + "peer": true + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "peer": true + }, + "node_modules/mj-context-menu": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz", + "integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==", + "dev": true + }, + "node_modules/mlly": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.5.0.tgz", + "integrity": "sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.0.3", + "ufo": "^1.3.2" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/npm-run-path": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true, + "peer": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/pkg-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", + "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0" + } + }, + "node_modules/postcss": { + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preact": { + "version": "10.19.5", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.5.tgz", + "integrity": "sha512-OPELkDmSVbKjbFqF9tgvOowiiQ9TmsJljIzXRyNE8nGiis94pwv1siF78rQkAP1Q1738Ce6pellRg/Ns/CtHqQ==", + "dev": true, + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true, + "peer": true + }, + "node_modules/rollup": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.0.tgz", + "integrity": "sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.12.0", + "@rollup/rollup-android-arm64": "4.12.0", + "@rollup/rollup-darwin-arm64": "4.12.0", + "@rollup/rollup-darwin-x64": "4.12.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.12.0", + "@rollup/rollup-linux-arm64-gnu": "4.12.0", + "@rollup/rollup-linux-arm64-musl": "4.12.0", + "@rollup/rollup-linux-riscv64-gnu": "4.12.0", + "@rollup/rollup-linux-x64-gnu": "4.12.0", + "@rollup/rollup-linux-x64-musl": "4.12.0", + "@rollup/rollup-win32-arm64-msvc": "4.12.0", + "@rollup/rollup-win32-ia32-msvc": "4.12.0", + "@rollup/rollup-win32-x64-msvc": "4.12.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/search-insights": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.13.0.tgz", + "integrity": "sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw==", + "dev": true, + "peer": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shiki": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.1.3.tgz", + "integrity": "sha512-k/B4UvtWmGcHMLp6JnQminlex3Go5MHKXEiormmzTJECAiSQiwSon6USuwTyto8EMUQc9aYRJ7HojkfVLbBk+g==", + "dev": true, + "peer": true, + "dependencies": { + "@shikijs/core": "1.1.3" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slick": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/slick/-/slick-1.12.2.tgz", + "integrity": "sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speech-rule-engine": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/speech-rule-engine/-/speech-rule-engine-4.0.7.tgz", + "integrity": "sha512-sJrL3/wHzNwJRLBdf6CjJWIlxC04iYKkyXvYSVsWVOiC2DSkHmxsqOhEeMsBA9XK+CHuNcsdkbFDnoUfAsmp9g==", + "dev": true, + "dependencies": { + "commander": "9.2.0", + "wicked-good-xpath": "1.3.0", + "xmldom-sre": "0.1.31" + }, + "bin": { + "sre": "bin/sre" + } + }, + "node_modules/speech-rule-engine/node_modules/commander": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz", + "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.0.0.tgz", + "integrity": "sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==", + "dev": true, + "dependencies": { + "js-tokens": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "dev": true, + "peer": true + }, + "node_modules/tinybench": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz", + "integrity": "sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz", + "integrity": "sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/uc.micro": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.0.0.tgz", + "integrity": "sha512-DffL94LsNOccVn4hyfRe5rdKa273swqeA5DJpMOeFmEn1wCDc7nAbbB0gXlgBCL7TNzeTv6G7XVWzan7iJtfig==", + "dev": true + }, + "node_modules/ufo": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", + "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==", + "dev": true + }, + "node_modules/valid-data-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-3.0.1.tgz", + "integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/vite": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.3.tgz", + "integrity": "sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==", + "dev": true, + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.35", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.3.0.tgz", + "integrity": "sha512-D/oiDVBw75XMnjAXne/4feCkCEwcbr2SU1bjAhCcfI5Bq3VoOHji8/wCPAfUkDIeohJ5nSZ39fNxM3dNZ6OBOA==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitepress": { + "version": "1.0.0-rc.43", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.0.0-rc.43.tgz", + "integrity": "sha512-XZ9xaN76/LxCBqvk6U+3ne3T60JOavdOlk+FMQBlXYK/9pyyKGfjnEra4yKYvOdZdStoTg8VXTAj4wcsCTlJaQ==", + "dev": true, + "peer": true, + "dependencies": { + "@docsearch/css": "^3.5.2", + "@docsearch/js": "^3.5.2", + "@shikijs/core": "^1.1.3", + "@shikijs/transformers": "^1.1.3", + "@types/markdown-it": "^13.0.7", + "@vitejs/plugin-vue": "^5.0.4", + "@vue/devtools-api": "^7.0.14", + "@vueuse/core": "^10.7.2", + "@vueuse/integrations": "^10.7.2", + "focus-trap": "^7.5.4", + "mark.js": "8.11.1", + "minisearch": "^6.3.0", + "shiki": "^1.1.3", + "vite": "^5.1.3", + "vue": "^3.4.19" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4.3.2", + "postcss": "^8.4.35" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/vitepress-plugin-tabs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/vitepress-plugin-tabs/-/vitepress-plugin-tabs-0.5.0.tgz", + "integrity": "sha512-SIhFWwGsUkTByfc2b279ray/E0Jt8vDTsM1LiHxmCOBAEMmvzIBZSuYYT1DpdDTiS3SuJieBheJkYnwCq/yD9A==", + "dev": true, + "peerDependencies": { + "vitepress": "^1.0.0-rc.27", + "vue": "^3.3.8" + } + }, + "node_modules/vitest": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.3.0.tgz", + "integrity": "sha512-V9qb276J1jjSx9xb75T2VoYXdO1UKi+qfflY7V7w93jzX7oA/+RtYE6TcifxksxsZvygSSMwu2Uw6di7yqDMwg==", + "dev": true, + "dependencies": { + "@vitest/expect": "1.3.0", + "@vitest/runner": "1.3.0", + "@vitest/snapshot": "1.3.0", + "@vitest/spy": "1.3.0", + "@vitest/utils": "1.3.0", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.2", + "vite": "^5.0.0", + "vite-node": "1.3.0", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.3.0", + "@vitest/ui": "1.3.0", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.19.tgz", + "integrity": "sha512-W/7Fc9KUkajFU8dBeDluM4sRGc/aa4YJnOYck8dkjgZoXtVsn3OeTGni66FV1l3+nvPA7VBFYtPioaGKUmEADw==", + "dev": true, + "peer": true, + "dependencies": { + "@vue/compiler-dom": "3.4.19", + "@vue/compiler-sfc": "3.4.19", + "@vue/runtime-dom": "3.4.19", + "@vue/server-renderer": "3.4.19", + "@vue/shared": "3.4.19" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/web-resource-inliner": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-6.0.1.tgz", + "integrity": "sha512-kfqDxt5dTB1JhqsCUQVFDj0rmY+4HLwGQIsLPbyrsN9y9WV/1oFDSx3BQ4GfCv9X+jVeQ7rouTqwK53rA/7t8A==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1", + "escape-goat": "^3.0.0", + "htmlparser2": "^5.0.0", + "mime": "^2.4.6", + "node-fetch": "^2.6.0", + "valid-data-url": "^3.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/web-resource-inliner/node_modules/domhandler": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz", + "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/web-resource-inliner/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/web-resource-inliner/node_modules/htmlparser2": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz", + "integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^3.3.0", + "domutils": "^2.4.2", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/fb55/htmlparser2?sponsor=1" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wicked-good-xpath": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz", + "integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==", + "dev": true + }, + "node_modules/xmldom-sre": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom-sre/-/xmldom-sre-0.1.31.tgz", + "integrity": "sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw==", + "dev": true, + "engines": { + "node": ">=0.1" + } + }, + "node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 00000000..376a4f7f --- /dev/null +++ b/docs/package.json @@ -0,0 +1,13 @@ +{ + "scripts": { + "docs:dev": "vitepress dev build", + "docs:build": "vitepress build build", + "docs:preview": "vitepress preview build" + }, + "devDependencies": { + "markdown-it": "^14.0.0", + "markdown-it-mathjax3": "^4.3.2", + "vitepress-plugin-tabs": "^0.5.0", + "vitest": "^1.3.0" + } +} diff --git a/docs/src/.vitepress/config.mts b/docs/src/.vitepress/config.mts new file mode 100644 index 00000000..a6fe1ca6 --- /dev/null +++ b/docs/src/.vitepress/config.mts @@ -0,0 +1,100 @@ +import { defineConfig } from 'vitepress' +import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs' +import mathjax3 from "markdown-it-mathjax3"; + +// https://vitepress.dev/reference/site-config +export default defineConfig({ + base: '/YAXArrays.jl/', + title: "YAXArrays.jl", + description: "Yet another xarray-like Julia package", + lastUpdated: true, + cleanUrls: true, + + markdown: { + math: true, + config(md) { + md.use(tabsMarkdownPlugin), + md.use(mathjax3) + }, + theme: { + light: "github-light", + dark: "github-dark"} + }, + themeConfig: { + outline: 'deep', + // https://vitepress.dev/reference/default-theme-config + logo: { src: '/logo.png', width: 24, height: 24 }, + search: { + provider: 'local', + options: { + detailedView: true + } + }, + nav: [ + { text: 'Home', link: '/' }, + { text: 'Getting Started', link: '/getting_started' }, + { text: 'User Guide', + items: [ + { text: 'Creating YAXArrays and Datasets', link: '/UserGuide/creating' }, + { text: 'Indexing and subsetting', link: '/UserGuide/indexing_subsetting' }, + { text: 'Saving YAXArrays and Datasets', link: '/UserGuide/saving' }, + { text: 'Setting chunks size', link: '/UserGuide/setchuncks' }, + { text: 'Apply functions on YAXArrays', link: '/UserGuide/applyfunctions' }, + { text: 'Create Cube from function', link: '/UserGuide/create_cube_from_function' }, + { text: 'Distributed computing', link: '/UserGuide/distributed' }, + { text: 'Open NetCDF', link: '/UserGuide/openNetCDF' }, + { text: 'Open Zarr (Store)', link: '/UserGuide/openZarr' }, + ]}, + { text: 'Tutorials', + items: [ + { text: 'Overview', link: '/tutorials/tutorial' }, + { text: 'Plotting maps', link: '/tutorials/plottingmaps' }, + { text: 'Mean Seasonal Cycle', link: '/tutorials/mean_seasonal_cycle' }, + { text: 'ESDL study 3', link: '/tutorials/examples_from_esdl_study_3' }, + { text: 'ESDL study 4', link: '/tutorials/examples_from_esdl_study_4' }, + ]}, + { text: 'How do I?', + items: [ + { text: 'How do I ...', link: '/HowdoI/howdoi' }, + { text: 'Contribute to docs', link: '/HowdoI/contribute' } + ]}, + ], + + sidebar: [ + { text: 'Getting Started', link: '/getting_started' }, + { text: 'User Guide', + items: [ + { text: 'Creating YAXArrays and Datasets', link: '/UserGuide/creating' }, + { text: 'Indexing and subsetting', link: '/UserGuide/indexing_subsetting' }, + { text: 'Saving YAXArrays and Datasets', link: '/UserGuide/saving' }, + { text: 'Setting chunks size', link: '/UserGuide/setchuncks' }, + { text: 'Apply functions on YAXArrays', link: '/UserGuide/applyfunctions' }, + { text: 'Create Cube from function', link: '/UserGuide/create_cube_from_function' }, + { text: 'Distributed computing', link: '/UserGuide/distributed' }, + { text: 'Open NetCDF', link: '/UserGuide/openNetCDF' }, + { text: 'Open Zarr (Store)', link: '/UserGuide/openZarr' }, + ]}, + { text: 'Tutorials', + items: [ + { text: 'Overview', link: '/tutorials/tutorial' }, + { text: 'Plotting maps', link: '/tutorials/plottingmaps' }, + { text: 'Mean Seasonal Cycle', link: '/tutorials/mean_seasonal_cycle' }, + { text: 'ESDL study 3', link: '/tutorials/examples_from_esdl_study_3' }, + { text: 'ESDL study 4', link: '/tutorials/examples_from_esdl_study_4' }, + ]}, + { text: 'How do I?', + items: [ + { text: 'How do I ...', link: '/HowdoI/howdoi' }, + { text: 'Contribute to docs', link: '/HowdoI/contribute' } + ]}, + ], + + socialLinks: [ + { icon: 'github', link: 'https://github.com/JuliaDataCubes/YAXArrays.jl' } + ], + footer: { + message: 'Made with DocumenterVitepress.jl by Lazaro Alonso
', + copyright: `© Copyright ${new Date().getUTCFullYear()}. Released under the MIT License.` + } + } +}) \ No newline at end of file diff --git a/docs/src/.vitepress/theme/index.ts b/docs/src/.vitepress/theme/index.ts new file mode 100644 index 00000000..5ac1c911 --- /dev/null +++ b/docs/src/.vitepress/theme/index.ts @@ -0,0 +1,21 @@ +// .vitepress/theme/index.ts +import { h } from 'vue' +import type { Theme } from 'vitepress' +import DefaultTheme from 'vitepress/theme' +import AsideTrustees from '../../components/AsideTrustees.vue' + +import { enhanceAppWithTabs } from 'vitepress-plugin-tabs/client' +import './style.css' + +export default { + extends: DefaultTheme, + Layout() { + return h(DefaultTheme.Layout, null, { + // 'home-hero-info-after': () => h(HomeTrustees), + 'aside-ads-before': () => h(AsideTrustees), + }) + }, + enhanceApp({ app, router, siteData }) { + enhanceAppWithTabs(app) + } +} satisfies Theme \ No newline at end of file diff --git a/docs/src/.vitepress/theme/style.css b/docs/src/.vitepress/theme/style.css new file mode 100644 index 00000000..5fedcf78 --- /dev/null +++ b/docs/src/.vitepress/theme/style.css @@ -0,0 +1,173 @@ +@import url(https://fonts.googleapis.com/css?family=Space+Mono:regular,italic,700,700italic); +@import url(https://fonts.googleapis.com/css?family=Space+Grotesk:regular,italic,700,700italic); + +/** + * Customize default theme styling by overriding CSS variables: + * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css + */ + +/** + * Fonts + * -------------------------------------------------------------------------- + */ +:root { + /* Typography */ + --vp-font-family-base: "Space Grotesk", "Inter var experimental", "Inter var", + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, + Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + + /* Code Snippet font */ + --vp-font-family-mono: "Space Mono", Menlo, Monaco, Consolas, "Courier New", + monospace; +} + +/** + * Colors + For inspiration visit + * -------------------------------------------------------------------------- */ + /* https://github.com/vuejs/pinia/blob/v2/packages/docs/.vitepress/theme/styles/vars.css */ + +:root { + --julia-blue: #4063D8; + --julia-purple: #9558B2; + --julia-red: #CB3C33; + --julia-green: #389826; + --c-white-dark: #f8f8f8; + --c-black-darker: #0d121b; + --c-black: #111827; + --c-black-light: #161f32; + --c-black-lighter: #262a44; + --vp-c-brand: #646cff; + --vp-c-brand-light: #747bff; + --vp-c-brand-lighter: #9499ff; + --vp-c-brand-lightest: #bcc0ff; + --vp-c-brand-dark: #535bf2; + --vp-c-brand-darker: #454ce1; + --vp-c-brand-dimm: rgba(100, 108, 255, 0.08); +} + +/** + * Component: Button + * -------------------------------------------------------------------------- */ + +:root { + --vp-button-brand-border: var(--vp-c-brand-light); + --vp-button-brand-text: var(--vp-c-white); + --vp-button-brand-bg: var(--vp-c-brand); + --vp-button-brand-hover-border: var(--vp-c-brand-light); + --vp-button-brand-hover-text: var(--vp-c-white); + --vp-button-brand-hover-bg: var(--vp-c-brand-light); + --vp-button-brand-active-border: var(--vp-c-brand-light); + --vp-button-brand-active-text: var(--vp-c-white); + --vp-button-brand-active-bg: var(--vp-button-brand-bg); +} + +/** + * Component: Home + * -------------------------------------------------------------------------- */ + +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient( + 120deg, + #bd34fe 30%, + #41d1ff + ); + + --vp-home-hero-image-background-image: linear-gradient( + -45deg, + #bd34fe 50%, + #47caff 50% + ); + --vp-home-hero-image-filter: blur(40px); +} + +@media (min-width: 640px) { + :root { + --vp-home-hero-image-filter: blur(56px); + } +} + +@media (min-width: 960px) { + :root { + --vp-home-hero-image-filter: blur(72px); + } +} + +/** + * Component: Custom Block + * -------------------------------------------------------------------------- */ + +:root { + --vp-custom-block-tip-border: var(--vp-c-brand); + --vp-custom-block-tip-text: var(--vp-c-brand-darker); + --vp-custom-block-tip-bg: var(--vp-c-brand-dimm); +} + +.dark { + --vp-custom-block-tip-border: var(--vp-c-brand); + --vp-custom-block-tip-text: var(--vp-c-brand-lightest); + --vp-custom-block-tip-bg: var(--vp-c-brand-dimm); +} + +/** + * Component: Algolia + * -------------------------------------------------------------------------- */ + +.DocSearch { + --docsearch-primary-color: var(--vp-c-brand) !important; +} + + +/** + * Component: MathJax + * -------------------------------------------------------------------------- */ +mjx-container > svg { + display: block; + margin: auto; +} + +mjx-container { + padding: 0.5rem 0; +} + +mjx-container { + display: inline-block; + margin: auto 2px -2px; +} + +mjx-container > svg { + margin: auto; + display: inline-block; +} + +/** + * Colors links + * -------------------------------------------------------------------------- */ + + :root { + --vp-c-brand-1: #bd34fe; + --vp-c-brand-2: #bd34fe; + --vp-c-brand-3: #bd34fe; + --vp-c-sponsor: #bd34fe; + --vitest-c-sponsor-hover: #c13071; +} + +.dark { + --vp-c-bg: var(--c-black); + --vp-c-bg-soft: var(--c-black-light); + --vp-c-bg-soft-up: var(--c-black-lighter); + --vp-c-bg-mute: var(--c-black-light); + --vp-c-bg-soft-mute: var(--c-black-lighter); + --vp-c-bg-alt: #0d121b; + --vp-c-bg-elv: var(--vp-c-bg-soft); + --vp-c-bg-elv-mute: var(--vp-c-bg-soft-mute); + --vp-c-mute: var(--vp-c-bg-mute); + --vp-c-mute-dark: var(--c-black-lighter); + --vp-c-mute-darker: var(--c-black-darker); + --vp-c-brand-1: #0087d7; + --vp-c-brand-2: #0087d7; + --vp-c-brand-3: #0087d7; + --vp-c-sponsor: #ee4e95; + --vitest-c-sponsor-hover: #e51370; +} \ No newline at end of file diff --git a/docs/src/HowdoI/contribute.md b/docs/src/HowdoI/contribute.md new file mode 100644 index 00000000..2dc0613d --- /dev/null +++ b/docs/src/HowdoI/contribute.md @@ -0,0 +1,56 @@ + +# Contribute to Documentation + +Contributing with examples can be done by first creating a new file example [here](https://github.com/JuliaDataCubes/YAXArrays.jl/tree/master/docs/examples/UserGuide) + +::: info new file +- `your_new_file.md` at `docs/src/UserGuide/` + + +::: + +Once this is done you need to add a new entry [here](https://github.com/JuliaDataCubes/YAXArrays.jl/blob/master/docs/src/.vitepress/config.mts) at the appropriate level. + +::: info add entry to docs + +Your new entry should look like: +- \\{ text: 'Your title example', link: '/UserGuide/your_new_file.md' \\} + + +::: + +## Build docs locally + +If you want to take a look at the docs locally before doing a PR follow the next steps: + +Install the dependencies in your system, locate yourself at the `docs` level folder, then do + +```sh +npm i +``` + + +Then simply go to your `docs` env and activate it, i.e. + +```sh +docs> julia +julia> ] +pkg> activate . +``` + + +Next, run the scripts. Generate files and build docs by running: + +```sh +include("make.jl") +``` + + +Now go to your `terminal` in the same path `docs>` and run: + +```sh +npm run docs:dev +``` + + +This should ouput `http://localhost:5173/YAXArrays.jl/`, copy/paste this into your browser and you are all set. diff --git a/docs/src/HowdoI/howdoi.md b/docs/src/HowdoI/howdoi.md new file mode 100644 index 00000000..36f24844 --- /dev/null +++ b/docs/src/HowdoI/howdoi.md @@ -0,0 +1,257 @@ +# How do I do it? + +The purpose of this section is to do a collection of small +convinient pieces of code on how to do simple things. + + +## Extract the axes names from a Cube + +````@example howdoi +using YAXArrays +using DimensionalData +```` + +````@ansi howdoi +c = YAXArray(rand(10, 10, 5)) +caxes(c) # former way of doing it +```` + +::: warning + +To get the axes of a YAXArray use the `dims` function instead of the `caxes` function + +::: + +````@ansi howdoi +dims(c) +```` + +::: info + +Also, use __`DD.rebuild(ax, values)`__ instead of `axcopy(ax, values)` to copy an axes with the same name but different values. + +::: + +## Obtain values from axes and data from the cube + +There are two options to collect values from axes. In this examples the axis ranges from 1 to 10. + +These two examples bring the same result + +````@example howdoi +collect(getAxis("Dim_1", c).val) +collect(c.axes[1].val) +```` + +to collect data from a cube works exactly the same as doing it from an array + +````@ansi howdoi +c[:, :, 1] +```` + +## How do I concatenate cubes + +It is possible to concatenate several cubes that shared the same dimensions using the [`concatenatecubes`]@ref function. + +Let's create two dummy cubes +````@example howdoi +using YAXArrays +axlist = ( + Dim{:time}(range(1, 20, length=20)), + Dim{:lon}(range(1, 10, length=10)), + Dim{:lat}(range(1, 5, length=15)) + ) + +data1 = rand(20, 10, 15) +ds1 = YAXArray(axlist, data1) + +data2 = rand(20, 10, 15) +ds2 = YAXArray(axlist, data2) +nothing # hide +```` + +Now we can concatenate `ds1` and `ds2`: + +````@ansi howdoi +dsfinal = concatenatecubes([ds1, ds2], Dim{:Variables}(["var1", "var2"])) +```` + +## How do I subset a Cube? + +Let's start by creating a dummy cube. Define the time span of the cube + +````@example howdoi +using Dates +t = Date("2020-01-01"):Month(1):Date("2022-12-31") +```` + +create cube axes + +````@example howdoi +axes = (Dim{:Lon}(1:10), Dim{:Lat}(1:10), Dim{:Time}(t)) +```` + +assign values to a cube + +````@ansi howdoi +c = YAXArray(axes, reshape(1:3600, (10, 10, 36))) +```` + +Now we subset the cube by any dimension. + +Subset cube by years + +````@ansi howdoi +ctime = c[Time=Between(Date(2021,1,1), Date(2021,12,31))] +```` + +Subset cube by a specific date and date range + +````@ansi howdoi +ctime2 = c[Time=At(Date("2021-05-01"))] +ctime3 = c[Time=Date("2021-05-01") .. Date("2021-12-01")] +```` + +Subset cube by longitude and latitude + +````@ansi howdoi +clonlat = c[Lon=1 .. 5, Lat=5 .. 10] # check even numbers range, it is ommiting them +```` + +## How do I apply map algebra? + +Our next step is map algebra computations. This can be done effectively using the 'map' function. For example: + +Multiplying cubes with only spatio-temporal dimensions + +````@ansi howdoi +map((x, y) -> x * y, ds1, ds2) +```` + +Cubes with more than 3 dimensions + +````@ansi howdoi +map((x, y) -> x * y, dsfinal[Variables=At("var1")], dsfinal[Variables=At("var2")]) +```` + +To add some complexity, we will multiply each value for π and then divided for the sum of each time step. We will use the `ds1` cube for this purpose. + +````@ansi howdoi +mapslices(ds1, dims=("Lon", "Lat")) do xin + (xin * π) ./ maximum(skipmissing(xin)) +end +```` + +## How do I use the CubeTable function? + +The function "CubeTable" creates an iterable table and the result is a DataCube. It is therefore very handy for grouping data and computing statistics by class. It uses `OnlineStats.jl` to calculate statistics, and weighted statistics can be calculated as well. + +Here we will use the `ds1` Cube defined previously and we create a mask for data classification. + +Cube containing a mask with classes 1, 2 and 3. + +````@ansi howdoi +classes = YAXArray((getAxis("lon", dsfinal), getAxis("lat", dsfinal)), rand(1:3, 10, 15)) +```` + +````@example howdoi +using GLMakie +GLMakie.activate!() +# This is how our classification map looks like +fig, ax, obj = heatmap(classes; + colormap=Makie.Categorical(cgrad([:grey15, :orangered, :snow3]))) +cbar = Colorbar(fig[1,2], obj) +fig +```` + +Now we define the input cubes that will be considered for the iterable table + +````@example howdoi +t = CubeTable(values=ds1, classes=classes) +```` + +````@example howdoi +using DataFrames +using OnlineStats +## visualization of the CubeTable +c_tbl = DataFrame(t[1]) +first(c_tbl, 5) +```` + +In this line we calculate the `Mean` for each class + +````@ansi howdoi +fitcube = cubefittable(t, Mean, :values, by=(:classes)) +```` + +We can also use more than one criteria for grouping the values. In the next example, the mean is calculated for each class and timestep. + +````@ansi howdoi +fitcube = cubefittable(t, Mean, :values, by=(:classes, :time)) +```` + +## convertions types `DimArray` & `YAXArray` + +````@example howdoi +using YAXArrays, YAXArrayBase +using DimensionalData +```` + +### `DimArray` to `YAXArray` + +````@ansi howdoi +dim_arr = rand(X(1:5), Y(10.0:15.0), metadata = Dict{String, Any}()) +```` + +!!! warning "metadata" + Note the `metadata` argument. Needed by `yaxconvert`. + +````@ansi howdoi +yax_arr = yaxconvert(YAXArray, dim_arr) +```` + +And saving it: + +````@example howdoi +using Zarr, NetCDF +savecube(yax_arr, "yax_arr.nc", driver=:netcdf, overwrite=true); +nothing # hide +```` + +or as a `zarr` file + +````@example howdoi +savecube(yax_arr, "yax_arr.zarr", driver=:zarr); +nothing # hide +```` + +And going back to the DimArray type is also possible. + +### `YAXArray` into a `DimArray` + +````@ansi howdoi +dim_arr = yaxconvert(DimArray, yax_arr) +```` + +at the moment there is no support to save a DimArray directly into disk as a `NetCDF` or a `Zarr` file. + + +## How do I assing variable names to `YAXArrays` in a `Dataset` + +### One variable name + +````@ansi howdoi +ds = YAXArrays.Dataset(; (:a => YAXArray(rand(10)),)...) +```` + +### Multiple variable names + +````@example howdoi +keylist = (:a, :b, :c) +varlist = (YAXArray(rand(10)), YAXArray(rand(10,5)), YAXArray(rand(2,5))) +nothing # hide +```` + +````@ansi howdoi +ds = YAXArrays.Dataset(; (keylist .=> varlist)...) +```` diff --git a/docs/src/UserGuide/applyfunctions.md b/docs/src/UserGuide/applyfunctions.md new file mode 100644 index 00000000..85d5d6df --- /dev/null +++ b/docs/src/UserGuide/applyfunctions.md @@ -0,0 +1,75 @@ +# How to apply functions on YAXArrays + +To apply user defined functions on a YAXArray data type we can use the [`map`](@ref) function, +[`mapslices`](@ref) function or the [`mapCube`](@ref) function. Which of these functions should +be used depends on the layout of the data that the user defined function should be applied on. + +## Apply a function on every element of a datacube + +The `map` function can be used to apply a function on every entry of a YAXArray without taking +the dimensions into account. This will lazily register the mapped function which is applied when +the YAXArray is either accessed or when more involved computations are made. + +If we set up a dummy data cube which has all numbers between 1 and 10000. + +````@example applyF +using YAXArrays +using DimensionalData +axes = (Dim{:Lon}(1:10), Dim{:Lat}(1:10), Dim{:Time}(1:100)) +original = YAXArray(axes, reshape(1:10000, (10,10,100))) +nothing # hide +```` + +with one at the first position: + +````@ansi applyF +original[1,:,1] +```` +now we can substract `1` from all elements of this cube + +````@ansi applyF +substracted = map(x-> x-1, original) +```` + +`substracted` is a cube of the same size as `original`, and the applied function is registered, +so that it is applied as soon as the elements of `substracted` are either accessed or further used +in other computations. + +````@ansi applyF +substracted[1,:,1] +```` + +## Apply a function along dimensions of a single cube + +If an function should work along a certain dimension of the data you can use the `mapslices` function +to easily apply this function. This doesn't give you the flexibility of the `mapCube` function but it +is easier to use for simple functions. + +If we set up a dummy data cube which has all numbers between 1 and 10000. + +````@ansi applyF +axes = (Dim{:Lon}(1:10), Dim{:Lat}(1:10), Dim{:Time}(1:100)) +original = YAXArray(axes, reshape(1:10000, (10,10,100))) +```` + +and then we would like to compute the sum over the Time dimension: + +````@ansi applyF +timesum = mapslices(sum, original, dims="Time") +```` + +this reduces over the time dimension and gives us the following values + +````@ansi applyF +timesum[:,:] +```` + +You can also apply a function along multiple dimensions of the same data cube. + +````@ansi applyF +lonlatsum = mapslices(sum, original, dims=("Lon", "Lat")) +```` + +## Multiple input cubes to a function + +TODO \ No newline at end of file diff --git a/docs/src/UserGuide/create_cube_from_function.md b/docs/src/UserGuide/create_cube_from_function.md new file mode 100644 index 00000000..e4b5d535 --- /dev/null +++ b/docs/src/UserGuide/create_cube_from_function.md @@ -0,0 +1,81 @@ +# Create cube / YAXArray from function + +````@example create_cube +using YAXArrays, Zarr +using Dates +```` + +## Define function in space and time + +````@example create_cube +f(lo, la, t) = (lo + la + Dates.dayofyear(t)) +```` + +Wrap function for mapCube output + +````@example create_cube +function g(xout,lo,la,t) + xout .= f.(lo,la,t) +end +```` + +Note the applied `.` after `f`, this is because we will slice/broadcasted across time. + +## Create Cube's Axes + +We wrap the dimensions of every axis into a YAXArray to use them in the mapCube function. + +````@ansi create_cube +lon = YAXArray(Dim{:lon}(range(1, 15))) +lat = YAXArray(Dim{:lat}(range(1, 10))) +```` + +And a time axis + +````@ansi create_cube +tspan = Date("2022-01-01"):Day(1):Date("2022-01-30") +time = YAXArray(Dim{:time}( tspan)) +```` + +## Generate Cube + +The following generates a new `cube` using `mapCube` and saving the output directly to disk. + +````@example create_cube +gen_cube = mapCube(g, (lon, lat, time); + indims = (InDims(), InDims(), InDims("time")), + outdims = OutDims("time", overwrite=true, + path = "my_gen_cube.zarr", backend=:zarr, outtype=Float32), + ## max_cache=1e9 + ) +nothing # hide +```` +!!! warning "time axis is first" + Note that currently the `time` axis in the output cube goes first. + +Check that it is working + +````@ansi create_cube +gen_cube.data[1,:,:] +```` + +## Change output order + +The following generates a new `cube` using `mapCube` and saving the output directly to disk. + +````@example create_cube +gen_cube = mapCube(g, (lon, lat, time); + indims = (InDims("lon"), InDims(), InDims()), + outdims = OutDims("lon", overwrite=true, + path = "my_gen_cube.zarr", backend=:zarr, outtype=Float32), + ## max_cache=1e9 + ) +nothing # hide +```` + +!!! info "slicing dim" + Note that now the broadcasted dimension is `lon`. + +````@ansi create_cube +gen_cube.data[:, :, 1] +```` \ No newline at end of file diff --git a/docs/src/UserGuide/creating.md b/docs/src/UserGuide/creating.md new file mode 100644 index 00000000..182e5691 --- /dev/null +++ b/docs/src/UserGuide/creating.md @@ -0,0 +1,183 @@ +# Creating YAXArrays and Datasets + +Here, we use `YAXArray` when the variables share dimensions and `Dataset` otherwise. + +## Creating a YAXArray + +````@example creating +using YAXArrays +using DimensionalData: DimensionalData as DD +using DimensionalData +```` + +````@ansi creating +a = YAXArray(rand(10, 20, 5)) +```` + +if no names are defined then default ones will be used, i.e. `Dim_1`, `Dim_2`. + +Get data from each Dimension with + +````@example creating +a.Dim_1 +```` + +or with + +````@example creating +getproperty(a, :Dim_1) +```` + +or even better with the `DD` `lookup` function + +````@example creating +lookup(a, :Dim_1) +```` + +## Creating a YAXArray with named axis + +The two most used axis are `RangeAxis` and `CategoricalAxis`. Here, we use a combination of them to create a `time`, `lon` and `lat` axis and a Categorical Axis for two variables. + +### Axis definitions + +````@ansi creating +using Dates +axlist = ( + Dim{:time}(Date("2022-01-01"):Day(1):Date("2022-01-30")), + Dim{:lon}(range(1, 10, length=10)), + Dim{:lat}(range(1, 5, length=15)), + Dim{:Variable}(["var1", "var2"]) + ) +```` + +And the corresponding data + +````@example creating +data = rand(30, 10, 15, 2); +nothing # hide +```` + +then, the `YAXArray` is + +````@ansi creating +ds = YAXArray(axlist, data) +```` + +### Select variables + +````@ansi creating +ds[Variable = At("var1"), lon = DD.Between(1,2.1)] +```` + +!!! info + Please note that selecting elements in YAXArrays is done via the `DimensionalData.jl` syntax. + For more information checkout the [docs](https://rafaqz.github.io/DimensionalData.jl/dev/). + + +````@ansi creating +subset = ds[ + time = DD.Between( Date("2022-01-01"), Date("2022-01-10")), + lon=DD.Between(1,2), + Variable = At("var2") + ] +```` + +### Properties / Attributes + +You might also want to add additional properties to your YAXArray. This can be done via a Dictionary, namely + +````@example creating +props = Dict( + "time" => "days", + "lon" => "longitude", + "lat" => "latitude", + "var1" => "first variable", + "var2" => "second variable", +); +nothing # hide +```` + +Then the `yaxarray` with properties is assemble with + +````@ansi creating +ds = YAXArray(axlist, data, props) +```` + +Access these properties with + +````@example creating +ds.properties +```` + +Note that this properties are shared for both variables `var1` and `var2`. +Namely, this are global properties for your `YAXArray`. +However, in most cases you will want to pass properties for each variable, here we will do this via Datasets. + +## Creating a Dataset + +Let's define first some range axis + +````@ansi creating +axs = ( + Dim{:lon}(range(0,1, length=10)), + Dim{:lat}(range(0,1, length=5)), +) +```` + +And two toy random `YAXArrays` to assemble our dataset + +````@ansi creating +t2m = YAXArray(axs, rand(10,5), Dict("units" => "K", "reference" => "your references")) +prec = YAXArray(axs, rand(10,5), Dict("units" => "mm", "reference" => "your references")) +```` + +Then the `Dataset` is assembled as + +````@ansi creating +ds = Dataset(t2m=t2m, prec= prec, num = YAXArray(rand(10)), + properties = Dict("space"=>"lon/lat", "reference" => "your global references")) +```` + +::: tip + +Note that the YAXArrays used not necessarily shared the same dimensions. +Hence, using a Dataset is more versatile than a plain YAXArray. + +::: + +## Selected Variables in a Data Cube + +Being able to collect variables that share dimensions into a data cube is possible with + +````@ansi creating +c = Cube(ds[["t2m", "prec"]]) +```` + +or simply the one that does not share all dimensions + +````@ansi creating +Cube(ds[["num"]]) +```` + +### Variable properties + +Access to variables properties is done via + +````@example creating +Cube(ds[["t2m"]]).properties +```` + +and + +````@example creating +Cube(ds[["prec"]]).properties +```` + +Note also that the global properties for the Dataset are accessed with + +````@example creating +ds.properties +```` + +Saving and different chunking modes are discussed in [here](). + diff --git a/docs/src/UserGuide/distributed.md b/docs/src/UserGuide/distributed.md new file mode 100644 index 00000000..9000fb0f --- /dev/null +++ b/docs/src/UserGuide/distributed.md @@ -0,0 +1,67 @@ +# Distributed Computing + +## How to calculate a time mean + +````@example distributed +using YAXArrays, Statistics, Zarr +using DimensionalData +using Dates +axlist = ( + Dim{:time}(Date("2022-01-01"):Day(1):Date("2022-01-10")), + Dim{:lon}(range(1, 10, length=10)), + Dim{:lat}(range(1, 5, length=15)), + Dim{:Variable}(["var1", "var2"]) + ) +# # And the corresponding data +data = rand(10, 10, 15, 2) +nothing # hide +```` + +````@ansi distributed +ds = YAXArray(axlist, data) +```` + +````@example distributed +c = ds[Variable = At("var1")] +mapslices(mean ∘ skipmissing, c, dims="Time") +```` + +## Distributed calculations + +It is possible to distribute the calculations over multiple process. The following code +does a time mean over all grid points using multiple CPU over a local machine. + + +````julia +using Distributed +addprocs(2) +@everywhere begin + using NetCDF + using YAXArrays + using Statistics + using Zarr +end +@everywhere function mymean(output, pixel) + @show "doing a mean" + output[:] .= mean(pixel) +end +indims = InDims("time") +outdims = OutDims() +resultcube = mapCube(mymean, c, indims=indims, outdims=outdims) +```` + + +In the last example, `mapCube` was used to map the `mymean` function. `mapslices` is a convenient function that can replace `mapCube`, where you can omit defining an extra function with the output argument as an input (e.g. `mymean`). It is possible to simply use `mapslice` + +````@ansi distributed +resultcube = mapslices(mean ∘ skipmissing, c, dims="time") +```` + +It is also possible to distribute easily the workload on a cluster, with little modification to the code. To do so, we use the `ClusterManagers` package. + +````julia +using Distributed +using ClusterManagers +addprocs(SlurmManager(10)) +```` + diff --git a/docs/src/UserGuide/indexing_subsetting.md b/docs/src/UserGuide/indexing_subsetting.md new file mode 100644 index 00000000..1651017e --- /dev/null +++ b/docs/src/UserGuide/indexing_subsetting.md @@ -0,0 +1,90 @@ +# Indexing, subsetting and selectors + +All these operations are done via [`DimensionalData.jl`](https://rafaqz.github.io/DimensionalData.jl/dev/). + +````@example indexing +using YAXArrays, Dates +```` + +## Define a toy cube + +````@ansi indexing +t = Date("2020-01-01"):Month(1):Date("2022-12-31") +axes = (Dim{:lon}(-9:10), Dim{:lat}(-5:15), Dim{:time}(t)) +c = YAXArray(axes, reshape(1:20*21*36, (20, 21, 36))) +```` + +A very convinient selector is `lookup`, getting for example the values for `lon` and `time`. + +## lookup + +````@example indexing +lon = lookup(c, :lon) +```` + +````@example indexing +tempo = lookup(c, :time) +```` + + +## Selectors + +### `At` value + +````@ansi indexing +c[time = At(DateTime("2021-05-01"))] +```` + +### `At` vector of values + +````@ansi indexing +c[time = At([DateTime("2021-05-01"), DateTime("2021-06-01")])] +```` + +similarly for any of the spatial dimensions: + +````@ansi indexing +c[lon = At([-9,-5])] +```` + +### `At` values with tolerance (`atol`, `rtol`) + +````@ansi indexing +c[lon = At([-10, 11]; atol = 1)] +```` +## Subsetting + +This is also done with selectors, see the following examples + +### Between + +Altought a `Between(a,b)` function is available in `DimensionalData`, is recommended to use instead the `a .. b` notation: + +````@ansi indexing +c[lon = -9 .. -7] # close interval, all points included. +```` + +More selectors from DimensionalData are available, such as `Touches`, `Near`, `Where` and `Contains`. + + +### Open/Close Intervals + +````@example indexing +using IntervalSets +```` + +````@ansi indexing +c[lon = OpenInterval(-9, -7)] +```` + +````@ansi indexing +c[lon = ClosedInterval(-9, -7)] +```` +````@ansi indexing +c[lon =Interval{:open,:closed}(-9,-7)] +```` +````@ansi indexing +c[lon =Interval{:closed,:open}(-9,-7)] +```` + +See tutorials for use cases. \ No newline at end of file diff --git a/docs/src/UserGuide/openNetCDF.md b/docs/src/UserGuide/openNetCDF.md new file mode 100644 index 00000000..6c25bde3 --- /dev/null +++ b/docs/src/UserGuide/openNetCDF.md @@ -0,0 +1,47 @@ +# Opening NetCDF files + +In this example we are going to use a `NetCDF` file. To open a single data file we first need to load the appropriate backend package via `using NetCDF`. + +## File with one variable + +````@example open_nc +using YAXArrays, NetCDF +using DiskArrays +using Downloads +url = "https://www.unidata.ucar.edu/software/netcdf/examples/tos_O1_2001-2002.nc" +filename = Downloads.download(url, "tos_O1_2001-2002.nc") # you pick your own path +nothing # hide +```` + +````@ansi open_nc +c = Cube(filename) +```` + +## File with multiple variables, mixed dimensions + +When the dataset contains variables with different dimensions you should use `open_dataset` as in + +````@example open_nc +path2file = "https://www.unidata.ucar.edu/software/netcdf/examples/sresa1b_ncar_ccsm3-example.nc" +filename = Downloads.download(path2file, "sresa1b_ncar_ccsm3-example.nc") +c = open_dataset(filename) +nothing # hide +```` + +````@ansi open_nc +c +```` + +Afterwards, selecting a variable as usual works, i.e. + +````@ansi open_nc +c["ua"] +```` + +or + +````@ansi open_nc +c["tas"] +```` + +Note that their output is a YAXArray. \ No newline at end of file diff --git a/docs/src/UserGuide/openZarr.md b/docs/src/UserGuide/openZarr.md new file mode 100644 index 00000000..f1ffc743 --- /dev/null +++ b/docs/src/UserGuide/openZarr.md @@ -0,0 +1,21 @@ +# Opening a Zarr directory from a store + +````@example open_zarr +using Zarr, YAXArrays +store ="gs://cmip6/CMIP6/ScenarioMIP/DKRZ/MPI-ESM1-2-HR/ssp585/r1i1p1f1/3hr/tas/gn/v20190710/" +```` + +Open and select the `tas` variable, + +````@ansi open_zarr +g = open_dataset(zopen(store, consolidated=true)) +```` + +get variable + +````@ansi open_zarr +c = g["tas"] +```` + +After this operate on it as usual. + diff --git a/docs/src/UserGuide/saving.md b/docs/src/UserGuide/saving.md new file mode 100644 index 00000000..e48e0d11 --- /dev/null +++ b/docs/src/UserGuide/saving.md @@ -0,0 +1,107 @@ +# Saving YAXArrays and Datasets + +Is possible to save datasets and `YAXArray` directly to `zarr` files. + +## Saving a YAXArray to Zarr + +One can save any `YAXArray` using the `savecube` function. +Simply add a path as an argument and the cube will be saved. + +````@example saveYAX +using YAXArrays, Zarr +a = YAXArray(rand(10,20)) +savecube(a, "our_yax.zarr", driver=:zarr) +nothing # hide +```` + + +## Saving a YAXArray to NetCDF + +Saving to NetCDF works exactly the same way: + +````@example saveYAX +using YAXArrays, Zarr, NetCDF +a = YAXArray(rand(10,20)) +savecube(a, "our_yax.nc", driver=:netcdf) +nothing # hide +```` + +## Saving a Dataset + +Saving Datasets can be done using the `savedataset` function. + +````@example saveDataset +using YAXArrays, Zarr +ds = Dataset(x = YAXArray(rand(10,20)), y = YAXArray(rand(10))) +f = "our_dataset.zarr" +savedataset(ds, path=f, driver=:zarr) +nothing # hide +```` + +## Overwriting a Dataset +If a path already exists, an error will be thrown. Set `overwrite=true` to delete the existing dataset + +````@example saveDataset +savedataset(ds, path=f, driver=:zarr, overwrite=true) +nothing # hide +```` + +::: danger + +Again, setting `overwrite` will delete all your previous saved data. + +::: + +Look at the doc string for more information + +````@docs +savedataset +```` + +## Appending to a Dataset + +New variables can be added to an existing dataset using the `append=true` keyword. + +````@example saveDataset +ds2 = Dataset(z = YAXArray(rand(10,20,5))) +savedataset(ds2, path=f, backend=:zarr, append=true) +nothing # hide +```` + +````@ansi saveDataset +open_dataset(f, driver=:zarr) +```` + +## Datacube Skeleton without the actual data +Sometimes one merely wants to create a datacube "Skeleton" on disk and gradually fill it with data. Here we make use of `FillArrays` to create a `YAXArray` and write only the axis data and array metadata to disk, while no actual array data is copied: + +````@example saveDataset +using YAXArrays, Zarr, FillArrays +```` + +create the `Zeros` array + +````@ansi saveDataset +a = YAXArray(Zeros(Union{Missing, Int32}, 10, 20)) +```` + +and save them as + +````@example saveDataset +r = savecube(a, "skeleton.zarr", driver=:zarr, skeleton=true) +nothing # hide +```` + +and check that all the values are `missing` + +````@example saveDataset +all(ismissing,r[:,:]) +```` + +If using `FillArrays` is not possible, using the `zeros` function works as well, though it does allocate the array in memory. + +::: info + +The `skeleton` argument is also available for `savedataset`. + +::: diff --git a/docs/src/UserGuide/setchuncks.md b/docs/src/UserGuide/setchuncks.md new file mode 100644 index 00000000..a02068c4 --- /dev/null +++ b/docs/src/UserGuide/setchuncks.md @@ -0,0 +1,90 @@ +# Set chunks + +> [!IMPORTANT] +> Thinking about chunking is important when it comes to analyzing your data, because in most situations this will not fit into memory, hence having the fastest read access to it is crucial for your workflows. For example, for geo-spatial data do you want fast access on time or space, or... think about it. + +To determine the chunk size of the array representation on disk, +call the `setchunks` function prior to saving. + +## Chunking YAXArrays + +````@example chunks +using YAXArrays, Zarr +a = YAXArray(rand(10,20)) +a_chunked = setchunks(a, (5,10)) +a_chunked.chunks +```` +And the saved file is also splitted into Chunks. + +````@example chunks +f = tempname() +savecube(a_chunked, f, backend=:zarr) +Cube(f).chunks +```` + +Alternatively chunk sizes can be given by dimension name, so the following results in the same chunks: + +````@example chunks +a_chunked = setchunks(a, (Dim_2=10, Dim_1=5)) +a_chunked.chunks +```` + +## Chunking Datasets +Setchunks can also be applied to a `Dataset`. + +### Set Chunks by Axis + +Set chunk size for each axis occuring in a `Dataset`. This will be applied to all variables in the dataset: + +````@example chunks +using YAXArrays, Zarr +ds = Dataset(x = YAXArray(rand(10,20)), y = YAXArray(rand(10)), z = YAXArray(rand(10,20,5))) +dschunked = setchunks(ds, Dict("Dim_1"=>5, "Dim_2"=>10, "Dim_3"=>2)) +Cube(dschunked).chunks +```` + +Saving... + +````@example chunks +f = tempname() +savedataset(dschunked, path=f, driver=:zarr) +```` + +### Set chunking by Variable + +The following will set the chunk size for each Variable separately +and results in exactly the same chunking as the example above + +````@example chunks +using YAXArrays, Zarr +ds = Dataset(x = YAXArray(rand(10,20)), y = YAXArray(rand(10)), z = YAXArray(rand(10,20,5))) +dschunked = setchunks(ds,(x = (5,10), y = Dict("Dim_1"=>5), z = (Dim_1 = 5, Dim_2 = 10, Dim_3 = 2))) +Cube(dschunked).chunks +```` + +saving... + +````@example chunks +f = tempname() +savedataset(dschunked, path=f, driver=:zarr) +```` + +### Set chunking for all variables + +The following code snippet only works when all member variables of the dataset have the same shape and sets the output chunks for all arrays. + +````@example chunks +using YAXArrays, Zarr +ds = Dataset(x = YAXArray(rand(10,20)), y = YAXArray(rand(10,20)), z = YAXArray(rand(10,20))) +dschunked = setchunks(ds,(5,10)) +Cube(dschunked).chunks +```` + +saving... + +````@example chunks +f = tempname() +savedataset(dschunked, path=f, driver=:zarr) +```` + +Suggestions on how to improve or add to these examples is welcome. diff --git a/docs/src/assets/view-grid-plus-outline.svg b/docs/src/assets/view-grid-plus-outline.svg deleted file mode 100644 index 64c0ac39..00000000 --- a/docs/src/assets/view-grid-plus-outline.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/src/components/AsideTrustees.vue b/docs/src/components/AsideTrustees.vue new file mode 100644 index 00000000..9153a6eb --- /dev/null +++ b/docs/src/components/AsideTrustees.vue @@ -0,0 +1,132 @@ + + + + diff --git a/docs/src/getting_started.md b/docs/src/getting_started.md new file mode 100644 index 00000000..0acfdb66 --- /dev/null +++ b/docs/src/getting_started.md @@ -0,0 +1,102 @@ +# Getting Started + +## Installation + +Install [Julia v1.10 or above](https://julialang.org/downloads/). YAXArrays.jl is available through the Julia package manager. You can enter it by pressing `]` in the REPL and then typing + +```julia +pkg> add YAXArrays +``` + +Alternatively, you can also do + +```julia +import Pkg; Pkg.add("YAXArrays") +``` + +:::tip + +The Julia Compiler is always improving. As such, we recommend using the latest stable +version of Julia. + +::: + + +## Quickstart + +```@example quickstart +using YAXArrays +``` + +You may check the installed version with: + +```julia +pkg> st YAXArrays +``` + +Let's assemble a `YAXArray` with 4 dimensions i.e. time, x,y and a variable dimension with two variables. + +```@example quickstart +using YAXArrays, DimensionalData +axlist = ( + Dim{:time}(range(1, 20, length=20)), + X(range(1, 10, length=10)), + Y(range(1, 5, length=15)), + Dim{:Variable}(["var1", "var2"])) +# and the corresponding data. +data = rand(20, 10, 15, 2); +nothing # hide +``` + +::: info + +With `YAXArrays.jl 0.5` we switched the underlying data type to be a subtype of the DimensionalData.jl types. Therefore the indexing with named dimensions changed to the DimensionalData syntax. See the [`DimensionalData.jl docs`](https://rafaqz.github.io/DimensionalData.jl/stable/). + +::: + +You can also add additional properties via a Dictionary, namely + +```@example quickstart +props = Dict( + "time" => "days", + "x" => "lon", + "y" => "lat", + "var1" => "one of your variables", + "var2" => "your second variable", +); +nothing # hide +``` + +And our first YAXArray is built with: + +```@ansi quickstart +ds = YAXArray(axlist, data, props) +``` + +## Getting data from a YAXArray + +For axis can be via `.` + +```@example quickstart +ds.X +``` + +or better yet via `lookup` + +```@example quickstart +lookup(ds, :X) +``` + +note that also the `.data` field can be use + +```@example quickstart +lookup(ds, :X).data +``` + +The data for one variables, i.e. `var1` can be accessed via: + +```@ansi quickstart +ds[Variable=At("var1")] +``` + +and again, you can use the `.data` field to actually get the data. \ No newline at end of file diff --git a/docs/src/index.md b/docs/src/index.md index 55d0a3db..9c52c07f 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,48 +1,32 @@ -# YAXArrays.jl - -*Yet another xarray-like Julia package* - -A package for operating on out-of-core labeled arrays, based on stores like NetCDF, Zarr or GDAL. - -!!! info - - Open datasets from a variety of sources (NetCDF, Zarr, ArchGDAL) - - Interoperability with other named axis packages through YAXArrayBase - - Efficient `mapslices(x)` operations on huge multiple arrays, optimized for high-latency data access (object storage, compressed datasets) - -## Installation - -In the Julia REPL type: - -```julia -using Pkg -Pkg.add("YAXArrays") -``` - -or - -```julia -] add YAXArrays -``` - -The `]` character starts the Julia [package manager](https://docs.julialang.org/en/v1/stdlib/Pkg/). Hit backspace key to return to Julia prompt. - -You may check the installed version with: - -```julia -] st YAXArrays -``` - -Start using the package: - -````julia -using YAXArrays -```` - -The [YAXArray tutorial](@ref) provides a tutorial explaining how to get started using YAXArrays. - -## Quick start - -````julia -using YAXArrays -yax = YAXArray(rand(10,20,30)) -```` \ No newline at end of file +```@raw html +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home + +hero: + name: "YAXArrays.jl" + text: "Yet another xarray-like Julia package" + tagline: A package for operating on out-of-core labeled arrays, based on stores like NetCDF, Zarr or GDAL + image: + src: /logo.png + alt: VitePress + actions: + - theme: brand + text: Getting Started + link: /api-examples + - theme: alt + text: API reference + link: /api-examples + - theme: alt + text: View on Github + link: /api-examples + +features: + - title: Data + details: Open datasets from a variety of sources (NetCDF, Zarr, ArchGDAL). + - title: Interoperability + details: Interoperability with other named axis packages through YAXArrayBase. + - title: Efficiency + details: Efficient `mapslices(x)` operations on huge multiple arrays, optimized for high-latency data access (object storage, compressed datasets). +--- +``` \ No newline at end of file diff --git a/docs/src/javascripts/mathjax.js b/docs/src/javascripts/mathjax.js deleted file mode 100644 index a80ddbff..00000000 --- a/docs/src/javascripts/mathjax.js +++ /dev/null @@ -1,16 +0,0 @@ -window.MathJax = { - tex: { - inlineMath: [["\\(", "\\)"]], - displayMath: [["\\[", "\\]"]], - processEscapes: true, - processEnvironments: true - }, - options: { - ignoreHtmlClass: ".*|", - processHtmlClass: "arithmatex" - } -}; - -document$.subscribe(() => { - MathJax.typesetPromise() -}) \ No newline at end of file diff --git a/docs/src/assets/logo.png b/docs/src/public/logo.png similarity index 100% rename from docs/src/assets/logo.png rename to docs/src/public/logo.png diff --git a/docs/src/assets/logo.svg b/docs/src/public/logo.svg similarity index 100% rename from docs/src/assets/logo.svg rename to docs/src/public/logo.svg diff --git a/docs/src/stylesheets/custom.css b/docs/src/stylesheets/custom.css deleted file mode 100644 index b9d91cf8..00000000 --- a/docs/src/stylesheets/custom.css +++ /dev/null @@ -1,157 +0,0 @@ -/* Fix /page#foo going to the top of the viewport and being hidden by the navbar */ -html { - scroll-padding-top: 50px; - } - - /* Fit the Twitter handle alongside the GitHub one in the top right. */ - - div.md-header__source { - width: revert; - max-width: revert; - } - - a.md-source { - display: inline-block; - } - - .md-source__repository { - max-width: 100%; - } - - /* Emphasise sections of nav on left hand side */ - - nav.md-nav { - padding-left: 5px; - } - - nav.md-nav--secondary { - border-left: revert !important; - } - - .md-nav__title { - font-size: 0.9rem; - } - - .md-nav__item--section > .md-nav__link { - font-size: 0.9rem; - } - - /* Indent autogenerated documentation */ - - div.doc-contents { - padding-left: 25px; - border-left: 4px solid rgba(230, 230, 230); - } - - /* Increase visibility of splitters "---" */ - - [data-md-color-scheme="default"] .md-typeset hr { - border-bottom-color: rgb(0, 0, 0); - border-bottom-width: 1pt; - } - - [data-md-color-scheme="slate"] .md-typeset hr { - border-bottom-color: rgb(230, 230, 230); - } - - /* More space at the bottom of the page */ - - .md-main__inner { - margin-bottom: 1.5rem; - } - - /* Remove prev/next footer buttons */ - - .md-footer__inner { - display: none; - } - - /* Bugfix: remove the superfluous parts generated when doing: - - ??? Blah - - ::: library.something - */ - - .md-typeset details .mkdocstrings > h4 { - display: none; - } - - .md-typeset details .mkdocstrings > h5 { - display: none; - } - - /* Change default colours for
tags */ - - [data-md-color-scheme="default"] { - --md-typeset-a-color: rgb(0, 150, 255) !important; - } - [data-md-color-scheme="slate"] { - --md-typeset-a-color: rgb(0, 150, 255) !important; - } - - /* Highlight functions, classes etc. type signatures. Really helps to make clear where - one item ends and another begins. */ - - [data-md-color-scheme="default"] { - --doc-heading-color: #DDD; - --doc-heading-border-color: #CCC; - --doc-heading-color-alt: #F0F0F0; - } - [data-md-color-scheme="slate"] { - --doc-heading-color: rgb(25,25,33); - --doc-heading-border-color: rgb(25,25,33); - --doc-heading-color-alt: rgb(33,33,44); - --md-code-bg-color: rgb(38,38,50); - } - - h4.doc-heading { - /* NOT var(--md-code-bg-color) as that's not visually distinct from other code blocks.*/ - background-color: var(--doc-heading-color); - border: solid var(--doc-heading-border-color); - border-width: 1.5pt; - border-radius: 2pt; - padding: 0pt 5pt 2pt 5pt; - } - h5.doc-heading, h6.heading { - background-color: var(--doc-heading-color-alt); - border-radius: 2pt; - padding: 0pt 5pt 2pt 5pt; - } - - /* From Pretty Pandas Dataframes */ -/* Supports mkdocs-material color variables */ -.data-frame { - border: 0; - font-size: smaller; -} -.data-frame tr { - border: none; - background: var(--md-code-bg-color, #ffffff); -} -.data-frame tr:nth-child(even) { - background: var(--md-default-bg-color, #f5f5f5); -} -.data-frame tr:hover { - background-color: var(--md-footer-bg-color--dark, #e1f5fe); -} - -.data-frame thead th { - background: var(--md-default-bg-color, #ffffff); - border-bottom: 1px solid #aaa; - font-weight: bold; -} -.data-frame th { - border: none; - padding-left: 10px; - padding-right: 10px; -} - -.data-frame td{ - /* background: #fff; */ - border: none; - text-align: right; - min-width:5em; - padding-left: 10px; - padding-right: 10px; -} \ No newline at end of file diff --git a/docs/examples/UserGuide/examples_from_esdl_study_1.jl b/docs/src/tutorials/examples_from_esdl_study_1.jl similarity index 100% rename from docs/examples/UserGuide/examples_from_esdl_study_1.jl rename to docs/src/tutorials/examples_from_esdl_study_1.jl diff --git a/docs/examples/UserGuide/examples_from_esdl_study_2.jl b/docs/src/tutorials/examples_from_esdl_study_2.jl similarity index 100% rename from docs/examples/UserGuide/examples_from_esdl_study_2.jl rename to docs/src/tutorials/examples_from_esdl_study_2.jl diff --git a/docs/examples/UserGuide/examples_from_esdl_study_3.jl b/docs/src/tutorials/examples_from_esdl_study_3.jl similarity index 53% rename from docs/examples/UserGuide/examples_from_esdl_study_3.jl rename to docs/src/tutorials/examples_from_esdl_study_3.jl index 4ab34df9..6f5e56ea 100644 --- a/docs/examples/UserGuide/examples_from_esdl_study_3.jl +++ b/docs/src/tutorials/examples_from_esdl_study_3.jl @@ -1,24 +1,24 @@ -# # Examples from the ESDL paper -# ## Earth Syst. Dynam., 11, 201–234, 2020 [doi](https://doi.org/10.5194/esd-11-201-2020) +# Examples from the ESDL paper +## Earth Syst. Dynam., 11, 201–234, 2020 [doi](https://doi.org/10.5194/esd-11-201-2020) -# **NOTE:** This section is based on the case studies from the paper "Earth system data cubes unravel global multivariate dynamics" by Mahecha, Gans et al. (2019), available [here](https://github.com/esa-esdl/ESDLPaperCode.jl). -# - We have slightly adjusted the scripts. A few differences are that these new scripts are updated to Julia 1.9, and the YAXArrays.jl package is used. -# - The dataset has been updated but it has less available variables. Therefore the results might differ. -# - The calculations are performed with a very coarse spatial (2.5°) and temporal resolution (monthly). -# - These are examples for illustrative purposes of the packages and do not intend any deeper scientific interpretation. For scientific analysis use the higher spatio-temporal resolution datasets. +**NOTE:** This section is based on the case studies from the paper "Earth system data cubes unravel global multivariate dynamics" by Mahecha, Gans et al. (2019), available [here](https://github.com/esa-esdl/ESDLPaperCode.jl). +- We have slightly adjusted the scripts. A few differences are that these new scripts are updated to Julia 1.9, and the YAXArrays.jl package is used. +- The dataset has been updated but it has less available variables. Therefore the results might differ. +- The calculations are performed with a very coarse spatial (2.5°) and temporal resolution (monthly). +- These are examples for illustrative purposes of the packages and do not intend any deeper scientific interpretation. For scientific analysis use the higher spatio-temporal resolution datasets. -# ## Case study 3: Model-parameter estimation in the ESDL -# ### Example of the temperature sensitivity of ecosystem respiration +## Case study 3: Model-parameter estimation in the ESDL +### Example of the temperature sensitivity of ecosystem respiration -# * Script to reproduce and understand examples in the paper *Earth system data cubes unravel global multivariate dynamics* . +* Script to reproduce and understand examples in the paper *Earth system data cubes unravel global multivariate dynamics* . -# * The code is written on Julia 1.9 and uses GeoMakie for plotting. +* The code is written on Julia 1.9 and uses GeoMakie for plotting. -# * Normal text are explanations referring to notation and equations in the paper +* Normal text are explanations referring to notation and equations in the paper -# * `# comments in the code are intended explain specific aspects of the coding` +* `# comments in the code are intended explain specific aspects of the coding` -# * ### New steps in workflows are introduced with **bold headers** +* ### New steps in workflows are introduced with **bold headers** ## Load requiered packages @@ -32,57 +32,63 @@ using Zarr, YAXArrays, NetCDF, DiskArrays ## other relevant packages using Statistics, Dates, SkipNan -# ### Select and subet an Earth system data cube +### Select and subet an Earth system data cube + +We have to choose a cube and here we select a monthly global cube of 2.5° resolution. This very low-resolution cube aims at fast processing for the safety of computational time and resources. -# We have to choose a cube and here we select a monthly global cube of 2.5° resolution. This very low-resolution cube aims at fast processing for the safety of computational time and resources. cube_handle = esdc(res="tiny") -# In this case it is better to have one cube for the Tair and one for terrestrial ecosystem respiration `R$_{eco}$`. +In this case it is better to have one cube for the Tair and one for terrestrial ecosystem respiration `R$_{eco}$`. + world_tair = cube_handle[variable = At("air_temperature_2m")] world_resp = cube_handle[variable = At("terrestrial_ecosystem_respiration")] -# Find overlapping time between variables +Find overlapping time between variables + span_starts = first(findall(i-> !ismissing(i), world_tair[:,:,:])) axtime = collect(cube_handle.axes[3]); println("Data span of `air_temperature_2m` starts on ", axtime[span_starts[3]]) -# similarly +similarly span_starts = first(findall(i-> !ismissing(i), world_resp[:,:,:])) axtime = collect(cube_handle.axes[3]); println("Data span of `terrestrial_ecosystem_respiration` starts on ", axtime[span_starts[3]]) -# susbet again based on overlapping period +susbet again based on overlapping period + world_tair = world_tair[time=2001:2015] world_resp = world_resp[time=2001:2015] -# The objective is to estimate $Q_{10}$ from the decomposed time series. -# For details we refere the reader to Mahecha, M.D. et al. (2010) *Global convergence -# in the temperature sensitivity of respiration at ecosystem level.* Science, 329, 838-840. +The objective is to estimate $Q_{10}$ from the decomposed time series. +For details we refere the reader to Mahecha, M.D. et al. (2010) *Global convergence +in the temperature sensitivity of respiration at ecosystem level.* Science, 329, 838-840. + +The first step is the transformation of both variables, so that the $Q_{10}$ model becomes linear and Tair the exponent: -# The first step is the transformation of both variables, so that the $Q_{10}$ model becomes linear and Tair the exponent: +Element-wise transformations using `map` are done in a lazy manner, so the +transformation will be applied only when the data is read or further processed +We forced `world_τ` output format as Float32 to assure the output data type is equal, and to avoid further incompatibilities -## Element-wise transformations using `map` are done in a lazy manner, so the -## transformation will be applied only when the data is read or further processed -## We forced `world_τ` output format as Float32 to assure the output data type is equal, and to avoid further incompatibilities world_τ = map(tair -> (tair - Float32(273.15+15))/10, world_tair) world_ρ = map(log, world_resp) -# ... and we combine them into a Data Cube again using `concatenatecubes` +... and we combine them into a Data Cube again using `concatenatecubes` + world_new = concatenatecubes([world_τ, world_ρ], Dim{:Variable}(["τ","ρ"])) -# First we need a function for time-series filtering. Using a moving average filter is the simplest way -# to decomposes a signal into fast and slow oscillations by caluclating a moving average over a window of points. -# This creates a smoothed curve (slow osc.) which can be subtracted from the original signal to obtain -# fast oscillations separately. We could have likewise used FFTs, SSA, EMD, or any other method for -# discrete time-series decomposition. -# Moving Average decomposes a signal into fast and slow oscillations -# by calculating a moving average over a window of points. -# This creates a smoothed curve (slow osc.) which can be subtracted from the original signal, -# to obtain fast oscillations separately. +First we need a function for time-series filtering. Using a moving average filter is the simplest way +to decomposes a signal into fast and slow oscillations by caluclating a moving average over a window of points. +This creates a smoothed curve (slow osc.) which can be subtracted from the original signal to obtain +fast oscillations separately. We could have likewise used FFTs, SSA, EMD, or any other method for +discrete time-series decomposition. +Moving Average decomposes a signal into fast and slow oscillations +by calculating a moving average over a window of points. +This creates a smoothed curve (slow osc.) which can be subtracted from the original signal, +to obtain fast oscillations separately. function movingAverage(xout, xin; windowsize = 4) Z = length(xin) @@ -98,14 +104,16 @@ function movingAverage(xout, xin; windowsize = 4) return xout end -## here we define the input and output dimensions for the decomposition +here we define the input and output dimensions for the decomposition + indims = InDims("Time") outdims = OutDims("Time", Dim{:Scale}(["Slow","Fast"])) cube_decomp = mapCube(movingAverage, world_new, indims=indims, outdims=outdims) -# ### For estimating the temperature sensitivities +## For estimating the temperature sensitivities + +The classical $Q_{10}$ estimation could be realized with the following function -## The classical $Q_{10}$ estimation could be realized with the following function function Q10direct(xout_Q10, xout_rb, xin) τ, ρ = eachcol(xin) ## solve the regression @@ -119,7 +127,7 @@ function Q10direct(xout_Q10, xout_rb, xin) xout_Q10 .= Q10 end -# For the scale dependent parameter estimation, the function is a bit more complex. And the numbers in the code comment refer to the supporting online materials in Mahecha et al. (2010) +For the scale dependent parameter estimation, the function is a bit more complex. And the numbers in the code comment refer to the supporting online materials in Mahecha et al. (2010) function Q10SCAPE(xout_Q10, xout_rb, xin) ## xin is now a 3D array with dimensions Time x Scale x Variable τ_slow = xin[:, 1, 1] @@ -146,19 +154,20 @@ function Q10SCAPE(xout_Q10, xout_rb, xin) xout_rb .= Rb_b end -# ### Application of these functions on the prepared cubes +### Application of these functions on the prepared cubes indims_q10 = InDims("Time","Var") outdims_q10 = OutDims() ## Just a single number, the first output cube outdims_rb = OutDims("Time") ## The Rb time series, the second output cube q10_direct, rb_direct = mapCube(Q10direct, world_new, indims=indims_q10, outdims=(outdims_q10, outdims_rb)) -# For the SCAPE approach, the parameter estimation on the decomposed appraoch is then +For the SCAPE approach, the parameter estimation on the decomposed appraoch is then indims_scape = InDims("Time","Scale","Var") q10_scape, rb_scape = mapCube(Q10SCAPE,cube_decomp, indims=indims_scape, outdims=(outdims_q10, outdims_rb)) -# ### The rest is plotting. In this example we use GeoMakie. +### The rest is plotting. In this example we use GeoMakie. + using CairoMakie, GeoMakie CairoMakie.activate!() using MakieTeX @@ -188,12 +197,13 @@ fig1 = geoplotsfx(q10_direct[:,:].data, "a) Confounded Parameter Estimation", la fig2 = geoplotsfx(q10_scape[:,:].data, "b) Scale Dependent Parameter Estimation", label_scape, crange, cmap) -# ## The following are some additional analyses, not included in the paper. -# For this analysis we need to construct a new cube by concatenating a couple of previous cube outputs. -# To do this, there are two important remarks; (1) the cubes' axes order must be the same in both cubes -# (2) as well they both must have the same data chunking +## The following are some additional analyses, not included in the paper. +For this analysis we need to construct a new cube by concatenating a couple of previous cube outputs. +To do this, there are two important remarks; (1) the cubes' axes order must be the same in both cubes +(2) as well they both must have the same data chunking + +checking cubes axes order -## checking cubes axes order world_tair.axes # and @@ -201,11 +211,13 @@ world_tair.axes rb_scape.axes -# Now we need to sort the rb_scape axes order. Axes order must be the same for the cubes concatenation. +Now we need to sort the rb_scape axes order. Axes order must be the same for the cubes concatenation. + data_reshaped = permutedims(rb_scape.data,(2,3,1)) rb_scape_reshaped = YAXArray(rb_scape.axes[[2,3,1]],data_reshaped) -# checking cubes chunking +checking cubes chunking + eachchunk(world_tair) diff --git a/docs/examples/UserGuide/examples_from_esdl_study_4.jl b/docs/src/tutorials/examples_from_esdl_study_4.jl similarity index 100% rename from docs/examples/UserGuide/examples_from_esdl_study_4.jl rename to docs/src/tutorials/examples_from_esdl_study_4.jl diff --git a/docs/src/tutorials/mean_seasonal_cycle.md b/docs/src/tutorials/mean_seasonal_cycle.md new file mode 100644 index 00000000..fbe65d1e --- /dev/null +++ b/docs/src/tutorials/mean_seasonal_cycle.md @@ -0,0 +1,110 @@ +# Mean Seasonal Cycle for a sigle pixel + +````@example mean_season +using CairoMakie +CairoMakie.activate!() +using Dates +using Statistics +```` + +We define the data span. For simplicity, three non-leap years were selected. + +````@example mean_season +t = Date("2021-01-01"):Day(1):Date("2023-12-31") +NpY = 3 +```` +and create some seasonal dummy data + +````@example mean_season +x = repeat(range(0, 2π, length=365), NpY) +var = @. sin(x) + 0.1 * randn() +nothing # hide +```` + +````@example mean_season +lines(1:length(t), var; color = :purple, linewidth=1.25, + axis=(; xlabel="Time", ylabel="Variable"), + figure = (; resolution = (600,400)) + ) +```` + +Currently makie doesn't support time axis natively, but the following function can do the work for now. + +````@example mean_season +function time_ticks(dates; frac=8) + tempo = string.(dates) + lentime = length(tempo) + slice_dates = range(1, lentime, step=lentime ÷ frac) + return slice_dates, tempo[slice_dates] +end +xpos, ticks = time_ticks(t; frac=8) +nothing # hide +```` + +In order to apply the previous output, we split the plotting function into his 3 components, `figure`, `axis` and `plotted object`, namely + +````@example mean_season +fig, ax, obj = lines(1:length(t), var; color = :purple, linewidth=1.25, + axis=(; xlabel="Time", ylabel="Variable"), + figure = (; resolution = (600,400)) + ) +ax.xticks = (xpos, ticks) +ax.xticklabelrotation = π / 4 +ax.xticklabelalign = (:right, :center) +fig +```` + +### Define the cube + +````@ansi mean_season +using YAXArrays, DimensionalData +axes = (Dim{:Time}(t),) +c = YAXArray(axes, var) +```` + +Let's calculate the mean seasonal cycle of our dummy variable 'var' + +````@example mean_season +function mean_seasonal_cycle(c; ndays = 365) + ## filterig by month-day + monthday = map(x->Dates.format(x, "u-d"), collect(c.Time)) + datesid = unique(monthday) + ## number of years + NpY = Int(size(monthday,1)/ndays) + idx = Int.(zeros(ndays, NpY)) + ## get the day-month indices for data subsetting + for i in 1:ndays + idx[i,:] = Int.(findall(x-> x == datesid[i], monthday)) + end + ## compute the mean seasonal cycle + mscarray = map(x->var[x], idx) + msc = mapslices(mean, mscarray, dims=2) + return msc +end + +msc = mean_seasonal_cycle(c); +```` + +TODO: Apply the new groupby funtion from DD + +### Plot results: mean seasonal cycle + +````@example mean_season +xpos, ticks = time_ticks(t[1:365]; frac=8) + +fig, ax, obj = lines(1:365, var[1:365]; label="2021", color=:black, + linewidth=2.0, linestyle=:dot, + axis = (; xlabel="Time", ylabel="Variable"), + figure=(; size = (600,400)) + ) +lines!(1:365, var[366:730], label="2022", color=:brown, + linewidth=1.5, linestyle=:dash + ) +lines!(1:365, msc[:,1]; label="MSC", color=:dodgerblue, lw=2.5) +axislegend() +ax.xticks = (xpos, ticks) +ax.xticklabelrotation = π / 4 +ax.xticklabelalign = (:right, :center) +fig +current_figure() +```` \ No newline at end of file diff --git a/docs/examples/Gallery/simplemaps.jl b/docs/src/tutorials/plottingmaps.md similarity index 73% rename from docs/examples/Gallery/simplemaps.jl rename to docs/src/tutorials/plottingmaps.md index 7d580d0b..7c5222e4 100644 --- a/docs/examples/Gallery/simplemaps.jl +++ b/docs/src/tutorials/plottingmaps.md @@ -1,53 +1,85 @@ +# Plotting maps + +As test data we use the CMIP6 Scenarios. + +````@example plots using Zarr, YAXArrays, Dates using DimensionalData using GLMakie, GeoMakie using GLMakie.GeometryBasics store ="gs://cmip6/CMIP6/ScenarioMIP/DKRZ/MPI-ESM1-2-HR/ssp585/r1i1p1f1/3hr/tas/gn/v20190710/" +```` +````@ansi plots g = open_dataset(zopen(store, consolidated=true)) -c = g["tas"] +```` + +````@ansi plots +c = g["tas"]; +nothing # hide +```` + +Subset, first time step -# Subset, first time step -ct1_slice = c[Ti = Near(Date("2015-01-01"))] -## use lookup to get axis values +````@ansi plots +ct1_slice = c[Ti = Near(Date("2015-01-01"))]; +nothing # hide +```` + +use lookup to get axis values + +````@example plots lon = lookup(ct1_slice, :lon) lat = lookup(ct1_slice, :lat) data = ct1_slice.data[:,:]; +nothing # hide +```` -# ## Heatmap plot +## Heatmap plot +````@example plots GLMakie.activate!() fig, ax, plt = heatmap(ct1_slice; colormap = :seaborn_icefire_gradient, axis = (; aspect=DataAspect()), figure = (; size = (1200,600), fontsize=24)) fig +```` +# Wintri Projection +Some transformations -# ## Add Coastlines via the GeoAxis, wintri Projection -# # some transformations +````@example plots δlon = (lon[2]-lon[1])/2 nlon = lon .- 180 .+ δlon ndata = circshift(data, (192,1)) +nothing # hide +```` +and add Coastlines with `GeoMakie.coastlines()`, + +````@example plots fig = Figure(;size=(1200,600)) ax = GeoAxis(fig[1,1]) surface!(ax, nlon, lat, ndata; colormap = :seaborn_icefire_gradient, shading=false) cl=lines!(ax, GeoMakie.coastlines(), color = :white, linewidth=0.85) translate!(cl, 0, 0, 1000) fig +```` +## Moll projection -# ## Moll projection - +````@example plots fig = Figure(; size=(1200,600)) ax = GeoAxis(fig[1,1]; dest = "+proj=moll") surface!(ax, nlon, lat, ndata; colormap = :seaborn_icefire_gradient, shading=false) cl=lines!(ax, GeoMakie.coastlines(), color = :white, linewidth=0.85) translate!(cl, 0, 0, 1000) fig +```` -# ## 3D sphere plot +## 3D sphere plot +````julia using Bonito, WGLMakie Page(exportable=true, offline=true) @@ -64,5 +96,6 @@ mesh!(ax, sphere; color = ds'[end:-1:1,:], shading=false, zoom!(ax.scene, cameracontrols(ax.scene), 0.5) rotate!(ax.scene, 2.5) fig +```` diff --git a/src/Cubes/Cubes.jl b/src/Cubes/Cubes.jl index 47b29d43..6a6d6026 100644 --- a/src/Cubes/Cubes.jl +++ b/src/Cubes/Cubes.jl @@ -505,13 +505,15 @@ getCubeDes(::DD.Dimension) = "Cube axis" getCubeDes(::YAXArray) = "YAXArray" getCubeDes(::Type{T}) where {T} = string(T) -function DD.show_after(io::IO,mime, c::YAXArray) - foreach(getattributes(c)) do p - if p[1] in ("labels", "name", "units") - println(io, p[1], ": ", p[2]) - end - end - println(io, "Total size: ", formatbytes(cubesize(c))) +function DD.show_after(io::IO, mime, c::YAXArray) + blockwidth = get(io, :blockwidth, 0) + DD.print_block_separator(io, "file size", blockwidth, blockwidth) + println(io, " ") + println(io, " file size: ", formatbytes(cubesize(c))) + DD.print_block_close(io, blockwidth) + # And if you want the array data to print: + # ndims(c) > 0 && println(io) + # DD.print_array(io, mime, c) end From 5e392bb1497bdf8572080fbd08c471a708715cff Mon Sep 17 00:00:00 2001 From: Lazaro Alonso Date: Mon, 19 Feb 2024 17:17:41 +0100 Subject: [PATCH 2/2] ignore dead links --- docs/src/.vitepress/config.mts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/src/.vitepress/config.mts b/docs/src/.vitepress/config.mts index a6fe1ca6..5bc40a2f 100644 --- a/docs/src/.vitepress/config.mts +++ b/docs/src/.vitepress/config.mts @@ -4,11 +4,12 @@ import mathjax3 from "markdown-it-mathjax3"; // https://vitepress.dev/reference/site-config export default defineConfig({ - base: '/YAXArrays.jl/', + base: 'REPLACE_ME_WITH_DOCUMENTER_VITEPRESS_BASE_URL_WITH_TRAILING_SLASH', title: "YAXArrays.jl", description: "Yet another xarray-like Julia package", lastUpdated: true, cleanUrls: true, + ignoreDeadLinks: true, markdown: { math: true,