diff --git a/docs/cookbook/data/_category_.json b/docs/cookbook/data/_category_.json
new file mode 100644
index 0000000..d949de3
--- /dev/null
+++ b/docs/cookbook/data/_category_.json
@@ -0,0 +1,10 @@
+{
+ "position": 3,
+ "label": "Datasets",
+ "collapsible": true,
+ "collapsed": true,
+ "link": {
+ "type": "doc",
+ "id": "cookbook-data-overview"
+ }
+}
diff --git a/docs/cookbook/data/germany-tmax-heatmap.md b/docs/cookbook/data/germany-tmax-heatmap.md
new file mode 100644
index 0000000..3ee9911
--- /dev/null
+++ b/docs/cookbook/data/germany-tmax-heatmap.md
@@ -0,0 +1,678 @@
+---
+title: Animated Temperature Heatmap | Datasets Cookbook
+sidebar_label: Animated Temperature Heatmap
+sidebar_position: 1
+description: Build an animated GIF showing Germany's daily maximum temperatures for a given month, using Meteostat bulk data, SciPy interpolation, and Matplotlib.
+tags:
+ - Python
+ - Visualization
+ - Datasets
+ - Bulk Data
+---
+
+# Animated Temperature Heatmap
+
+This recipe walks through creating an animated GIF of Germany's daily maximum temperature (`tmax`) for a given month. It combines Meteostat's [daily Parquet dataset](/data/bulk/daily) with SciPy spatial interpolation and Matplotlib rendering to produce a smooth, day-by-day temperature map.
+
+
+
+Full Script
+
+```python
+"""
+Generate an animated GIF of Germany's daily maximum temperature (tmax).
+
+Data sources:
+ - Station metadata : Meteostat stations.db
+ - Daily observations : Meteostat daily parquet (one file per year)
+ - Country / state borders : Natural Earth 50 m cultural shapefiles
+
+Usage:
+ python generate_germany_tmax_gif.py
+"""
+
+import io
+import os
+import pathlib
+import sqlite3
+import tempfile
+import urllib.request
+import warnings
+import zipfile
+
+import geopandas as gpd
+import matplotlib
+import matplotlib.patheffects as pe
+import matplotlib.pyplot as plt
+import numpy as np
+import pandas as pd
+import requests
+import shapely
+from matplotlib.collections import PatchCollection
+from matplotlib.colors import LinearSegmentedColormap
+from matplotlib.patches import Polygon as MplPolygon
+from matplotlib.ticker import MultipleLocator
+from PIL import Image
+from scipy.interpolate import griddata
+from scipy.ndimage import gaussian_filter
+
+warnings.filterwarnings("ignore")
+matplotlib.use("Agg")
+
+# ── Configuration ─────────────────────────────────────────────────────────────
+
+YEAR = 2026
+MONTH = 5 # 1 = January … 12 = December
+
+OUTPUT_PATH = pathlib.Path(__file__).with_name(
+ f"germany_tmax_{YEAR}_{MONTH:02d}.gif"
+)
+
+# Map bounding box (WGS 84 lon/lat)
+LON_MIN, LAT_MIN, LON_MAX, LAT_MAX = 5.5, 47.0, 15.5, 55.5
+GRID_RES = 500 # interpolation grid points per axis
+
+# Temperature colour scale; each colour is paired with an approximate °C anchor
+TEMP_COLORS = [
+ "#3B0DA6", # -5 °C deep violet
+ "#1464D2", # 5 °C royal blue
+ "#28B4E6", # 12 °C sky blue
+ "#A0E632", # 18 °C yellow-green
+ "#F5E900", # 24 °C golden yellow
+ "#F07800", # 30 °C deep orange
+ "#9B0000", # 35 °C dark red
+]
+VMIN, VMAX = -5, 35
+
+# Minimum spacing (degrees) between temperature labels — one per grid cell
+LABEL_GRID_LON = 0.9
+LABEL_GRID_LAT = 0.6
+
+# ── Helpers ───────────────────────────────────────────────────────────────────
+
+def download_ne(scale, category, name, tmpdir):
+ """Download and unzip a Natural Earth shapefile; return the .shp path."""
+ url = f"https://naciscdn.org/naturalearth/{scale}/{category}/{name}.zip"
+ zip_path = os.path.join(tmpdir, f"{name}.zip")
+ urllib.request.urlretrieve(url, zip_path)
+ out = os.path.join(tmpdir, name)
+ os.makedirs(out, exist_ok=True)
+ with zipfile.ZipFile(zip_path) as zf:
+ zf.extractall(out)
+ return next(pathlib.Path(out).rglob("*.shp"))
+
+
+def iter_parts(geom):
+ """Yield individual polygon parts from a (possibly Multi-) geometry."""
+ yield from (geom.geoms if hasattr(geom, "geoms") else [geom])
+
+
+def extract_coords(geodataframe):
+ """Return exterior coordinate arrays for all polygon parts in a GeoDataFrame."""
+ return [
+ np.column_stack(part.exterior.xy)
+ for geom in geodataframe.geometry.dropna()
+ for part in iter_parts(geom)
+ ]
+
+
+# ── 1. Station metadata ───────────────────────────────────────────────────────
+
+print("Downloading stations.db …")
+r = requests.get("https://data.meteostat.net/stations.db", timeout=60)
+with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as f:
+ f.write(r.content)
+ db_tmp = f.name
+
+con = sqlite3.connect(db_tmp)
+de_stations = pd.read_sql(
+ "SELECT id AS station, latitude AS lat, longitude AS lon "
+ "FROM stations WHERE country = 'DE'",
+ con,
+).set_index("station")
+con.close()
+os.unlink(db_tmp)
+print(f" {len(de_stations)} German stations found")
+
+# ── 2. Daily observations ─────────────────────────────────────────────────────
+
+print(f"Downloading daily parquet ({YEAR}) …")
+r = requests.get(f"https://data.meteostat.net/daily/{YEAR}.parquet", timeout=120)
+df = pd.read_parquet(io.BytesIO(r.content), columns=["station", "date", "tmax"])
+
+df = df[df["station"].isin(de_stations.index)].copy()
+df = df.dropna(subset=["tmax"])
+df["date"] = pd.to_datetime(df["date"])
+df = df.merge(de_stations[["lat", "lon"]], left_on="station", right_index=True)
+print(f" {len(df):,} rows for Germany")
+
+# ── 3. Geographic data ────────────────────────────────────────────────────────
+
+print("Downloading Natural Earth 50 m boundaries …")
+tmpdir = tempfile.mkdtemp()
+
+countries_shp = download_ne("50m", "cultural", "ne_50m_admin_0_countries", tmpdir)
+states_shp = download_ne("50m", "cultural", "ne_50m_admin_1_states_provinces", tmpdir)
+
+world = gpd.read_file(countries_shp)
+germany = world[world["SOVEREIGNT"] == "Germany"]
+de_states = gpd.read_file(states_shp).query("admin == 'Germany'")
+
+# Natural Earth has used "Czechia" since ~2016; accept both spellings
+NEIGHBORS = {
+ "France", "Netherlands", "Belgium", "Luxembourg",
+ "Denmark", "Poland", "Czechia", "Czech Republic",
+ "Austria", "Switzerland", "Liechtenstein", "Italy",
+}
+neighbors = world[world["SOVEREIGNT"].isin(NEIGHBORS)]
+
+# ── 4. Interpolation grid & land mask ────────────────────────────────────────
+
+grid_lon = np.linspace(LON_MIN, LON_MAX, GRID_RES)
+grid_lat = np.linspace(LAT_MIN, LAT_MAX, GRID_RES)
+glon, glat = np.meshgrid(grid_lon, grid_lat)
+
+# Boolean mask: True where a grid point lies inside Germany
+germany_union = germany.geometry.union_all()
+mask = shapely.contains_xy(germany_union, glon.ravel(), glat.ravel()).reshape(glon.shape)
+
+# ── 5. Figure geometry ────────────────────────────────────────────────────────
+#
+# Pre-compute layout constants so the map axes fills its allocated fraction
+# at equal aspect with no wasted whitespace.
+#
+# map height (in) = map width (in) × (lat_range / lon_range)
+# figure height = map height + top margin (title) + bottom margin (credit)
+
+FIG_W = 11.0 # figure width in inches
+MAP_W_FRAC = 0.82 # fraction of figure width occupied by the map axes
+MAP_LEFT = 0.01
+
+lon_range = LON_MAX - LON_MIN
+lat_range = LAT_MAX - LAT_MIN
+
+map_w_in = FIG_W * MAP_W_FRAC
+map_h_in = map_w_in * (lat_range / lon_range)
+
+TOP_IN = 0.80 # inches reserved for the title block
+BOTTOM_IN = 0.22 # inches reserved for the credit line
+FIG_H = map_h_in + TOP_IN + BOTTOM_IN
+
+MAP_BOTTOM = BOTTOM_IN / FIG_H
+MAP_H_FRAC = map_h_in / FIG_H
+
+CBAR_GAP = 0.015
+CBAR_W_FRAC = 0.030
+CBAR_LEFT = MAP_LEFT + MAP_W_FRAC + CBAR_GAP
+CBAR_BOTTOM = MAP_BOTTOM + 0.05
+CBAR_HEIGHT = MAP_H_FRAC - 0.10
+
+# ── 6. Pre-compute static geometry ───────────────────────────────────────────
+
+temp_cmap = LinearSegmentedColormap.from_list("tmax", TEMP_COLORS, N=512)
+
+# Extract polygon coordinate arrays once; MplPolygon objects are recreated
+# each frame because PatchCollection takes ownership of its patches.
+neighbor_coords = extract_coords(neighbors)
+state_coords = extract_coords(de_states)
+germany_coords = extract_coords(germany)
+
+# ── 7. Render frames ──────────────────────────────────────────────────────────
+
+dates = sorted(d for d in df["date"].dt.date.unique() if d.month == MONTH)
+print(f"Rendering {len(dates)} frames (figure {FIG_W:.1f}\" × {FIG_H:.1f}\")")
+
+frames = []
+
+for i, day in enumerate(dates):
+ day_df = df[df["date"].dt.date == day]
+ if len(day_df) < 10:
+ continue
+
+ points = day_df[["lon", "lat"]].values
+ values = day_df["tmax"].values
+
+ # Bilinear interpolation with nearest-neighbour fallback for edge gaps,
+ # then Gaussian smoothing to reduce point artefacts around sparse stations
+ grid_z = griddata(points, values, (glon, glat), method="linear")
+ grid_z_nn = griddata(points, values, (glon, glat), method="nearest")
+ grid_z = np.where(np.isnan(grid_z), grid_z_nn, grid_z)
+ grid_z = gaussian_filter(grid_z, sigma=5)
+ grid_z_masked = np.where(mask, grid_z, np.nan)
+
+ # ── figure setup ─────────────────────────────────────────────────────────
+ fig = plt.figure(figsize=(FIG_W, FIG_H), dpi=150, facecolor="#F0F4F8")
+ ax = fig.add_axes([MAP_LEFT, MAP_BOTTOM, MAP_W_FRAC, MAP_H_FRAC])
+ ax.set_facecolor("#C8DCF0") # ocean / out-of-bounds colour
+
+ # Neighbouring countries
+ ax.add_collection(PatchCollection(
+ [MplPolygon(c) for c in neighbor_coords],
+ facecolor="#E2E2E2", edgecolor="#BBBBBB", linewidth=0.4, zorder=1,
+ ))
+
+ # Temperature heatmap (Gouraud shading for smooth colour transitions)
+ im = ax.pcolormesh(
+ glon, glat, grid_z_masked,
+ cmap=temp_cmap, vmin=VMIN, vmax=VMAX,
+ shading="gouraud", zorder=2,
+ )
+
+ # Bundesländer borders
+ for coords in state_coords:
+ ax.plot(*coords.T, color="white", linewidth=0.5, alpha=0.7, zorder=3)
+
+ # Germany outer border
+ for coords in germany_coords:
+ ax.plot(*coords.T, color="#222222", linewidth=1.1, zorder=4)
+
+ # ── station temperature labels ────────────────────────────────────────────
+ # Divide the map into coarse grid cells and keep only the first station per
+ # cell so that labels are spread out and don't overlap.
+ label_cells = {}
+ for _, row in day_df.iterrows():
+ cell = (
+ int((row["lon"] - LON_MIN) / LABEL_GRID_LON),
+ int((row["lat"] - LAT_MIN) / LABEL_GRID_LAT),
+ )
+ label_cells.setdefault(cell, row)
+
+ outline = [pe.withStroke(linewidth=2.2, foreground="white")]
+ for row in label_cells.values():
+ if LON_MIN <= row["lon"] <= LON_MAX and LAT_MIN <= row["lat"] <= LAT_MAX:
+ ax.text(
+ row["lon"], row["lat"], str(int(round(row["tmax"]))),
+ ha="center", va="center",
+ fontsize=7.5, fontweight="bold", color="#111111",
+ path_effects=outline, zorder=5,
+ )
+
+ ax.set_xlim(LON_MIN, LON_MAX)
+ ax.set_ylim(LAT_MIN, LAT_MAX)
+ ax.set_aspect("equal")
+ ax.axis("off")
+
+ # ── colorbar ─────────────────────────────────────────────────────────────
+ cbar_ax = fig.add_axes([CBAR_LEFT, CBAR_BOTTOM, CBAR_W_FRAC, CBAR_HEIGHT])
+ cbar = fig.colorbar(im, cax=cbar_ax)
+ cbar.set_label("Max Temp (°C)", fontsize=8, color="#333333", labelpad=5)
+ cbar.ax.yaxis.set_tick_params(color="#555555", width=0.5)
+ cbar.outline.set_edgecolor("#AAAAAA")
+ cbar.outline.set_linewidth(0.5)
+ plt.setp(cbar.ax.yaxis.get_ticklabels(), color="#333333", fontsize=7.5)
+ cbar.ax.yaxis.set_major_locator(MultipleLocator(5))
+
+ # ── title and date ────────────────────────────────────────────────────────
+ fig.text(
+ MAP_LEFT + MAP_W_FRAC / 2, 1.0 - (TOP_IN * 0.12) / FIG_H,
+ "Germany — Daily Maximum Temperature",
+ ha="center", va="top", fontsize=12, fontweight="bold", color="#1A1A2E",
+ )
+ fig.text(
+ MAP_LEFT + MAP_W_FRAC / 2, 1.0 - (TOP_IN * 0.55) / FIG_H,
+ day.strftime("%d %B %Y"),
+ ha="center", va="top", fontsize=15, fontweight="bold", color="#C0392B",
+ )
+
+ # ── credit ────────────────────────────────────────────────────────────────
+ fig.text(
+ MAP_LEFT, (BOTTOM_IN * 0.35) / FIG_H,
+ "© Meteostat, Natural Earth",
+ ha="left", va="bottom", fontsize=6.5, color="#999999",
+ )
+
+ buf = io.BytesIO()
+ fig.savefig(buf, format="png", dpi=150, facecolor=fig.get_facecolor(),
+ bbox_inches="tight", pad_inches=0.12)
+ plt.close(fig)
+ buf.seek(0)
+ frames.append(Image.open(buf).copy())
+ buf.close()
+
+ if (i + 1) % 10 == 0 or (i + 1) == len(dates):
+ print(f" {i + 1}/{len(dates)} frames done")
+
+# ── 8. Save GIF ───────────────────────────────────────────────────────────────
+
+print(f"Saving GIF ({len(frames)} frames) → {OUTPUT_PATH}")
+frames[0].save(
+ OUTPUT_PATH,
+ save_all=True,
+ append_images=frames[1:],
+ duration=1000, # ms per frame
+ loop=0, # loop forever
+ optimize=False,
+)
+print("Done!")
+```
+
+
+
+
+
+## Dependencies {#dependencies}
+
+Install the required packages:
+
+```bash
+pip install requests pandas pyarrow geopandas scipy matplotlib pillow shapely
+```
+
+| Package | Purpose |
+| --------------------------------- | -------------------------------------------- |
+| `requests` / `pandas` / `pyarrow` | Fetch and read Parquet data |
+| `geopandas` / `shapely` | Load shapefiles and build a land mask |
+| `scipy` | Spatial interpolation and Gaussian smoothing |
+| `matplotlib` | Render each map frame |
+| `pillow` | Assemble frames into an animated GIF |
+
+## Configuration {#configuration}
+
+All tunable parameters live at the top of the script:
+
+```python
+import pathlib
+
+YEAR = 2026
+MONTH = 5 # 1 = January … 12 = December
+
+OUTPUT_PATH = pathlib.Path(__file__).with_name(
+ f"germany_tmax_{YEAR}_{MONTH:02d}.gif"
+)
+
+# Map bounding box (WGS 84 lon/lat)
+LON_MIN, LAT_MIN, LON_MAX, LAT_MAX = 5.5, 47.0, 15.5, 55.5
+GRID_RES = 500 # interpolation grid points per axis
+
+# Temperature colour scale; each colour is paired with an approximate °C anchor
+TEMP_COLORS = [
+ "#3B0DA6", # -5 °C deep violet
+ "#1464D2", # 5 °C royal blue
+ "#28B4E6", # 12 °C sky blue
+ "#A0E632", # 18 °C yellow-green
+ "#F5E900", # 24 °C golden yellow
+ "#F07800", # 30 °C deep orange
+ "#9B0000", # 35 °C dark red
+]
+VMIN, VMAX = -5, 35
+```
+
+Change `YEAR` and `MONTH` to render any month covered by the dataset.
+
+## Station Metadata {#station-metadata}
+
+The [weather station database](/data/weather-stations#database) is downloaded as a SQLite file. Only German stations (`country = 'DE'`) are retained, keeping just the coordinates needed for the subsequent spatial join.
+
+```python
+import io, os, sqlite3, tempfile
+import requests
+import pandas as pd
+
+r = requests.get("https://data.meteostat.net/stations.db", timeout=60)
+with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as f:
+ f.write(r.content)
+ db_tmp = f.name
+
+con = sqlite3.connect(db_tmp)
+de_stations = pd.read_sql(
+ "SELECT id AS station, latitude AS lat, longitude AS lon "
+ "FROM stations WHERE country = 'DE'",
+ con,
+).set_index("station")
+con.close()
+os.unlink(db_tmp)
+```
+
+## Daily Observations {#daily-observations}
+
+The [daily bulk endpoint](/data/bulk/daily) provides one Parquet file per year. Only the `tmax` column is read to keep memory usage low, then filtered to German stations and joined with their coordinates.
+
+```python
+r = requests.get(f"https://data.meteostat.net/daily/{YEAR}.parquet", timeout=120)
+df = pd.read_parquet(io.BytesIO(r.content), columns=["station", "date", "tmax"])
+
+df = df[df["station"].isin(de_stations.index)].copy()
+df = df.dropna(subset=["tmax"])
+df["date"] = pd.to_datetime(df["date"])
+df = df.merge(de_stations[["lat", "lon"]], left_on="station", right_index=True)
+```
+
+:::tip
+Passing `columns=["station", "date", "tmax"]` to `read_parquet` reads only the three needed columns, significantly reducing I/O for large files.
+:::
+
+## Geographic Data {#geographic-data}
+
+Country and state borders come from [Natural Earth](https://www.naturalearthdata.com/) 1:50 m cultural shapefiles. Germany's geometry is also used to build the land mask in the next step.
+
+```python
+import urllib.request, zipfile
+import geopandas as gpd
+
+def download_ne(scale, category, name, tmpdir):
+ url = f"https://naciscdn.org/naturalearth/{scale}/{category}/{name}.zip"
+ zip_path = os.path.join(tmpdir, f"{name}.zip")
+ urllib.request.urlretrieve(url, zip_path)
+ out = os.path.join(tmpdir, name)
+ os.makedirs(out, exist_ok=True)
+ with zipfile.ZipFile(zip_path) as zf:
+ zf.extractall(out)
+ return next(pathlib.Path(out).rglob("*.shp"))
+
+tmpdir = tempfile.mkdtemp()
+countries_shp = download_ne("50m", "cultural", "ne_50m_admin_0_countries", tmpdir)
+states_shp = download_ne("50m", "cultural", "ne_50m_admin_1_states_provinces", tmpdir)
+
+world = gpd.read_file(countries_shp)
+germany = world[world["SOVEREIGNT"] == "Germany"]
+de_states = gpd.read_file(states_shp).query("admin == 'Germany'")
+
+NEIGHBORS = {
+ "France", "Netherlands", "Belgium", "Luxembourg",
+ "Denmark", "Poland", "Czechia", "Czech Republic",
+ "Austria", "Switzerland", "Liechtenstein", "Italy",
+}
+neighbors = world[world["SOVEREIGNT"].isin(NEIGHBORS)]
+```
+
+## Interpolation {#interpolation}
+
+For each day, station observations are interpolated onto a regular `500 × 500` grid using SciPy's `griddata`. A bilinear pass fills most of the grid; a nearest-neighbour pass plugs any remaining gaps near the borders. A Gaussian blur (`σ = 5`) then smooths out point artefacts around sparse station coverage.
+
+```python
+import numpy as np
+from scipy.interpolate import griddata
+from scipy.ndimage import gaussian_filter
+import shapely
+
+# Build the grid once
+grid_lon = np.linspace(LON_MIN, LON_MAX, GRID_RES)
+grid_lat = np.linspace(LAT_MIN, LAT_MAX, GRID_RES)
+glon, glat = np.meshgrid(grid_lon, grid_lat)
+
+# Boolean land mask — True where the grid point lies inside Germany
+germany_union = germany.geometry.union_all()
+mask = shapely.contains_xy(germany_union, glon.ravel(), glat.ravel()).reshape(glon.shape)
+
+# Per-day interpolation (inside the rendering loop)
+points = day_df[["lon", "lat"]].values
+values = day_df["tmax"].values
+
+grid_z = griddata(points, values, (glon, glat), method="linear")
+grid_z_nn = griddata(points, values, (glon, glat), method="nearest")
+grid_z = np.where(np.isnan(grid_z), grid_z_nn, grid_z)
+grid_z = gaussian_filter(grid_z, sigma=5)
+grid_z_masked = np.where(mask, grid_z, np.nan)
+```
+
+## Figure Layout {#figure-layout}
+
+The figure dimensions are derived analytically so the map axes fills its allocated width at equal aspect without whitespace. This is computed once before the rendering loop.
+
+```python
+FIG_W = 11.0 # figure width in inches
+MAP_W_FRAC = 0.82 # fraction of the figure width occupied by the map axes
+MAP_LEFT = 0.01
+
+lon_range = LON_MAX - LON_MIN
+lat_range = LAT_MAX - LAT_MIN
+
+map_w_in = FIG_W * MAP_W_FRAC
+map_h_in = map_w_in * (lat_range / lon_range)
+
+TOP_IN = 0.80 # inches for the title block
+BOTTOM_IN = 0.22 # inches for the credit line
+FIG_H = map_h_in + TOP_IN + BOTTOM_IN
+
+MAP_BOTTOM = BOTTOM_IN / FIG_H
+MAP_H_FRAC = map_h_in / FIG_H
+
+CBAR_GAP = 0.015
+CBAR_W_FRAC = 0.030
+CBAR_LEFT = MAP_LEFT + MAP_W_FRAC + CBAR_GAP
+CBAR_BOTTOM = MAP_BOTTOM + 0.05
+CBAR_HEIGHT = MAP_H_FRAC - 0.10
+```
+
+## Rendering {#rendering}
+
+Each day becomes one figure. The heatmap uses Gouraud shading for smooth colour transitions. Temperature labels are de-cluttered by dividing the map into a coarse grid and keeping only one station per cell.
+
+```python
+import matplotlib
+import matplotlib.patheffects as pe
+import matplotlib.pyplot as plt
+from matplotlib.collections import PatchCollection
+from matplotlib.colors import LinearSegmentedColormap
+from matplotlib.patches import Polygon as MplPolygon
+from matplotlib.ticker import MultipleLocator
+
+matplotlib.use("Agg")
+
+temp_cmap = LinearSegmentedColormap.from_list("tmax", TEMP_COLORS, N=512)
+
+# Helper — extract polygon coordinate arrays from a GeoDataFrame
+def extract_coords(gdf):
+ def iter_parts(geom):
+ yield from (geom.geoms if hasattr(geom, "geoms") else [geom])
+ return [
+ np.column_stack(part.exterior.xy)
+ for geom in gdf.geometry.dropna()
+ for part in iter_parts(geom)
+ ]
+
+neighbor_coords = extract_coords(neighbors)
+state_coords = extract_coords(de_states)
+germany_coords = extract_coords(germany)
+
+# ── render one frame ──────────────────────────────────────────────────────────
+fig = plt.figure(figsize=(11.0, FIG_H), dpi=150, facecolor="#F0F4F8")
+ax = fig.add_axes([MAP_LEFT, MAP_BOTTOM, MAP_W_FRAC, MAP_H_FRAC])
+ax.set_facecolor("#C8DCF0") # ocean / out-of-bounds colour
+
+# Neighbouring countries (light grey fill)
+ax.add_collection(PatchCollection(
+ [MplPolygon(c) for c in neighbor_coords],
+ facecolor="#E2E2E2", edgecolor="#BBBBBB", linewidth=0.4, zorder=1,
+))
+
+# Temperature heatmap
+im = ax.pcolormesh(
+ glon, glat, grid_z_masked,
+ cmap=temp_cmap, vmin=VMIN, vmax=VMAX,
+ shading="gouraud", zorder=2,
+)
+
+# Bundesländer borders and Germany outline
+for coords in state_coords:
+ ax.plot(*coords.T, color="white", linewidth=0.5, alpha=0.7, zorder=3)
+for coords in germany_coords:
+ ax.plot(*coords.T, color="#222222", linewidth=1.1, zorder=4)
+
+# De-cluttered temperature labels — one per coarse grid cell
+LABEL_GRID_LON, LABEL_GRID_LAT = 0.9, 0.6
+label_cells = {}
+for _, row in day_df.iterrows():
+ cell = (
+ int((row["lon"] - LON_MIN) / LABEL_GRID_LON),
+ int((row["lat"] - LAT_MIN) / LABEL_GRID_LAT),
+ )
+ label_cells.setdefault(cell, row)
+
+outline = [pe.withStroke(linewidth=2.2, foreground="white")]
+for row in label_cells.values():
+ if LON_MIN <= row["lon"] <= LON_MAX and LAT_MIN <= row["lat"] <= LAT_MAX:
+ ax.text(
+ row["lon"], row["lat"], str(int(round(row["tmax"]))),
+ ha="center", va="center",
+ fontsize=7.5, fontweight="bold", color="#111111",
+ path_effects=outline, zorder=5,
+ )
+
+ax.set_xlim(LON_MIN, LON_MAX)
+ax.set_ylim(LAT_MIN, LAT_MAX)
+ax.set_aspect("equal")
+ax.axis("off")
+
+# Colorbar
+cbar_ax = fig.add_axes([CBAR_LEFT, CBAR_BOTTOM, CBAR_W_FRAC, CBAR_HEIGHT])
+cbar = fig.colorbar(im, cax=cbar_ax)
+cbar.set_label("Max Temp (°C)", fontsize=8, color="#333333", labelpad=5)
+cbar.ax.yaxis.set_major_locator(MultipleLocator(5))
+
+# Title, date, and credit
+fig.text(
+ MAP_LEFT + MAP_W_FRAC / 2, 1.0 - (TOP_IN * 0.12) / FIG_H,
+ "Germany — Daily Maximum Temperature",
+ ha="center", va="top", fontsize=12, fontweight="bold", color="#1A1A2E",
+)
+fig.text(
+ MAP_LEFT + MAP_W_FRAC / 2, 1.0 - (TOP_IN * 0.55) / FIG_H,
+ day.strftime("%d %B %Y"),
+ ha="center", va="top", fontsize=15, fontweight="bold", color="#C0392B",
+)
+fig.text(
+ MAP_LEFT, (BOTTOM_IN * 0.35) / FIG_H,
+ "© Meteostat, Natural Earth",
+ ha="left", va="bottom", fontsize=6.5, color="#999999",
+)
+```
+
+## Output {#output}
+
+Each rendered figure is captured into an in-memory buffer and converted to a Pillow `Image`. After all days are processed, the frames are assembled into a looping animated GIF at one second per frame.
+
+```python
+from PIL import Image
+
+frames = []
+dates = sorted(d for d in df["date"].dt.date.unique() if d.month == MONTH)
+
+for day in dates:
+ day_df = df[df["date"].dt.date == day]
+ if len(day_df) < 10:
+ continue
+
+ # … interpolation and rendering (see above) …
+
+ buf = io.BytesIO()
+ fig.savefig(buf, format="png", dpi=150, facecolor=fig.get_facecolor(),
+ bbox_inches="tight", pad_inches=0.12)
+ plt.close(fig)
+ buf.seek(0)
+ frames.append(Image.open(buf).copy())
+ buf.close()
+
+frames[0].save(
+ OUTPUT_PATH,
+ save_all=True,
+ append_images=frames[1:],
+ duration=1000, # ms per frame
+ loop=0, # loop forever
+ optimize=False,
+)
+```
+
+:::tip
+Calling `Image.open(buf).copy()` before closing the buffer ensures each frame is fully loaded into memory. Without `.copy()`, Pillow would read from a closed buffer when assembling the GIF.
+:::
diff --git a/docs/cookbook/data/germany_tmax_2026_05.gif b/docs/cookbook/data/germany_tmax_2026_05.gif
new file mode 100644
index 0000000..fb93094
Binary files /dev/null and b/docs/cookbook/data/germany_tmax_2026_05.gif differ
diff --git a/docs/cookbook/data/overview.md b/docs/cookbook/data/overview.md
new file mode 100644
index 0000000..95e429c
--- /dev/null
+++ b/docs/cookbook/data/overview.md
@@ -0,0 +1,15 @@
+---
+title: Datasets Cookbook
+sidebar_label: Overview
+id: cookbook-data-overview
+slug: /cookbook/data
+sidebar_position: 1
+---
+
+import DocCardList from '@theme/DocCardList';
+
+# Datasets Cookbook
+
+A collection of recipes and examples for accessing Meteostat weather and climate data.
+
+
diff --git a/docs/cookbook/python/_category_.json b/docs/cookbook/python/_category_.json
index e1ad155..03fc762 100644
--- a/docs/cookbook/python/_category_.json
+++ b/docs/cookbook/python/_category_.json
@@ -1,6 +1,6 @@
{
"position": 2,
- "label": "Python",
+ "label": "Python Library",
"collapsible": true,
"collapsed": true,
"link": {
diff --git a/docs/cookbook/python/dwd-climate-data.md b/docs/cookbook/python/dwd-climate-data.md
new file mode 100644
index 0000000..8f15b41
--- /dev/null
+++ b/docs/cookbook/python/dwd-climate-data.md
@@ -0,0 +1,194 @@
+---
+title: Accessing Climate Data from DWD | Python Library Cookbook
+sidebar_label: Accessing Data from DWD
+sidebar_position: 3
+description: Learn how to fetch weather and climate data directly from Deutscher Wetterdienst (DWD) using the Meteostat Python library.
+tags:
+ - Python
+ - Time Series
+ - Providers
+ - DWD
+---
+
+# Accessing Climate Data from DWD
+
+[Deutscher Wetterdienst (DWD)](https://www.dwd.de) is Germany's national meteorological service and one of the most comprehensive sources of weather and climate data for German stations. Meteostat integrates several DWD data feeds — covering hourly observations, daily summaries, and monthly records — that you can target directly using the [`providers`](/python/api/meteostat.hourly#parameters) parameter.
+
+## Available DWD Providers {#providers}
+
+| Provider Enum | Granularity | Covered Area |
+| ------------------------- | ----------------- | ------------ |
+| `ms.Provider.DWD_HOURLY` | Hourly | Germany |
+| `ms.Provider.DWD_POI` | Hourly | Europe |
+| `ms.Provider.DWD_MOSMIX` | Hourly (forecast) | Global |
+| `ms.Provider.DWD_DAILY` | Daily | Germany |
+| `ms.Provider.DWD_MONTHLY` | Monthly | Germany |
+| `ms.Provider.CLIMAT` | Monthly | Global |
+
+A full list of available providers is available [here](/providers).
+
+:::tip[Be Explicit]
+Always pass both `providers` and `parameters` when targeting a specific DWD source. This avoids unnecessary data fetches and makes the data lineage clear.
+:::
+
+## Installation {#installation}
+
+```bash
+pip install meteostat
+```
+
+The `DWD_MOSMIX` provider also requires the `lxml` package for parsing XML data.
+
+## Finding a DWD Station {#finding-stations}
+
+DWD does not only cover stations in Germany, but also provides access to stations across Europe and beyond. However, the majority of DWD's data is for German stations, and the `DWD_HOURLY`, `DWD_DAILY`, and `DWD_MONTHLY` providers are limited to German stations only.
+
+Those are the relevant identifiers for the different DWD feeds:
+
+- `DWD_HOURLY`, `DWD_DAILY` and `DWD_MONTHLY`: `national` ID; **most** German stations
+- `DWD_POI`: `wmo` ID, **selected** European stations
+- `DWD_MOSMIX`: `mosmix` ID, **thousands** of global stations
+
+For example, let's filter for German stations with a `national` ID:
+
+```python
+import meteostat as ms
+
+stations = ms.stations.query("""
+ SELECT s.id, n.name, i.value AS national_id, s.latitude, s.longitude
+ FROM stations s
+ JOIN names n ON s.id = n.station AND n.language = 'en'
+ JOIN identifiers i ON s.id = i.station AND i.key = 'national'
+ WHERE s.country = 'DE';
+""", index_col="id")
+
+print(stations)
+```
+
+Throughout this recipe, **Frankfurt Airport** (`10637`) is used as the example station — it has one of the longest continuous DWD records in Germany.
+
+## Hourly Observations {#hourly}
+
+`DWD_HOURLY` provides synoptic observations recorded every hour. The example below retrieves temperature and relative humidity for a full calendar year:
+
+```python
+from datetime import datetime
+import meteostat as ms
+
+start = datetime(2024, 1, 1)
+end = datetime(2024, 12, 31, 23, 59)
+
+ts = ms.hourly(
+ '10637',
+ start,
+ end,
+ providers=[ms.Provider.DWD_HOURLY],
+ parameters=[ms.Parameter.TEMP, ms.Parameter.RHUM],
+)
+
+df = ts.fetch()
+
+print(df.head())
+```
+
+Sample output:
+
+```
+ temp rhum
+time
+2024-01-01 00:00:00 4.8 92.0
+2024-01-01 01:00:00 4.5 93.0
+2024-01-01 02:00:00 4.2 94.0
+2024-01-01 03:00:00 4.0 95.0
+2024-01-01 04:00:00 3.8 95.0
+```
+
+## POI Feed {#poi}
+
+`DWD_POI` is a richer hourly feed that additionally includes cloud cover, snow depth, wind gusts, and visibility. Use it when you need the full parameter set:
+
+```python
+ts = ms.hourly(
+ '10637',
+ start,
+ end,
+ providers=[ms.Provider.DWD_POI],
+ parameters=[
+ ms.Parameter.TEMP,
+ ms.Parameter.PRCP,
+ ms.Parameter.CLDC,
+ ms.Parameter.SNWD,
+ ],
+)
+df = ts.fetch()
+```
+
+## Daily Summaries {#daily}
+
+`DWD_DAILY` provides daily climate summaries with a full set of parameters including min/max temperatures, precipitation, sunshine duration, and more:
+
+```python
+from datetime import date
+import meteostat as ms
+
+start = date(2020, 1, 1)
+end = date(2024, 12, 31)
+
+ts = ms.daily(
+ '10637',
+ start,
+ end,
+ providers=[ms.Provider.DWD_DAILY],
+ parameters=[
+ ms.Parameter.TMIN,
+ ms.Parameter.TMAX,
+ ms.Parameter.PRCP,
+ ms.Parameter.TSUN,
+ ],
+)
+df = ts.fetch()
+print(df.describe())
+```
+
+## Monthly Records {#monthly}
+
+`DWD_MONTHLY` provides pre-aggregated monthly values published by DWD. Use it for long-running climatological analyses where daily resolution is not required:
+
+```python
+from datetime import date
+import meteostat as ms
+
+start = date(1950, 1, 1)
+end = date(2024, 12, 31)
+
+ts = ms.monthly(
+ '10637',
+ start,
+ end,
+ providers=[ms.Provider.DWD_MONTHLY],
+ parameters=[ms.Parameter.TEMP, ms.Parameter.PRCP],
+)
+df = ts.fetch()
+print(df.tail(12))
+```
+
+## CLIMAT Reports {#climat}
+
+`CLIMAT` is an international monthly exchange format that DWD contributes to. It covers stations worldwide and includes parameters not available in `DWD_MONTHLY`, such as absolute monthly extremes (`txmn`, `txmx`) and mean sea-level pressure:
+
+```python
+from datetime import date
+import meteostat as ms
+
+start = date(1990, 1, 1)
+end = date(2024, 12, 31)
+
+ts = ms.monthly(
+ '10637',
+ start,
+ end,
+ providers=[ms.Provider.CLIMAT],
+ parameters=[ms.Parameter.TEMP, ms.Parameter.TMIN, ms.Parameter.TMAX],
+)
+df = ts.fetch()
+```
diff --git a/docs/cookbook/python/location-input.md b/docs/cookbook/python/location-input.md
index 2f8bdd7..c915900 100644
--- a/docs/cookbook/python/location-input.md
+++ b/docs/cookbook/python/location-input.md
@@ -1,5 +1,7 @@
---
-title: Location Input
+title: Location Input | Python Library Cookbook
+sidebar_label: Location Input
+sidebar_position: 1
description: Learn how to specify a location for fetching weather data using the Meteostat Python library.
tags:
- Python
diff --git a/docs/cookbook/python/merging-time-series.md b/docs/cookbook/python/merging-time-series.md
index d4c2448..d1350f3 100644
--- a/docs/cookbook/python/merging-time-series.md
+++ b/docs/cookbook/python/merging-time-series.md
@@ -1,5 +1,7 @@
---
-title: Merging Time Series
+title: Merging Time Series | Python Library Cookbook
+sidebar_label: Merging Time Series
+sidebar_position: 2
description: Learn how to merge multiple time series objects into a single one using the Meteostat Python library.
tags:
- Python
diff --git a/docs/cookbook/python/overview.md b/docs/cookbook/python/overview.md
index fc0b032..3f9f646 100644
--- a/docs/cookbook/python/overview.md
+++ b/docs/cookbook/python/overview.md
@@ -1,5 +1,5 @@
---
-title: Python | Cookbook
+title: Python Library Cookbook
sidebar_label: Overview
id: cookbook-python-overview
slug: /cookbook/python
@@ -8,7 +8,7 @@ sidebar_position: 1
import DocCardList from '@theme/DocCardList';
-# Python Cookbook
+# Python Library Cookbook
A collection of recipes and examples for working with Meteostat weather and climate data using the Python library.
diff --git a/docs/data/_category_.json b/docs/data/_category_.json
index c4ee0b9..b3c9a19 100644
--- a/docs/data/_category_.json
+++ b/docs/data/_category_.json
@@ -1,10 +1,10 @@
{
"position": 2,
- "label": "Data Access",
+ "label": "Datasets",
"collapsible": true,
"collapsed": true,
"link": {
"type": "generated-index",
- "title": "Data Access"
+ "title": "Datasets"
}
}
diff --git a/docs/data/bulk/daily.md b/docs/data/bulk/daily.md
index 6368f83..2b21169 100644
--- a/docs/data/bulk/daily.md
+++ b/docs/data/bulk/daily.md
@@ -1,5 +1,5 @@
---
-title: Daily Bulk Data | Data Access
+title: Daily Bulk Data | Datasets
sidebar_label: Daily Data
sidebar_position: 2
---
diff --git a/docs/data/bulk/hourly.md b/docs/data/bulk/hourly.md
index 6ad2b45..6434f4e 100644
--- a/docs/data/bulk/hourly.md
+++ b/docs/data/bulk/hourly.md
@@ -1,5 +1,5 @@
---
-title: Hourly Bulk Data | Data Access
+title: Hourly Bulk Data | Datasets
sidebar_label: Hourly Data
sidebar_position: 1
---
diff --git a/docs/data/bulk/monthly.md b/docs/data/bulk/monthly.md
index 7918891..e3f0ec7 100644
--- a/docs/data/bulk/monthly.md
+++ b/docs/data/bulk/monthly.md
@@ -1,5 +1,5 @@
---
-title: Monthly Bulk Data | Data Access
+title: Monthly Bulk Data | Datasets
sidebar_label: Monthly Data
sidebar_position: 3
---
diff --git a/docs/data/bulk/overview.md b/docs/data/bulk/overview.md
index 6f49d75..8958167 100644
--- a/docs/data/bulk/overview.md
+++ b/docs/data/bulk/overview.md
@@ -1,5 +1,5 @@
---
-title: Bulk Data | Data Access
+title: Bulk Data | Datasets
sidebar_label: Overview
id: data-bulk-overview
slug: /data/bulk
@@ -16,7 +16,7 @@ The Meteostat bulk data interface provides access to weather and climate data ac
This interface is currently in beta. We are actively working on improving it and adding new features. The formats and data structures may change in the future. We recommend checking back regularly for updates and improvements.
:::
-## 🔌 Access
+## 🔌 Access {#access}
This interface does not require an API key. However, when using this service you must comply with our [terms of service](/terms). Please make sure to cache data if possible and forbear from sending malicious calls to this service.
@@ -30,7 +30,7 @@ Data is available in three different granularities:
Years without data will return an HTTP `404` status code.
:::
-## 🚀 Quick Start
+## 🚀 Quick Start {#quick-start}
The download of annual data dumps is dead simple and doesn’t even require an API key:
@@ -38,10 +38,24 @@ The download of annual data dumps is dead simple and doesn’t even require an A
curl "https://data.meteostat.net/hourly/2024.parquet" --output "2024.parquet"
```
-## 🔄 Update Cycle
+## 🔄 Update Cycle {#update-cycle}
The dumps are updated regularly, depending on the granularity of records. Recent hourly data should be available after a maximum of 24 hours.
+## 📚 Specification {#specification}
+
+This dataset **is not versioned**. Therefore, clients **must be able to handle changes in the data structure**.
+
+- New columns may be added to the datasets **without prior notice**.
+- The order of columns may change **without prior notice**.
+- Changes to the data types of columns are **not communicated ahead of time** if types can be cast automatically (e.g., integer to float).
+- Existing columns may be removed or renamed with a **minimum 90-day notice**.
+- Breaking changes will be announced ahead of time in the [changelog](#changelog).
+
+## 📝 Changelog {#changelog}
+
+No changes have been made to this dataset so far.
+
## 👀 Learn More {#learn-more}
diff --git a/docs/data/overview.md b/docs/data/overview.md
index fff3d08..6bfd5b1 100644
--- a/docs/data/overview.md
+++ b/docs/data/overview.md
@@ -1,5 +1,5 @@
---
-title: Data Access
+title: Datasets
sidebar_label: Overview
id: data-overview
slug: /data
@@ -8,10 +8,12 @@ sidebar_position: 1
import DocCardList from '@theme/DocCardList';
-# Data Access
+# Meteostat Datasets
Meteostat provides open and free access to historical weather and climate data. Users can download full [time series](/data/timeseries/) of individual weather stations provided in **CSV** format and [bulk data](/data/bulk/) in **Parquet** format. Weather station [meta data](/data/weather-stations) is provided in **JSON** and **SQL** formats. Users are **not required to sign up** for this service.
+
+
## 👀 Learn More
diff --git a/docs/data/temperature-2026.gif b/docs/data/temperature-2026.gif
new file mode 100644
index 0000000..8916613
Binary files /dev/null and b/docs/data/temperature-2026.gif differ
diff --git a/docs/data/timeseries/daily.md b/docs/data/timeseries/daily.md
index c21982c..75866d6 100644
--- a/docs/data/timeseries/daily.md
+++ b/docs/data/timeseries/daily.md
@@ -1,5 +1,5 @@
---
-title: Daily Data | Data Access
+title: Daily Data | Datasets
sidebar_label: Daily Data
sidebar_position: 2
---
diff --git a/docs/data/timeseries/hourly.md b/docs/data/timeseries/hourly.md
index efb139f..c56e8c5 100644
--- a/docs/data/timeseries/hourly.md
+++ b/docs/data/timeseries/hourly.md
@@ -1,5 +1,5 @@
---
-title: Hourly Data | Data Access
+title: Hourly Data | Datasets
sidebar_label: Hourly Data
sidebar_position: 1
---
diff --git a/docs/data/timeseries/monthly.md b/docs/data/timeseries/monthly.md
index 35d72a0..c91bff8 100644
--- a/docs/data/timeseries/monthly.md
+++ b/docs/data/timeseries/monthly.md
@@ -1,5 +1,5 @@
---
-title: Monthly Data | Data Access
+title: Monthly Data | Datasets
sidebar_label: Monthly Data
sidebar_position: 3
---
diff --git a/docs/data/timeseries/overview.md b/docs/data/timeseries/overview.md
index b5348ff..e1e0662 100644
--- a/docs/data/timeseries/overview.md
+++ b/docs/data/timeseries/overview.md
@@ -1,5 +1,5 @@
---
-title: Time Series | Data Access
+title: Time Series | Datasets
sidebar_label: Overview
id: data-timeseries-overview
slug: /data/timeseries
@@ -12,7 +12,7 @@ import DocCardList from '@theme/DocCardList';
Meteostat provides access to full time series data dumps of individual weather stations. The data is provided in CSV format. Users are **not required to sign up** for this service.
-## 🔌 Access
+## 🔌 Access {#access}
This interface does not require an API key. However, when using this service you must comply with our [terms of service](/terms). Please make sure to cache data if possible and forbear from sending malicious calls to this service.
@@ -26,7 +26,7 @@ Data is available in three different granularities:
The dumps of weather stations which didn't report data for the requested granularity or data type will return an HTTP `404` status code.
:::
-## 🚀 Quick Start
+## 🚀 Quick Start {#quick-start}
The download of annual data dumps is dead simple and doesn’t even require an API key:
@@ -36,10 +36,31 @@ curl "https://data.meteostat.net/hourly/2024/10637.csv.gz" --output "10637-2024.
With our [Python library](/python/) we're providing a simple, yet powerful, wrapper for data dumps. If you're into more complex analysis you should definitely have a look at it.
-## 🔄 Update Cycle
+## 🔄 Update Cycle {#update-cycle}
To keep the load on our infrastructure as low as possible, Meteostat updates data dumps individually for each weather station. The dumps are updated regularly, depending on the granularity of records. Recent hourly data should be available after a maximum of 24 hours.
+## 📚 Specification {#specification}
+
+:::tip
+We recommend using [Meteostat Python](/python) for accessing this dataset.
+:::
+
+This dataset **is not versioned**. Therefore, clients **must be able to handle changes in the data structure**.
+
+- New columns may be added to the datasets **without prior notice**.
+- The order of columns may change **without prior notice**.
+- Existing columns may be removed or renamed with a **minimum 90-day notice**.
+- Breaking changes will be announced ahead of time in the [changelog](#changelog).
+
+:::warning
+CSV readers that rely on the order of columns may break when new columns are added or existing columns are removed. Therefore, it is recommended to use column names instead of column indices when accessing data.
+:::
+
+## 📝 Changelog {#changelog}
+
+No changes have been made to this dataset so far.
+
## 👀 Learn More {#learn-more}
diff --git a/docs/data/weather-stations.md b/docs/data/weather-stations.md
index 872e9cc..d559948 100644
--- a/docs/data/weather-stations.md
+++ b/docs/data/weather-stations.md
@@ -1,5 +1,5 @@
---
-title: Weather Stations | Data Access
+title: Weather Stations | Datasets
sidebar_label: Weather Stations
sidebar_position: 4
---
diff --git a/docs/faq.md b/docs/faq.md
index 04f3ddc..f3153fa 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -41,7 +41,7 @@ Meteostat is not a public or governmental service, and it is not affiliated with
Under which license is Meteostat data distributed?
-Meteostat data is distributed under the terms of the CC BY-NC 4.0 license. See [Terms](/terms) for details.
+Meteostat data is distributed under the terms of the CC BY 4.0 license. See [License](/license) for details.
diff --git a/docs/overview.md b/docs/overview.md
index 34d7d7d..6232bde 100644
--- a/docs/overview.md
+++ b/docs/overview.md
@@ -7,14 +7,26 @@ sidebar_position: 1
Meteostat is a leading provider of open weather and climate data. Access long-term time series from thousands of weather stations and integrate Meteostat data into products, applications, and workflows. With an open-data policy, Meteostat is well suited for research, education, and commercial projects.
-## Our services
-
-Meteostat provides several interfaces for retrieving weather and climate data. Choose the option that fits your use case:
-
-- [JSON API](/api/): Simple, fast access to Meteostat data in JSON format.
-- [Python Library](/python/): Analyze historical weather data for thousands of stations with Pandas.
-- [Command Line Interface](/cli/): Access Meteostat data directly from your terminal.
-- [Data Access](/data/): Download full data dumps for individual weather stations or access data in bulk.
+## Our Services
+
+Meteostat provides several interfaces for retrieving weather and climate data. [**Meteostat Python**](/python/) is the library at the core of it all — the [**API**](/api/) and [**CLI**](/cli/) are both built on top of it. The underlying [**Datasets**](/data/) can also be accessed directly. Pick whichever entry point fits your use case, or click a node below to jump straight to its docs:
+
+```mermaid
+flowchart LR
+ Python(["Meteostat Python
Analyze data with Pandas"])
+ Datasets[("Meteostat Datasets
Download data dumps")]
+ API["Meteostat API
JSON access over HTTP"]
+ CLI["Meteostat CLI
Query data from your terminal"]
+
+ API --> Python
+ CLI --> Python
+ Python --> Datasets
+
+ click Python "/python" "Meteostat Python docs"
+ click Datasets "/data" "Meteostat Datasets docs"
+ click API "/api" "Meteostat API docs"
+ click CLI "/cli" "Meteostat CLI docs"
+```
## About Meteostat
diff --git a/docs/python/overview.md b/docs/python/overview.md
index 56db703..0576f1d 100644
--- a/docs/python/overview.md
+++ b/docs/python/overview.md
@@ -10,7 +10,7 @@ import DocCardList from '@theme/DocCardList';
# Meteostat Python
-The Meteostat Python library offers an easy and efficient way to access open weather and climate data through Pandas. It retrieves historical observations and statistics from Meteostat’s [data access interface](/data), which aggregates information from various public sources — primarily governmental agencies. Among Meteostat’s data providers are national weather services such as the **National Oceanic and Atmospheric Administration (NOAA)** and **Germany’s Meteorological Service (DWD)**.
+The Meteostat Python library offers an easy and efficient way to access open weather and climate data through Pandas. It retrieves historical observations and statistics from [Meteostat Datasets](/data), which aggregates information from various public sources — primarily governmental agencies. Among Meteostat’s data providers are national weather services such as the **National Oceanic and Atmospheric Administration (NOAA)** and **Germany’s Meteorological Service (DWD)**.
## 📚 Installation
diff --git a/docs/terms.md b/docs/terms.md
index a74c486..fa03434 100644
--- a/docs/terms.md
+++ b/docs/terms.md
@@ -4,7 +4,7 @@ sidebar_position: 3
# Terms
-The following terms of service apply when using the Meteostat Python library, the Meteostat JSON API, the Meteostat CLI or the Meteostat data access interface (the “services”). Please review the terms and [license](/license) carefully. By accessing or using the services, you signify your agreement to these terms.
+The following terms of service apply when using the Meteostat Python library, the Meteostat JSON API, the Meteostat CLI or Meteostat Datasets (the “services”). Please review the terms and [license](/license) carefully. By accessing or using the services, you signify your agreement to these terms.
If you do not agree to the terms, you may not access or use the services provided by Meteostat.
diff --git a/docusaurus.config.ts b/docusaurus.config.ts
index 09f3995..4c04f65 100644
--- a/docusaurus.config.ts
+++ b/docusaurus.config.ts
@@ -32,6 +32,10 @@ const config: Config = {
onBrokenLinks: "throw",
onBrokenMarkdownLinks: "warn",
+ markdown: {
+ mermaid: true,
+ },
+
// Even if you don't use internationalization, you can use this field to set
// useful metadata like html lang. For example, if your site is Chinese, you
// may want to replace "en" with "zh-Hans".
@@ -84,7 +88,15 @@ const config: Config = {
plugins: ["docusaurus-plugin-matomo", "./src/plugins/docTagsPlugin.ts"],
+ themes: ["@docusaurus/theme-mermaid"],
+
themeConfig: {
+ mermaid: {
+ theme: { light: "neutral", dark: "dark" },
+ options: {
+ securityLevel: "loose",
+ },
+ },
// Replace with your project's social card
image: "img/meteostat-social-card.jpg",
algolia: {
@@ -132,7 +144,7 @@ const config: Config = {
type: "docSidebar",
sidebarId: "dataSidebar",
position: "left",
- label: "Data",
+ label: "Datasets",
},
{
type: "docSidebar",
@@ -176,7 +188,7 @@ const config: Config = {
to: "/cli",
},
{
- label: "Data Access",
+ label: "Datasets",
to: "/data",
},
{
diff --git a/package-lock.json b/package-lock.json
index 203b297..117163b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,7 @@
"dependencies": {
"@docusaurus/core": "3.8.1",
"@docusaurus/preset-classic": "3.8.1",
+ "@docusaurus/theme-mermaid": "^3.8.1",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"docusaurus-plugin-matomo": "^0.0.8",
@@ -252,6 +253,19 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@antfu/install-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz",
+ "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==",
+ "license": "MIT",
+ "dependencies": {
+ "package-manager-detector": "^1.3.0",
+ "tinyexec": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
"node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
@@ -1817,6 +1831,18 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@braintree/sanitize-url": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz",
+ "integrity": "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==",
+ "license": "MIT"
+ },
+ "node_modules/@chevrotain/types": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.2.tgz",
+ "integrity": "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==",
+ "license": "Apache-2.0"
+ },
"node_modules/@colors/colors": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
@@ -3481,6 +3507,28 @@
"react-dom": "^18.0.0 || ^19.0.0"
}
},
+ "node_modules/@docusaurus/theme-mermaid": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.8.1.tgz",
+ "integrity": "sha512-IWYqjyTPjkNnHsFFu9+4YkeXS7PD1xI3Bn2shOhBq+f95mgDfWInkpfBN4aYvx4fTT67Am6cPtohRdwh4Tidtg==",
+ "license": "MIT",
+ "dependencies": {
+ "@docusaurus/core": "3.8.1",
+ "@docusaurus/module-type-aliases": "3.8.1",
+ "@docusaurus/theme-common": "3.8.1",
+ "@docusaurus/types": "3.8.1",
+ "@docusaurus/utils-validation": "3.8.1",
+ "mermaid": ">=11.6.0",
+ "tslib": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=18.0"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/@docusaurus/theme-search-algolia": {
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.8.1.tgz",
@@ -3636,6 +3684,23 @@
"@hapi/hoek": "^9.0.0"
}
},
+ "node_modules/@iconify/types": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
+ "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
+ "license": "MIT"
+ },
+ "node_modules/@iconify/utils": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.4.tgz",
+ "integrity": "sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==",
+ "license": "MIT",
+ "dependencies": {
+ "@antfu/install-pkg": "^1.1.0",
+ "@iconify/types": "^2.0.0",
+ "import-meta-resolve": "^4.2.0"
+ }
+ },
"node_modules/@jest/schemas": {
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
@@ -3771,6 +3836,15 @@
"react": ">=16"
}
},
+ "node_modules/@mermaid-js/parser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.2.0.tgz",
+ "integrity": "sha512-oYPyv8A4As1yH5Bx+04iQEQxXuIQDe0GKCNSRgao6z8AM9jixXIfP0vsppRLvGf+nKIOb9/LdpWA4YuJiVvESA==",
+ "license": "MIT",
+ "dependencies": {
+ "@chevrotain/types": "~11.1.2"
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -4185,6 +4259,259 @@
"@types/node": "*"
}
},
+ "node_modules/@types/d3": {
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz",
+ "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-array": "*",
+ "@types/d3-axis": "*",
+ "@types/d3-brush": "*",
+ "@types/d3-chord": "*",
+ "@types/d3-color": "*",
+ "@types/d3-contour": "*",
+ "@types/d3-delaunay": "*",
+ "@types/d3-dispatch": "*",
+ "@types/d3-drag": "*",
+ "@types/d3-dsv": "*",
+ "@types/d3-ease": "*",
+ "@types/d3-fetch": "*",
+ "@types/d3-force": "*",
+ "@types/d3-format": "*",
+ "@types/d3-geo": "*",
+ "@types/d3-hierarchy": "*",
+ "@types/d3-interpolate": "*",
+ "@types/d3-path": "*",
+ "@types/d3-polygon": "*",
+ "@types/d3-quadtree": "*",
+ "@types/d3-random": "*",
+ "@types/d3-scale": "*",
+ "@types/d3-scale-chromatic": "*",
+ "@types/d3-selection": "*",
+ "@types/d3-shape": "*",
+ "@types/d3-time": "*",
+ "@types/d3-time-format": "*",
+ "@types/d3-timer": "*",
+ "@types/d3-transition": "*",
+ "@types/d3-zoom": "*"
+ }
+ },
+ "node_modules/@types/d3-array": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz",
+ "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-axis": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz",
+ "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-brush": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz",
+ "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-chord": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz",
+ "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-color": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
+ "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-contour": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz",
+ "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-array": "*",
+ "@types/geojson": "*"
+ }
+ },
+ "node_modules/@types/d3-delaunay": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
+ "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-dispatch": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz",
+ "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-drag": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz",
+ "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-dsv": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz",
+ "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-ease": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
+ "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-fetch": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz",
+ "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-dsv": "*"
+ }
+ },
+ "node_modules/@types/d3-force": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz",
+ "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-format": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz",
+ "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-geo": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz",
+ "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/geojson": "*"
+ }
+ },
+ "node_modules/@types/d3-hierarchy": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz",
+ "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-interpolate": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
+ "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-color": "*"
+ }
+ },
+ "node_modules/@types/d3-path": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
+ "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-polygon": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz",
+ "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-quadtree": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz",
+ "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-random": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.4.tgz",
+ "integrity": "sha512-UHYId5WTCx4L4YNel7NU00XUXXgvgpgZOvp10PuvsQENjMDXhh2RyFc0KBjO7B45ne4Ha1yVH7ii0vnzKkuzWA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-scale": {
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
+ "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-time": "*"
+ }
+ },
+ "node_modules/@types/d3-scale-chromatic": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
+ "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-selection": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz",
+ "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-shape": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz",
+ "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-path": "*"
+ }
+ },
+ "node_modules/@types/d3-time": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
+ "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-time-format": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz",
+ "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-timer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-transition": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz",
+ "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "node_modules/@types/d3-zoom": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz",
+ "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-interpolate": "*",
+ "@types/d3-selection": "*"
+ }
+ },
"node_modules/@types/debug": {
"version": "4.1.12",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
@@ -4257,6 +4584,12 @@
"@types/send": "*"
}
},
+ "node_modules/@types/geojson": {
+ "version": "7946.0.16",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
+ "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
+ "license": "MIT"
+ },
"node_modules/@types/gtag.js": {
"version": "0.0.12",
"resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz",
@@ -4463,6 +4796,13 @@
"@types/node": "*"
}
},
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/@types/unist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
@@ -4494,6 +4834,16 @@
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
"integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="
},
+ "node_modules/@upsetjs/venn.js": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@upsetjs/venn.js/-/venn.js-2.0.0.tgz",
+ "integrity": "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==",
+ "license": "MIT",
+ "optionalDependencies": {
+ "d3-selection": "^3.0.0",
+ "d3-transition": "^3.0.1"
+ }
+ },
"node_modules/@webassemblyjs/ast": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
@@ -5899,6 +6249,15 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
+ "node_modules/cose-base": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz",
+ "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==",
+ "license": "MIT",
+ "dependencies": {
+ "layout-base": "^1.0.0"
+ }
+ },
"node_modules/cosmiconfig": {
"version": "8.3.6",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
@@ -6358,6 +6717,532 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
+ "node_modules/cytoscape": {
+ "version": "3.34.0",
+ "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.34.0.tgz",
+ "integrity": "sha512-62rNSrioXw93uliKFBwjukeQyeWwH2PqDrTac31r2P6464u3AUvTk0xS4LVvT251g7IgkFunrI48ZEZGjywSOg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/cytoscape-cose-bilkent": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz",
+ "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cose-base": "^1.0.0"
+ },
+ "peerDependencies": {
+ "cytoscape": "^3.2.0"
+ }
+ },
+ "node_modules/cytoscape-fcose": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz",
+ "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cose-base": "^2.2.0"
+ },
+ "peerDependencies": {
+ "cytoscape": "^3.2.0"
+ }
+ },
+ "node_modules/cytoscape-fcose/node_modules/cose-base": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz",
+ "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==",
+ "license": "MIT",
+ "dependencies": {
+ "layout-base": "^2.0.0"
+ }
+ },
+ "node_modules/cytoscape-fcose/node_modules/layout-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz",
+ "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==",
+ "license": "MIT"
+ },
+ "node_modules/d3": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz",
+ "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "3",
+ "d3-axis": "3",
+ "d3-brush": "3",
+ "d3-chord": "3",
+ "d3-color": "3",
+ "d3-contour": "4",
+ "d3-delaunay": "6",
+ "d3-dispatch": "3",
+ "d3-drag": "3",
+ "d3-dsv": "3",
+ "d3-ease": "3",
+ "d3-fetch": "3",
+ "d3-force": "3",
+ "d3-format": "3",
+ "d3-geo": "3",
+ "d3-hierarchy": "3",
+ "d3-interpolate": "3",
+ "d3-path": "3",
+ "d3-polygon": "3",
+ "d3-quadtree": "3",
+ "d3-random": "3",
+ "d3-scale": "4",
+ "d3-scale-chromatic": "3",
+ "d3-selection": "3",
+ "d3-shape": "3",
+ "d3-time": "3",
+ "d3-time-format": "4",
+ "d3-timer": "3",
+ "d3-transition": "3",
+ "d3-zoom": "3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-array": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+ "license": "ISC",
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-axis": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz",
+ "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-brush": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz",
+ "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-drag": "2 - 3",
+ "d3-interpolate": "1 - 3",
+ "d3-selection": "3",
+ "d3-transition": "3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-chord": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz",
+ "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-path": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-contour": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz",
+ "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "^3.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-delaunay": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
+ "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
+ "license": "ISC",
+ "dependencies": {
+ "delaunator": "5"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dispatch": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
+ "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-drag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
+ "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-selection": "3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dsv": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
+ "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
+ "license": "ISC",
+ "dependencies": {
+ "commander": "7",
+ "iconv-lite": "0.6",
+ "rw": "1"
+ },
+ "bin": {
+ "csv2json": "bin/dsv2json.js",
+ "csv2tsv": "bin/dsv2dsv.js",
+ "dsv2dsv": "bin/dsv2dsv.js",
+ "dsv2json": "bin/dsv2json.js",
+ "json2csv": "bin/json2dsv.js",
+ "json2dsv": "bin/json2dsv.js",
+ "json2tsv": "bin/json2dsv.js",
+ "tsv2csv": "bin/dsv2dsv.js",
+ "tsv2json": "bin/dsv2json.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dsv/node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/d3-dsv/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/d3-ease": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+ "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-fetch": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz",
+ "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dsv": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-force": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
+ "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-quadtree": "1 - 3",
+ "d3-timer": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz",
+ "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-geo": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz",
+ "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2.5.0 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-hierarchy": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
+ "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-color": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-polygon": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz",
+ "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-quadtree": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
+ "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-random": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz",
+ "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-sankey": {
+ "version": "0.12.3",
+ "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz",
+ "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "d3-array": "1 - 2",
+ "d3-shape": "^1.2.0"
+ }
+ },
+ "node_modules/d3-sankey/node_modules/d3-array": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
+ "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "internmap": "^1.0.0"
+ }
+ },
+ "node_modules/d3-sankey/node_modules/d3-path": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
+ "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/d3-sankey/node_modules/d3-shape": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
+ "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "d3-path": "1"
+ }
+ },
+ "node_modules/d3-sankey/node_modules/internmap": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz",
+ "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==",
+ "license": "ISC"
+ },
+ "node_modules/d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale-chromatic": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
+ "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-color": "1 - 3",
+ "d3-interpolate": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-selection": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
+ "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-path": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time-format": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-time": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-transition": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
+ "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-color": "1 - 3",
+ "d3-dispatch": "1 - 3",
+ "d3-ease": "1 - 3",
+ "d3-interpolate": "1 - 3",
+ "d3-timer": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "d3-selection": "2 - 3"
+ }
+ },
+ "node_modules/d3-zoom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
+ "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-drag": "2 - 3",
+ "d3-interpolate": "1 - 3",
+ "d3-selection": "2 - 3",
+ "d3-transition": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/dagre-d3-es": {
+ "version": "7.0.14",
+ "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.14.tgz",
+ "integrity": "sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==",
+ "license": "MIT",
+ "dependencies": {
+ "d3": "^7.9.0",
+ "lodash-es": "^4.17.21"
+ }
+ },
+ "node_modules/dayjs": {
+ "version": "1.11.21",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz",
+ "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==",
+ "license": "MIT"
+ },
"node_modules/debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
@@ -6491,6 +7376,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/delaunator": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz",
+ "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==",
+ "license": "ISC",
+ "dependencies": {
+ "robust-predicates": "^3.0.2"
+ }
+ },
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -6629,6 +7523,15 @@
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
+ "node_modules/dompurify": {
+ "version": "3.4.12",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.12.tgz",
+ "integrity": "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==",
+ "license": "(MPL-2.0 OR Apache-2.0)",
+ "optionalDependencies": {
+ "@types/trusted-types": "^2.0.7"
+ }
+ },
"node_modules/domutils": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
@@ -6804,6 +7707,16 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-toolkit": {
+ "version": "1.49.0",
+ "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.49.0.tgz",
+ "integrity": "sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==",
+ "license": "MIT",
+ "workspaces": [
+ "docs",
+ "benchmarks"
+ ]
+ },
"node_modules/esast-util-from-estree": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz",
@@ -7781,6 +8694,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/hachure-fill": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz",
+ "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==",
+ "license": "MIT"
+ },
"node_modules/handle-thing": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
@@ -8379,6 +9298,16 @@
"node": ">=8"
}
},
+ "node_modules/import-meta-resolve": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz",
+ "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -8431,6 +9360,15 @@
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz",
"integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q=="
},
+ "node_modules/internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@@ -8838,6 +9776,31 @@
"graceful-fs": "^4.1.6"
}
},
+ "node_modules/katex": {
+ "version": "0.16.47",
+ "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
+ "integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
+ "funding": [
+ "https://opencollective.com/katex",
+ "https://github.com/sponsors/katex"
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^8.3.0"
+ },
+ "bin": {
+ "katex": "cli.js"
+ }
+ },
+ "node_modules/katex/node_modules/commander": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -8846,6 +9809,11 @@
"json-buffer": "3.0.1"
}
},
+ "node_modules/khroma": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz",
+ "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="
+ },
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -8885,6 +9853,12 @@
"shell-quote": "^1.8.1"
}
},
+ "node_modules/layout-base": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz",
+ "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==",
+ "license": "MIT"
+ },
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -8949,6 +9923,12 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
+ "node_modules/lodash-es": {
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
+ "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
+ "license": "MIT"
+ },
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -9031,6 +10011,18 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/marked": {
+ "version": "16.4.2",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz",
+ "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==",
+ "license": "MIT",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 20"
+ }
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -9463,6 +10455,48 @@
"node": ">= 8"
}
},
+ "node_modules/mermaid": {
+ "version": "11.16.0",
+ "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.16.0.tgz",
+ "integrity": "sha512-Zvm3kbstgdpvIJPPItlL7fppIZ3kibvc1oZIGxdvk9t6UFz6flv+Jw7FtRGKwfcI8OckmH04LqG6LlS6X4B1pA==",
+ "license": "MIT",
+ "dependencies": {
+ "@braintree/sanitize-url": "^7.1.2",
+ "@iconify/utils": "^3.0.2",
+ "@mermaid-js/parser": "^1.2.0",
+ "@types/d3": "^7.4.3",
+ "@upsetjs/venn.js": "^2.0.0",
+ "cytoscape": "^3.33.3",
+ "cytoscape-cose-bilkent": "^4.1.0",
+ "cytoscape-fcose": "^2.2.0",
+ "d3": "^7.9.0",
+ "d3-sankey": "^0.12.3",
+ "dagre-d3-es": "7.0.14",
+ "dayjs": "^1.11.20",
+ "dompurify": "^3.3.3",
+ "es-toolkit": "^1.45.1",
+ "katex": "^0.16.45",
+ "khroma": "^2.1.0",
+ "marked": "^16.3.0",
+ "roughjs": "^4.6.6",
+ "stylis": "^4.3.6",
+ "ts-dedent": "^2.2.0",
+ "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0"
+ }
+ },
+ "node_modules/mermaid/node_modules/uuid": {
+ "version": "14.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz",
+ "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist-node/bin/uuid"
+ }
+ },
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
@@ -11703,6 +12737,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/package-manager-detector": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.7.0.tgz",
+ "integrity": "sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==",
+ "license": "MIT"
+ },
"node_modules/param-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
@@ -11819,6 +12859,12 @@
"tslib": "^2.0.3"
}
},
+ "node_modules/path-data-parser": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz",
+ "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==",
+ "license": "MIT"
+ },
"node_modules/path-exists": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
@@ -11899,6 +12945,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/points-on-curve": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz",
+ "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==",
+ "license": "MIT"
+ },
+ "node_modules/points-on-path": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz",
+ "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==",
+ "license": "MIT",
+ "dependencies": {
+ "path-data-parser": "0.1.0",
+ "points-on-curve": "0.2.0"
+ }
+ },
"node_modules/postcss": {
"version": "8.5.4",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz",
@@ -14167,6 +15229,24 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/robust-predicates": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz",
+ "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==",
+ "license": "Unlicense"
+ },
+ "node_modules/roughjs": {
+ "version": "4.6.6",
+ "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz",
+ "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==",
+ "license": "MIT",
+ "dependencies": {
+ "hachure-fill": "^0.5.2",
+ "path-data-parser": "^0.1.0",
+ "points-on-curve": "^0.2.0",
+ "points-on-path": "^0.2.1"
+ }
+ },
"node_modules/rtlcss": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.3.0.tgz",
@@ -14206,6 +15286,12 @@
"queue-microtask": "^1.2.2"
}
},
+ "node_modules/rw": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
+ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -14956,6 +16042,12 @@
"postcss": "^8.4.31"
}
},
+ "node_modules/stylis": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz",
+ "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==",
+ "license": "MIT"
+ },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -15120,6 +16212,15 @@
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
},
+ "node_modules/tinyexec": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz",
+ "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/tinypool": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.0.tgz",
@@ -15173,6 +16274,15 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/ts-dedent": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.3.0.tgz",
+ "integrity": "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.10"
+ }
+ },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
diff --git a/package.json b/package.json
index c0d6828..e3ce1bb 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"dependencies": {
"@docusaurus/core": "3.8.1",
"@docusaurus/preset-classic": "3.8.1",
+ "@docusaurus/theme-mermaid": "^3.8.1",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"docusaurus-plugin-matomo": "^0.0.8",
diff --git a/src/components/HomepageFeatures/index.tsx b/src/components/HomepageFeatures/index.tsx
index 8f44f89..32c2d2e 100644
--- a/src/components/HomepageFeatures/index.tsx
+++ b/src/components/HomepageFeatures/index.tsx
@@ -24,7 +24,7 @@ const FeatureList: FeatureItem[] = [
),
},
{
- title: "Data Access",
+ title: "Datasets",
to: "/data",
Svg: require("@site/static/img/undraw_visual-data_1eya.svg").default,
description: (
diff --git a/src/theme/DocBreadcrumbs/useSidebarBreadcrumbsWithContext.ts b/src/theme/DocBreadcrumbs/useSidebarBreadcrumbsWithContext.ts
index 4913c80..c69c952 100644
--- a/src/theme/DocBreadcrumbs/useSidebarBreadcrumbsWithContext.ts
+++ b/src/theme/DocBreadcrumbs/useSidebarBreadcrumbsWithContext.ts
@@ -4,7 +4,7 @@ import { useLocation } from "@docusaurus/router";
const CONTEXT_MAP = {
data: {
- label: "Data Access",
+ label: "Datasets",
href: "/data",
},
python: {