/ concept-collection / benchcompress
Sign in
concept-collection / benchcompress
ui improvements
Jeremy Magland <jmagland@flatironinstitute.org> committed commit 0602a7ea78b5 parent d824abc Browse files
21 changed files+1654−96
.vscode/tasks.jsonmodified+11−0View file
@@ -1,6 +1,17 @@
11 {
22 "version": "2.0.0",
33 "tasks": [
4+ {
5+ "label": "Generate Posts Index",
6+ "type": "shell",
7+ "command": "./devel/generate_posts_index.sh",
8+ "group": "build",
9+ "presentation": {
10+ "reveal": "silent",
11+ "panel": "shared"
12+ },
13+ "problemMatcher": []
14+ },
415 {
516 "label": "Format Code",
617 "type": "shell",
README.mdmodified+2−3View file
@@ -2,6 +2,8 @@
22
33 A benchmarking framework for evaluating compression algorithms on numeric array datasets, with a focus on scientific data.
44
5+Latest benchmark results: https://magland.github.io/zia/
6+
57 ## Overview
68
79 Zia provides systematic benchmarking of compression methods for numeric arrays, measuring:
@@ -52,6 +54,3 @@ pre-commit install
5254
5355 After this setup, code will be automatically formatted when you make a commit.
5456
55-## Results
56-
57-Latest benchmark results: https://magland.github.io/zia/
devel/check_format.shmodified+6−2View file
@@ -1,8 +1,12 @@
11 #!/bin/bash
22
3+# Get the directory where the script is located
4+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
5+PROJECT_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )"
6+
37 # Check Python code formatting
48 echo "Checking Python code formatting..."
5-if ! black --check zia_benchmark/src/zia_benchmark; then
9+if ! black --check "$PROJECT_ROOT/zia_benchmark/src/zia_benchmark"; then
610 echo "Python code is not properly formatted!"
711 echo "Please run './devel/format_code.sh' to format the code"
812 exit 1
@@ -10,7 +14,7 @@ fi
1014
1115 # Check TypeScript/JavaScript code formatting
1216 echo "Checking TypeScript/JavaScript code formatting..."
13-cd web-ui
17+cd "$PROJECT_ROOT/web-ui"
1418 if ! npm run format:check; then
1519 echo "TypeScript/JavaScript code is not properly formatted!"
1620 echo "Please run './devel/format_code.sh' to format the code"
devel/format_code.shmodified+6−2View file
@@ -1,11 +1,15 @@
11 #!/bin/bash
22
3+# Get the directory where the script is located
4+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
5+PROJECT_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )"
6+
37 # Format Python code
48 echo "Formatting Python code..."
5-black zia_benchmark/src/zia_benchmark
9+black "$PROJECT_ROOT/zia_benchmark/src/zia_benchmark"
610
711 # Format TypeScript/JavaScript code
812 echo "Formatting TypeScript/JavaScript code..."
9-cd web-ui && npm run format
13+cd "$PROJECT_ROOT/web-ui" && npm run format
1014
1115 echo "Code formatting complete!"
devel/generate_posts_index.shadded+16−0View file
@@ -0,0 +1,16 @@
1+#!/bin/bash
2+
3+# Directory containing this script
4+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
5+
6+# Path to the posts directory relative to the script location
7+POSTS_DIR="$SCRIPT_DIR/../web-ui/public/posts"
8+INDEX_FILE="$POSTS_DIR/index.txt"
9+
10+# Create posts directory if it doesn't exist
11+mkdir -p "$POSTS_DIR"
12+
13+# Find all .md files in the posts directory and write to index.txt
14+find "$POSTS_DIR" -maxdepth 1 -name "*.md" -type f -printf "%f\n" | sort > "$INDEX_FILE"
15+
16+echo "Generated posts index at $INDEX_FILE"
web-ui/package-lock.jsonmodified+1089−6View file
@@ -14,6 +14,7 @@
1414 "plotly.js-dist-min": "^2.35.3",
1515 "react": "^18.3.1",
1616 "react-dom": "^18.3.1",
17+ "react-markdown": "^9.0.3",
1718 "react-plotly.js": "^2.6.0",
1819 "react-router-dom": "^7.1.3"
1920 },
@@ -1584,6 +1585,14 @@
15841585 "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
15851586 "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="
15861587 },
1588+ "node_modules/@types/debug": {
1589+ "version": "4.1.12",
1590+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
1591+ "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
1592+ "dependencies": {
1593+ "@types/ms": "*"
1594+ }
1595+ },
15871596 "node_modules/@types/eslint": {
15881597 "version": "9.6.1",
15891598 "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
@@ -1609,6 +1618,14 @@
16091618 "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
16101619 "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
16111620 },
1621+ "node_modules/@types/estree-jsx": {
1622+ "version": "1.0.5",
1623+ "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz",
1624+ "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==",
1625+ "dependencies": {
1626+ "@types/estree": "*"
1627+ }
1628+ },
16121629 "node_modules/@types/geojson": {
16131630 "version": "7946.0.16",
16141631 "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
@@ -1624,6 +1641,14 @@
16241641 "@types/geojson": "*"
16251642 }
16261643 },
1644+ "node_modules/@types/hast": {
1645+ "version": "3.0.4",
1646+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
1647+ "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
1648+ "dependencies": {
1649+ "@types/unist": "*"
1650+ }
1651+ },
16271652 "node_modules/@types/json-schema": {
16281653 "version": "7.0.15",
16291654 "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@@ -1646,6 +1671,19 @@
16461671 "@types/pbf": "*"
16471672 }
16481673 },
1674+ "node_modules/@types/mdast": {
1675+ "version": "4.0.4",
1676+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
1677+ "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
1678+ "dependencies": {
1679+ "@types/unist": "*"
1680+ }
1681+ },
1682+ "node_modules/@types/ms": {
1683+ "version": "2.1.0",
1684+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
1685+ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="
1686+ },
16491687 "node_modules/@types/node": {
16501688 "version": "22.10.10",
16511689 "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.10.tgz",
@@ -1669,14 +1707,12 @@
16691707 "node_modules/@types/prop-types": {
16701708 "version": "15.7.14",
16711709 "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
1672- "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==",
1673- "dev": true
1710+ "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ=="
16741711 },
16751712 "node_modules/@types/react": {
16761713 "version": "18.3.18",
16771714 "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz",
16781715 "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==",
1679- "dev": true,
16801716 "dependencies": {
16811717 "@types/prop-types": "*",
16821718 "csstype": "^3.0.2"
@@ -1710,6 +1746,11 @@
17101746 "@types/geojson": "*"
17111747 }
17121748 },
1749+ "node_modules/@types/unist": {
1750+ "version": "3.0.3",
1751+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
1752+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="
1753+ },
17131754 "node_modules/@typescript-eslint/eslint-plugin": {
17141755 "version": "8.21.0",
17151756 "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.21.0.tgz",
@@ -1918,6 +1959,11 @@
19181959 "url": "https://opencollective.com/typescript-eslint"
19191960 }
19201961 },
1962+ "node_modules/@ungap/structured-clone": {
1963+ "version": "1.3.0",
1964+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
1965+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="
1966+ },
19211967 "node_modules/@vitejs/plugin-react": {
19221968 "version": "4.3.4",
19231969 "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz",
@@ -2299,6 +2345,15 @@
22992345 "proxy-from-env": "^1.1.0"
23002346 }
23012347 },
2348+ "node_modules/bail": {
2349+ "version": "2.0.2",
2350+ "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
2351+ "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
2352+ "funding": {
2353+ "type": "github",
2354+ "url": "https://github.com/sponsors/wooorm"
2355+ }
2356+ },
23022357 "node_modules/balanced-match": {
23032358 "version": "1.0.2",
23042359 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -2438,6 +2493,15 @@
24382493 "element-size": "^1.1.1"
24392494 }
24402495 },
2496+ "node_modules/ccount": {
2497+ "version": "2.0.1",
2498+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
2499+ "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
2500+ "funding": {
2501+ "type": "github",
2502+ "url": "https://github.com/sponsors/wooorm"
2503+ }
2504+ },
24412505 "node_modules/chalk": {
24422506 "version": "4.1.2",
24432507 "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -2454,6 +2518,42 @@
24542518 "url": "https://github.com/chalk/chalk?sponsor=1"
24552519 }
24562520 },
2521+ "node_modules/character-entities": {
2522+ "version": "2.0.2",
2523+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
2524+ "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
2525+ "funding": {
2526+ "type": "github",
2527+ "url": "https://github.com/sponsors/wooorm"
2528+ }
2529+ },
2530+ "node_modules/character-entities-html4": {
2531+ "version": "2.1.0",
2532+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
2533+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
2534+ "funding": {
2535+ "type": "github",
2536+ "url": "https://github.com/sponsors/wooorm"
2537+ }
2538+ },
2539+ "node_modules/character-entities-legacy": {
2540+ "version": "3.0.0",
2541+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
2542+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
2543+ "funding": {
2544+ "type": "github",
2545+ "url": "https://github.com/sponsors/wooorm"
2546+ }
2547+ },
2548+ "node_modules/character-reference-invalid": {
2549+ "version": "2.0.1",
2550+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
2551+ "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
2552+ "funding": {
2553+ "type": "github",
2554+ "url": "https://github.com/sponsors/wooorm"
2555+ }
2556+ },
24572557 "node_modules/chrome-trace-event": {
24582558 "version": "1.0.4",
24592559 "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
@@ -2574,6 +2674,15 @@
25742674 "node": ">= 0.8"
25752675 }
25762676 },
2677+ "node_modules/comma-separated-tokens": {
2678+ "version": "2.0.3",
2679+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
2680+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
2681+ "funding": {
2682+ "type": "github",
2683+ "url": "https://github.com/sponsors/wooorm"
2684+ }
2685+ },
25772686 "node_modules/commander": {
25782687 "version": "2.20.3",
25792688 "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
@@ -2762,8 +2871,7 @@
27622871 "node_modules/csstype": {
27632872 "version": "3.1.3",
27642873 "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
2765- "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
2766- "dev": true
2874+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
27672875 },
27682876 "node_modules/d": {
27692877 "version": "1.0.2",
@@ -2915,7 +3023,6 @@
29153023 "version": "4.4.0",
29163024 "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
29173025 "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
2918- "dev": true,
29193026 "dependencies": {
29203027 "ms": "^2.1.3"
29213028 },
@@ -2928,6 +3035,18 @@
29283035 }
29293036 }
29303037 },
3038+ "node_modules/decode-named-character-reference": {
3039+ "version": "1.0.2",
3040+ "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz",
3041+ "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==",
3042+ "dependencies": {
3043+ "character-entities": "^2.0.0"
3044+ },
3045+ "funding": {
3046+ "type": "github",
3047+ "url": "https://github.com/sponsors/wooorm"
3048+ }
3049+ },
29313050 "node_modules/deep-is": {
29323051 "version": "0.1.4",
29333052 "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -2951,12 +3070,32 @@
29513070 "node": ">=0.4.0"
29523071 }
29533072 },
3073+ "node_modules/dequal": {
3074+ "version": "2.0.3",
3075+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
3076+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
3077+ "engines": {
3078+ "node": ">=6"
3079+ }
3080+ },
29543081 "node_modules/detect-kerning": {
29553082 "version": "2.1.2",
29563083 "resolved": "https://registry.npmjs.org/detect-kerning/-/detect-kerning-2.1.2.tgz",
29573084 "integrity": "sha512-I3JIbrnKPAntNLl1I6TpSQQdQ4AutYzv/sKMFKbepawV/hlH0GmYKhUoOEMd4xqaUHT+Bm0f4127lh5qs1m1tw==",
29583085 "peer": true
29593086 },
3087+ "node_modules/devlop": {
3088+ "version": "1.1.0",
3089+ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
3090+ "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
3091+ "dependencies": {
3092+ "dequal": "^2.0.0"
3093+ },
3094+ "funding": {
3095+ "type": "github",
3096+ "url": "https://github.com/sponsors/wooorm"
3097+ }
3098+ },
29603099 "node_modules/draw-svg-path": {
29613100 "version": "1.0.0",
29623101 "resolved": "https://registry.npmjs.org/draw-svg-path/-/draw-svg-path-1.0.0.tgz",
@@ -3365,6 +3504,15 @@
33653504 "node": ">=4.0"
33663505 }
33673506 },
3507+ "node_modules/estree-util-is-identifier-name": {
3508+ "version": "3.0.0",
3509+ "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz",
3510+ "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==",
3511+ "funding": {
3512+ "type": "opencollective",
3513+ "url": "https://opencollective.com/unified"
3514+ }
3515+ },
33683516 "node_modules/esutils": {
33693517 "version": "2.0.3",
33703518 "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -3401,6 +3549,11 @@
34013549 "type": "^2.7.2"
34023550 }
34033551 },
3552+ "node_modules/extend": {
3553+ "version": "3.0.2",
3554+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
3555+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
3556+ },
34043557 "node_modules/falafel": {
34053558 "version": "2.2.5",
34063559 "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.2.5.tgz",
@@ -4079,12 +4232,59 @@
40794232 "node": ">= 0.4"
40804233 }
40814234 },
4235+ "node_modules/hast-util-to-jsx-runtime": {
4236+ "version": "2.3.2",
4237+ "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.2.tgz",
4238+ "integrity": "sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==",
4239+ "dependencies": {
4240+ "@types/estree": "^1.0.0",
4241+ "@types/hast": "^3.0.0",
4242+ "@types/unist": "^3.0.0",
4243+ "comma-separated-tokens": "^2.0.0",
4244+ "devlop": "^1.0.0",
4245+ "estree-util-is-identifier-name": "^3.0.0",
4246+ "hast-util-whitespace": "^3.0.0",
4247+ "mdast-util-mdx-expression": "^2.0.0",
4248+ "mdast-util-mdx-jsx": "^3.0.0",
4249+ "mdast-util-mdxjs-esm": "^2.0.0",
4250+ "property-information": "^6.0.0",
4251+ "space-separated-tokens": "^2.0.0",
4252+ "style-to-object": "^1.0.0",
4253+ "unist-util-position": "^5.0.0",
4254+ "vfile-message": "^4.0.0"
4255+ },
4256+ "funding": {
4257+ "type": "opencollective",
4258+ "url": "https://opencollective.com/unified"
4259+ }
4260+ },
4261+ "node_modules/hast-util-whitespace": {
4262+ "version": "3.0.0",
4263+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
4264+ "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
4265+ "dependencies": {
4266+ "@types/hast": "^3.0.0"
4267+ },
4268+ "funding": {
4269+ "type": "opencollective",
4270+ "url": "https://opencollective.com/unified"
4271+ }
4272+ },
40824273 "node_modules/hsluv": {
40834274 "version": "0.0.3",
40844275 "resolved": "https://registry.npmjs.org/hsluv/-/hsluv-0.0.3.tgz",
40854276 "integrity": "sha512-08iL2VyCRbkQKBySkSh6m8zMUa3sADAxGVWs3Z1aPcUkTJeK0ETG4Fc27tEmQBGUAXZjIsXOZqBvacuVNSC/fQ==",
40864277 "peer": true
40874278 },
4279+ "node_modules/html-url-attributes": {
4280+ "version": "3.0.1",
4281+ "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
4282+ "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==",
4283+ "funding": {
4284+ "type": "opencollective",
4285+ "url": "https://opencollective.com/unified"
4286+ }
4287+ },
40884288 "node_modules/iconv-lite": {
40894289 "version": "0.4.24",
40904290 "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -4178,6 +4378,33 @@
41784378 "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
41794379 }
41804380 },
4381+ "node_modules/inline-style-parser": {
4382+ "version": "0.2.4",
4383+ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz",
4384+ "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q=="
4385+ },
4386+ "node_modules/is-alphabetical": {
4387+ "version": "2.0.1",
4388+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
4389+ "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==",
4390+ "funding": {
4391+ "type": "github",
4392+ "url": "https://github.com/sponsors/wooorm"
4393+ }
4394+ },
4395+ "node_modules/is-alphanumerical": {
4396+ "version": "2.0.1",
4397+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
4398+ "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
4399+ "dependencies": {
4400+ "is-alphabetical": "^2.0.0",
4401+ "is-decimal": "^2.0.0"
4402+ },
4403+ "funding": {
4404+ "type": "github",
4405+ "url": "https://github.com/sponsors/wooorm"
4406+ }
4407+ },
41814408 "node_modules/is-browser": {
41824409 "version": "2.1.0",
41834410 "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.1.0.tgz",
@@ -4199,6 +4426,15 @@
41994426 "url": "https://github.com/sponsors/ljharb"
42004427 }
42014428 },
4429+ "node_modules/is-decimal": {
4430+ "version": "2.0.1",
4431+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
4432+ "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==",
4433+ "funding": {
4434+ "type": "github",
4435+ "url": "https://github.com/sponsors/wooorm"
4436+ }
4437+ },
42024438 "node_modules/is-extglob": {
42034439 "version": "2.1.1",
42044440 "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -4241,6 +4477,15 @@
42414477 "node": ">=0.10.0"
42424478 }
42434479 },
4480+ "node_modules/is-hexadecimal": {
4481+ "version": "2.0.1",
4482+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz",
4483+ "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==",
4484+ "funding": {
4485+ "type": "github",
4486+ "url": "https://github.com/sponsors/wooorm"
4487+ }
4488+ },
42444489 "node_modules/is-iexplorer": {
42454490 "version": "1.0.0",
42464491 "resolved": "https://registry.npmjs.org/is-iexplorer/-/is-iexplorer-1.0.0.tgz",
@@ -4472,6 +4717,15 @@
44724717 "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
44734718 "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
44744719 },
4720+ "node_modules/longest-streak": {
4721+ "version": "3.1.0",
4722+ "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
4723+ "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==",
4724+ "funding": {
4725+ "type": "github",
4726+ "url": "https://github.com/sponsors/wooorm"
4727+ }
4728+ },
44754729 "node_modules/loose-envify": {
44764730 "version": "1.4.0",
44774731 "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -4644,6 +4898,151 @@
46444898 "node": ">=0.10.0"
46454899 }
46464900 },
4901+ "node_modules/mdast-util-from-markdown": {
4902+ "version": "2.0.2",
4903+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
4904+ "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
4905+ "dependencies": {
4906+ "@types/mdast": "^4.0.0",
4907+ "@types/unist": "^3.0.0",
4908+ "decode-named-character-reference": "^1.0.0",
4909+ "devlop": "^1.0.0",
4910+ "mdast-util-to-string": "^4.0.0",
4911+ "micromark": "^4.0.0",
4912+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
4913+ "micromark-util-decode-string": "^2.0.0",
4914+ "micromark-util-normalize-identifier": "^2.0.0",
4915+ "micromark-util-symbol": "^2.0.0",
4916+ "micromark-util-types": "^2.0.0",
4917+ "unist-util-stringify-position": "^4.0.0"
4918+ },
4919+ "funding": {
4920+ "type": "opencollective",
4921+ "url": "https://opencollective.com/unified"
4922+ }
4923+ },
4924+ "node_modules/mdast-util-mdx-expression": {
4925+ "version": "2.0.1",
4926+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
4927+ "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==",
4928+ "dependencies": {
4929+ "@types/estree-jsx": "^1.0.0",
4930+ "@types/hast": "^3.0.0",
4931+ "@types/mdast": "^4.0.0",
4932+ "devlop": "^1.0.0",
4933+ "mdast-util-from-markdown": "^2.0.0",
4934+ "mdast-util-to-markdown": "^2.0.0"
4935+ },
4936+ "funding": {
4937+ "type": "opencollective",
4938+ "url": "https://opencollective.com/unified"
4939+ }
4940+ },
4941+ "node_modules/mdast-util-mdx-jsx": {
4942+ "version": "3.2.0",
4943+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz",
4944+ "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==",
4945+ "dependencies": {
4946+ "@types/estree-jsx": "^1.0.0",
4947+ "@types/hast": "^3.0.0",
4948+ "@types/mdast": "^4.0.0",
4949+ "@types/unist": "^3.0.0",
4950+ "ccount": "^2.0.0",
4951+ "devlop": "^1.1.0",
4952+ "mdast-util-from-markdown": "^2.0.0",
4953+ "mdast-util-to-markdown": "^2.0.0",
4954+ "parse-entities": "^4.0.0",
4955+ "stringify-entities": "^4.0.0",
4956+ "unist-util-stringify-position": "^4.0.0",
4957+ "vfile-message": "^4.0.0"
4958+ },
4959+ "funding": {
4960+ "type": "opencollective",
4961+ "url": "https://opencollective.com/unified"
4962+ }
4963+ },
4964+ "node_modules/mdast-util-mdxjs-esm": {
4965+ "version": "2.0.1",
4966+ "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz",
4967+ "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==",
4968+ "dependencies": {
4969+ "@types/estree-jsx": "^1.0.0",
4970+ "@types/hast": "^3.0.0",
4971+ "@types/mdast": "^4.0.0",
4972+ "devlop": "^1.0.0",
4973+ "mdast-util-from-markdown": "^2.0.0",
4974+ "mdast-util-to-markdown": "^2.0.0"
4975+ },
4976+ "funding": {
4977+ "type": "opencollective",
4978+ "url": "https://opencollective.com/unified"
4979+ }
4980+ },
4981+ "node_modules/mdast-util-phrasing": {
4982+ "version": "4.1.0",
4983+ "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz",
4984+ "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==",
4985+ "dependencies": {
4986+ "@types/mdast": "^4.0.0",
4987+ "unist-util-is": "^6.0.0"
4988+ },
4989+ "funding": {
4990+ "type": "opencollective",
4991+ "url": "https://opencollective.com/unified"
4992+ }
4993+ },
4994+ "node_modules/mdast-util-to-hast": {
4995+ "version": "13.2.0",
4996+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz",
4997+ "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==",
4998+ "dependencies": {
4999+ "@types/hast": "^3.0.0",
5000+ "@types/mdast": "^4.0.0",
5001+ "@ungap/structured-clone": "^1.0.0",
5002+ "devlop": "^1.0.0",
5003+ "micromark-util-sanitize-uri": "^2.0.0",
5004+ "trim-lines": "^3.0.0",
5005+ "unist-util-position": "^5.0.0",
5006+ "unist-util-visit": "^5.0.0",
5007+ "vfile": "^6.0.0"
5008+ },
5009+ "funding": {
5010+ "type": "opencollective",
5011+ "url": "https://opencollective.com/unified"
5012+ }
5013+ },
5014+ "node_modules/mdast-util-to-markdown": {
5015+ "version": "2.1.2",
5016+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz",
5017+ "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==",
5018+ "dependencies": {
5019+ "@types/mdast": "^4.0.0",
5020+ "@types/unist": "^3.0.0",
5021+ "longest-streak": "^3.0.0",
5022+ "mdast-util-phrasing": "^4.0.0",
5023+ "mdast-util-to-string": "^4.0.0",
5024+ "micromark-util-classify-character": "^2.0.0",
5025+ "micromark-util-decode-string": "^2.0.0",
5026+ "unist-util-visit": "^5.0.0",
5027+ "zwitch": "^2.0.0"
5028+ },
5029+ "funding": {
5030+ "type": "opencollective",
5031+ "url": "https://opencollective.com/unified"
5032+ }
5033+ },
5034+ "node_modules/mdast-util-to-string": {
5035+ "version": "4.0.0",
5036+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
5037+ "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
5038+ "dependencies": {
5039+ "@types/mdast": "^4.0.0"
5040+ },
5041+ "funding": {
5042+ "type": "opencollective",
5043+ "url": "https://opencollective.com/unified"
5044+ }
5045+ },
46475046 "node_modules/merge-stream": {
46485047 "version": "2.0.0",
46495048 "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -4659,6 +5058,427 @@
46595058 "node": ">= 8"
46605059 }
46615060 },
5061+ "node_modules/micromark": {
5062+ "version": "4.0.1",
5063+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.1.tgz",
5064+ "integrity": "sha512-eBPdkcoCNvYcxQOAKAlceo5SNdzZWfF+FcSupREAzdAh9rRmE239CEQAiTwIgblwnoM8zzj35sZ5ZwvSEOF6Kw==",
5065+ "funding": [
5066+ {
5067+ "type": "GitHub Sponsors",
5068+ "url": "https://github.com/sponsors/unifiedjs"
5069+ },
5070+ {
5071+ "type": "OpenCollective",
5072+ "url": "https://opencollective.com/unified"
5073+ }
5074+ ],
5075+ "dependencies": {
5076+ "@types/debug": "^4.0.0",
5077+ "debug": "^4.0.0",
5078+ "decode-named-character-reference": "^1.0.0",
5079+ "devlop": "^1.0.0",
5080+ "micromark-core-commonmark": "^2.0.0",
5081+ "micromark-factory-space": "^2.0.0",
5082+ "micromark-util-character": "^2.0.0",
5083+ "micromark-util-chunked": "^2.0.0",
5084+ "micromark-util-combine-extensions": "^2.0.0",
5085+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
5086+ "micromark-util-encode": "^2.0.0",
5087+ "micromark-util-normalize-identifier": "^2.0.0",
5088+ "micromark-util-resolve-all": "^2.0.0",
5089+ "micromark-util-sanitize-uri": "^2.0.0",
5090+ "micromark-util-subtokenize": "^2.0.0",
5091+ "micromark-util-symbol": "^2.0.0",
5092+ "micromark-util-types": "^2.0.0"
5093+ }
5094+ },
5095+ "node_modules/micromark-core-commonmark": {
5096+ "version": "2.0.2",
5097+ "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.2.tgz",
5098+ "integrity": "sha512-FKjQKbxd1cibWMM1P9N+H8TwlgGgSkWZMmfuVucLCHaYqeSvJ0hFeHsIa65pA2nYbes0f8LDHPMrd9X7Ujxg9w==",
5099+ "funding": [
5100+ {
5101+ "type": "GitHub Sponsors",
5102+ "url": "https://github.com/sponsors/unifiedjs"
5103+ },
5104+ {
5105+ "type": "OpenCollective",
5106+ "url": "https://opencollective.com/unified"
5107+ }
5108+ ],
5109+ "dependencies": {
5110+ "decode-named-character-reference": "^1.0.0",
5111+ "devlop": "^1.0.0",
5112+ "micromark-factory-destination": "^2.0.0",
5113+ "micromark-factory-label": "^2.0.0",
5114+ "micromark-factory-space": "^2.0.0",
5115+ "micromark-factory-title": "^2.0.0",
5116+ "micromark-factory-whitespace": "^2.0.0",
5117+ "micromark-util-character": "^2.0.0",
5118+ "micromark-util-chunked": "^2.0.0",
5119+ "micromark-util-classify-character": "^2.0.0",
5120+ "micromark-util-html-tag-name": "^2.0.0",
5121+ "micromark-util-normalize-identifier": "^2.0.0",
5122+ "micromark-util-resolve-all": "^2.0.0",
5123+ "micromark-util-subtokenize": "^2.0.0",
5124+ "micromark-util-symbol": "^2.0.0",
5125+ "micromark-util-types": "^2.0.0"
5126+ }
5127+ },
5128+ "node_modules/micromark-factory-destination": {
5129+ "version": "2.0.1",
5130+ "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
5131+ "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==",
5132+ "funding": [
5133+ {
5134+ "type": "GitHub Sponsors",
5135+ "url": "https://github.com/sponsors/unifiedjs"
5136+ },
5137+ {
5138+ "type": "OpenCollective",
5139+ "url": "https://opencollective.com/unified"
5140+ }
5141+ ],
5142+ "dependencies": {
5143+ "micromark-util-character": "^2.0.0",
5144+ "micromark-util-symbol": "^2.0.0",
5145+ "micromark-util-types": "^2.0.0"
5146+ }
5147+ },
5148+ "node_modules/micromark-factory-label": {
5149+ "version": "2.0.1",
5150+ "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
5151+ "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==",
5152+ "funding": [
5153+ {
5154+ "type": "GitHub Sponsors",
5155+ "url": "https://github.com/sponsors/unifiedjs"
5156+ },
5157+ {
5158+ "type": "OpenCollective",
5159+ "url": "https://opencollective.com/unified"
5160+ }
5161+ ],
5162+ "dependencies": {
5163+ "devlop": "^1.0.0",
5164+ "micromark-util-character": "^2.0.0",
5165+ "micromark-util-symbol": "^2.0.0",
5166+ "micromark-util-types": "^2.0.0"
5167+ }
5168+ },
5169+ "node_modules/micromark-factory-space": {
5170+ "version": "2.0.1",
5171+ "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
5172+ "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==",
5173+ "funding": [
5174+ {
5175+ "type": "GitHub Sponsors",
5176+ "url": "https://github.com/sponsors/unifiedjs"
5177+ },
5178+ {
5179+ "type": "OpenCollective",
5180+ "url": "https://opencollective.com/unified"
5181+ }
5182+ ],
5183+ "dependencies": {
5184+ "micromark-util-character": "^2.0.0",
5185+ "micromark-util-types": "^2.0.0"
5186+ }
5187+ },
5188+ "node_modules/micromark-factory-title": {
5189+ "version": "2.0.1",
5190+ "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
5191+ "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==",
5192+ "funding": [
5193+ {
5194+ "type": "GitHub Sponsors",
5195+ "url": "https://github.com/sponsors/unifiedjs"
5196+ },
5197+ {
5198+ "type": "OpenCollective",
5199+ "url": "https://opencollective.com/unified"
5200+ }
5201+ ],
5202+ "dependencies": {
5203+ "micromark-factory-space": "^2.0.0",
5204+ "micromark-util-character": "^2.0.0",
5205+ "micromark-util-symbol": "^2.0.0",
5206+ "micromark-util-types": "^2.0.0"
5207+ }
5208+ },
5209+ "node_modules/micromark-factory-whitespace": {
5210+ "version": "2.0.1",
5211+ "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
5212+ "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==",
5213+ "funding": [
5214+ {
5215+ "type": "GitHub Sponsors",
5216+ "url": "https://github.com/sponsors/unifiedjs"
5217+ },
5218+ {
5219+ "type": "OpenCollective",
5220+ "url": "https://opencollective.com/unified"
5221+ }
5222+ ],
5223+ "dependencies": {
5224+ "micromark-factory-space": "^2.0.0",
5225+ "micromark-util-character": "^2.0.0",
5226+ "micromark-util-symbol": "^2.0.0",
5227+ "micromark-util-types": "^2.0.0"
5228+ }
5229+ },
5230+ "node_modules/micromark-util-character": {
5231+ "version": "2.1.1",
5232+ "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
5233+ "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
5234+ "funding": [
5235+ {
5236+ "type": "GitHub Sponsors",
5237+ "url": "https://github.com/sponsors/unifiedjs"
5238+ },
5239+ {
5240+ "type": "OpenCollective",
5241+ "url": "https://opencollective.com/unified"
5242+ }
5243+ ],
5244+ "dependencies": {
5245+ "micromark-util-symbol": "^2.0.0",
5246+ "micromark-util-types": "^2.0.0"
5247+ }
5248+ },
5249+ "node_modules/micromark-util-chunked": {
5250+ "version": "2.0.1",
5251+ "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
5252+ "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==",
5253+ "funding": [
5254+ {
5255+ "type": "GitHub Sponsors",
5256+ "url": "https://github.com/sponsors/unifiedjs"
5257+ },
5258+ {
5259+ "type": "OpenCollective",
5260+ "url": "https://opencollective.com/unified"
5261+ }
5262+ ],
5263+ "dependencies": {
5264+ "micromark-util-symbol": "^2.0.0"
5265+ }
5266+ },
5267+ "node_modules/micromark-util-classify-character": {
5268+ "version": "2.0.1",
5269+ "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
5270+ "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==",
5271+ "funding": [
5272+ {
5273+ "type": "GitHub Sponsors",
5274+ "url": "https://github.com/sponsors/unifiedjs"
5275+ },
5276+ {
5277+ "type": "OpenCollective",
5278+ "url": "https://opencollective.com/unified"
5279+ }
5280+ ],
5281+ "dependencies": {
5282+ "micromark-util-character": "^2.0.0",
5283+ "micromark-util-symbol": "^2.0.0",
5284+ "micromark-util-types": "^2.0.0"
5285+ }
5286+ },
5287+ "node_modules/micromark-util-combine-extensions": {
5288+ "version": "2.0.1",
5289+ "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
5290+ "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==",
5291+ "funding": [
5292+ {
5293+ "type": "GitHub Sponsors",
5294+ "url": "https://github.com/sponsors/unifiedjs"
5295+ },
5296+ {
5297+ "type": "OpenCollective",
5298+ "url": "https://opencollective.com/unified"
5299+ }
5300+ ],
5301+ "dependencies": {
5302+ "micromark-util-chunked": "^2.0.0",
5303+ "micromark-util-types": "^2.0.0"
5304+ }
5305+ },
5306+ "node_modules/micromark-util-decode-numeric-character-reference": {
5307+ "version": "2.0.2",
5308+ "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
5309+ "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==",
5310+ "funding": [
5311+ {
5312+ "type": "GitHub Sponsors",
5313+ "url": "https://github.com/sponsors/unifiedjs"
5314+ },
5315+ {
5316+ "type": "OpenCollective",
5317+ "url": "https://opencollective.com/unified"
5318+ }
5319+ ],
5320+ "dependencies": {
5321+ "micromark-util-symbol": "^2.0.0"
5322+ }
5323+ },
5324+ "node_modules/micromark-util-decode-string": {
5325+ "version": "2.0.1",
5326+ "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz",
5327+ "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==",
5328+ "funding": [
5329+ {
5330+ "type": "GitHub Sponsors",
5331+ "url": "https://github.com/sponsors/unifiedjs"
5332+ },
5333+ {
5334+ "type": "OpenCollective",
5335+ "url": "https://opencollective.com/unified"
5336+ }
5337+ ],
5338+ "dependencies": {
5339+ "decode-named-character-reference": "^1.0.0",
5340+ "micromark-util-character": "^2.0.0",
5341+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
5342+ "micromark-util-symbol": "^2.0.0"
5343+ }
5344+ },
5345+ "node_modules/micromark-util-encode": {
5346+ "version": "2.0.1",
5347+ "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
5348+ "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
5349+ "funding": [
5350+ {
5351+ "type": "GitHub Sponsors",
5352+ "url": "https://github.com/sponsors/unifiedjs"
5353+ },
5354+ {
5355+ "type": "OpenCollective",
5356+ "url": "https://opencollective.com/unified"
5357+ }
5358+ ]
5359+ },
5360+ "node_modules/micromark-util-html-tag-name": {
5361+ "version": "2.0.1",
5362+ "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
5363+ "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==",
5364+ "funding": [
5365+ {
5366+ "type": "GitHub Sponsors",
5367+ "url": "https://github.com/sponsors/unifiedjs"
5368+ },
5369+ {
5370+ "type": "OpenCollective",
5371+ "url": "https://opencollective.com/unified"
5372+ }
5373+ ]
5374+ },
5375+ "node_modules/micromark-util-normalize-identifier": {
5376+ "version": "2.0.1",
5377+ "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
5378+ "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==",
5379+ "funding": [
5380+ {
5381+ "type": "GitHub Sponsors",
5382+ "url": "https://github.com/sponsors/unifiedjs"
5383+ },
5384+ {
5385+ "type": "OpenCollective",
5386+ "url": "https://opencollective.com/unified"
5387+ }
5388+ ],
5389+ "dependencies": {
5390+ "micromark-util-symbol": "^2.0.0"
5391+ }
5392+ },
5393+ "node_modules/micromark-util-resolve-all": {
5394+ "version": "2.0.1",
5395+ "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
5396+ "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==",
5397+ "funding": [
5398+ {
5399+ "type": "GitHub Sponsors",
5400+ "url": "https://github.com/sponsors/unifiedjs"
5401+ },
5402+ {
5403+ "type": "OpenCollective",
5404+ "url": "https://opencollective.com/unified"
5405+ }
5406+ ],
5407+ "dependencies": {
5408+ "micromark-util-types": "^2.0.0"
5409+ }
5410+ },
5411+ "node_modules/micromark-util-sanitize-uri": {
5412+ "version": "2.0.1",
5413+ "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
5414+ "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
5415+ "funding": [
5416+ {
5417+ "type": "GitHub Sponsors",
5418+ "url": "https://github.com/sponsors/unifiedjs"
5419+ },
5420+ {
5421+ "type": "OpenCollective",
5422+ "url": "https://opencollective.com/unified"
5423+ }
5424+ ],
5425+ "dependencies": {
5426+ "micromark-util-character": "^2.0.0",
5427+ "micromark-util-encode": "^2.0.0",
5428+ "micromark-util-symbol": "^2.0.0"
5429+ }
5430+ },
5431+ "node_modules/micromark-util-subtokenize": {
5432+ "version": "2.0.4",
5433+ "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.4.tgz",
5434+ "integrity": "sha512-N6hXjrin2GTJDe3MVjf5FuXpm12PGm80BrUAeub9XFXca8JZbP+oIwY4LJSVwFUCL1IPm/WwSVUN7goFHmSGGQ==",
5435+ "funding": [
5436+ {
5437+ "type": "GitHub Sponsors",
5438+ "url": "https://github.com/sponsors/unifiedjs"
5439+ },
5440+ {
5441+ "type": "OpenCollective",
5442+ "url": "https://opencollective.com/unified"
5443+ }
5444+ ],
5445+ "dependencies": {
5446+ "devlop": "^1.0.0",
5447+ "micromark-util-chunked": "^2.0.0",
5448+ "micromark-util-symbol": "^2.0.0",
5449+ "micromark-util-types": "^2.0.0"
5450+ }
5451+ },
5452+ "node_modules/micromark-util-symbol": {
5453+ "version": "2.0.1",
5454+ "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
5455+ "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
5456+ "funding": [
5457+ {
5458+ "type": "GitHub Sponsors",
5459+ "url": "https://github.com/sponsors/unifiedjs"
5460+ },
5461+ {
5462+ "type": "OpenCollective",
5463+ "url": "https://opencollective.com/unified"
5464+ }
5465+ ]
5466+ },
5467+ "node_modules/micromark-util-types": {
5468+ "version": "2.0.1",
5469+ "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.1.tgz",
5470+ "integrity": "sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==",
5471+ "funding": [
5472+ {
5473+ "type": "GitHub Sponsors",
5474+ "url": "https://github.com/sponsors/unifiedjs"
5475+ },
5476+ {
5477+ "type": "OpenCollective",
5478+ "url": "https://opencollective.com/unified"
5479+ }
5480+ ]
5481+ },
46625482 "node_modules/micromatch": {
46635483 "version": "4.0.8",
46645484 "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
@@ -4946,6 +5766,29 @@
49465766 "integrity": "sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw==",
49475767 "peer": true
49485768 },
5769+ "node_modules/parse-entities": {
5770+ "version": "4.0.2",
5771+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
5772+ "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==",
5773+ "dependencies": {
5774+ "@types/unist": "^2.0.0",
5775+ "character-entities-legacy": "^3.0.0",
5776+ "character-reference-invalid": "^2.0.0",
5777+ "decode-named-character-reference": "^1.0.0",
5778+ "is-alphanumerical": "^2.0.0",
5779+ "is-decimal": "^2.0.0",
5780+ "is-hexadecimal": "^2.0.0"
5781+ },
5782+ "funding": {
5783+ "type": "github",
5784+ "url": "https://github.com/sponsors/wooorm"
5785+ }
5786+ },
5787+ "node_modules/parse-entities/node_modules/@types/unist": {
5788+ "version": "2.0.11",
5789+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
5790+ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="
5791+ },
49495792 "node_modules/parse-rect": {
49505793 "version": "1.2.0",
49515794 "resolved": "https://registry.npmjs.org/parse-rect/-/parse-rect-1.2.0.tgz",
@@ -5271,6 +6114,15 @@
52716114 "react-is": "^16.13.1"
52726115 }
52736116 },
6117+ "node_modules/property-information": {
6118+ "version": "6.5.0",
6119+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz",
6120+ "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==",
6121+ "funding": {
6122+ "type": "github",
6123+ "url": "https://github.com/sponsors/wooorm"
6124+ }
6125+ },
52746126 "node_modules/protocol-buffers-schema": {
52756127 "version": "3.6.0",
52766128 "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
@@ -5362,6 +6214,31 @@
53626214 "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
53636215 "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
53646216 },
6217+ "node_modules/react-markdown": {
6218+ "version": "9.0.3",
6219+ "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.3.tgz",
6220+ "integrity": "sha512-Yk7Z94dbgYTOrdk41Z74GoKA7rThnsbbqBTRYuxoe08qvfQ9tJVhmAKw6BJS/ZORG7kTy/s1QvYzSuaoBA1qfw==",
6221+ "dependencies": {
6222+ "@types/hast": "^3.0.0",
6223+ "devlop": "^1.0.0",
6224+ "hast-util-to-jsx-runtime": "^2.0.0",
6225+ "html-url-attributes": "^3.0.0",
6226+ "mdast-util-to-hast": "^13.0.0",
6227+ "remark-parse": "^11.0.0",
6228+ "remark-rehype": "^11.0.0",
6229+ "unified": "^11.0.0",
6230+ "unist-util-visit": "^5.0.0",
6231+ "vfile": "^6.0.0"
6232+ },
6233+ "funding": {
6234+ "type": "opencollective",
6235+ "url": "https://opencollective.com/unified"
6236+ },
6237+ "peerDependencies": {
6238+ "@types/react": ">=18",
6239+ "react": ">=18"
6240+ }
6241+ },
53656242 "node_modules/react-plotly.js": {
53666243 "version": "2.6.0",
53676244 "resolved": "https://registry.npmjs.org/react-plotly.js/-/react-plotly.js-2.6.0.tgz",
@@ -5528,6 +6405,37 @@
55286405 "regl-scatter2d": "^3.2.3"
55296406 }
55306407 },
6408+ "node_modules/remark-parse": {
6409+ "version": "11.0.0",
6410+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
6411+ "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==",
6412+ "dependencies": {
6413+ "@types/mdast": "^4.0.0",
6414+ "mdast-util-from-markdown": "^2.0.0",
6415+ "micromark-util-types": "^2.0.0",
6416+ "unified": "^11.0.0"
6417+ },
6418+ "funding": {
6419+ "type": "opencollective",
6420+ "url": "https://opencollective.com/unified"
6421+ }
6422+ },
6423+ "node_modules/remark-rehype": {
6424+ "version": "11.1.1",
6425+ "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.1.tgz",
6426+ "integrity": "sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==",
6427+ "dependencies": {
6428+ "@types/hast": "^3.0.0",
6429+ "@types/mdast": "^4.0.0",
6430+ "mdast-util-to-hast": "^13.0.0",
6431+ "unified": "^11.0.0",
6432+ "vfile": "^6.0.0"
6433+ },
6434+ "funding": {
6435+ "type": "opencollective",
6436+ "url": "https://opencollective.com/unified"
6437+ }
6438+ },
55316439 "node_modules/require-from-string": {
55326440 "version": "2.0.2",
55336441 "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
@@ -5799,6 +6707,15 @@
57996707 "source-map": "^0.6.0"
58006708 }
58016709 },
6710+ "node_modules/space-separated-tokens": {
6711+ "version": "2.0.2",
6712+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
6713+ "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
6714+ "funding": {
6715+ "type": "github",
6716+ "url": "https://github.com/sponsors/wooorm"
6717+ }
6718+ },
58026719 "node_modules/stack-trace": {
58036720 "version": "0.0.9",
58046721 "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz",
@@ -5871,6 +6788,19 @@
58716788 "parenthesis": "^3.1.5"
58726789 }
58736790 },
6791+ "node_modules/stringify-entities": {
6792+ "version": "4.0.4",
6793+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
6794+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
6795+ "dependencies": {
6796+ "character-entities-html4": "^2.0.0",
6797+ "character-entities-legacy": "^3.0.0"
6798+ },
6799+ "funding": {
6800+ "type": "github",
6801+ "url": "https://github.com/sponsors/wooorm"
6802+ }
6803+ },
58746804 "node_modules/strip-json-comments": {
58756805 "version": "3.1.1",
58766806 "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -5905,6 +6835,14 @@
59056835 "webpack": "^5.27.0"
59066836 }
59076837 },
6838+ "node_modules/style-to-object": {
6839+ "version": "1.0.8",
6840+ "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz",
6841+ "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==",
6842+ "dependencies": {
6843+ "inline-style-parser": "0.2.4"
6844+ }
6845+ },
59086846 "node_modules/supercluster": {
59096847 "version": "7.1.5",
59106848 "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.5.tgz",
@@ -6173,6 +7111,24 @@
61737111 "topoquantize": "bin/topoquantize"
61747112 }
61757113 },
7114+ "node_modules/trim-lines": {
7115+ "version": "3.0.1",
7116+ "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
7117+ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
7118+ "funding": {
7119+ "type": "github",
7120+ "url": "https://github.com/sponsors/wooorm"
7121+ }
7122+ },
7123+ "node_modules/trough": {
7124+ "version": "2.2.0",
7125+ "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz",
7126+ "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==",
7127+ "funding": {
7128+ "type": "github",
7129+ "url": "https://github.com/sponsors/wooorm"
7130+ }
7131+ },
61767132 "node_modules/ts-api-utils": {
61777133 "version": "2.0.0",
61787134 "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz",
@@ -6271,6 +7227,98 @@
62717227 "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
62727228 "peer": true
62737229 },
7230+ "node_modules/unified": {
7231+ "version": "11.0.5",
7232+ "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
7233+ "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==",
7234+ "dependencies": {
7235+ "@types/unist": "^3.0.0",
7236+ "bail": "^2.0.0",
7237+ "devlop": "^1.0.0",
7238+ "extend": "^3.0.0",
7239+ "is-plain-obj": "^4.0.0",
7240+ "trough": "^2.0.0",
7241+ "vfile": "^6.0.0"
7242+ },
7243+ "funding": {
7244+ "type": "opencollective",
7245+ "url": "https://opencollective.com/unified"
7246+ }
7247+ },
7248+ "node_modules/unified/node_modules/is-plain-obj": {
7249+ "version": "4.1.0",
7250+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
7251+ "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
7252+ "engines": {
7253+ "node": ">=12"
7254+ },
7255+ "funding": {
7256+ "url": "https://github.com/sponsors/sindresorhus"
7257+ }
7258+ },
7259+ "node_modules/unist-util-is": {
7260+ "version": "6.0.0",
7261+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz",
7262+ "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==",
7263+ "dependencies": {
7264+ "@types/unist": "^3.0.0"
7265+ },
7266+ "funding": {
7267+ "type": "opencollective",
7268+ "url": "https://opencollective.com/unified"
7269+ }
7270+ },
7271+ "node_modules/unist-util-position": {
7272+ "version": "5.0.0",
7273+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
7274+ "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
7275+ "dependencies": {
7276+ "@types/unist": "^3.0.0"
7277+ },
7278+ "funding": {
7279+ "type": "opencollective",
7280+ "url": "https://opencollective.com/unified"
7281+ }
7282+ },
7283+ "node_modules/unist-util-stringify-position": {
7284+ "version": "4.0.0",
7285+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
7286+ "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
7287+ "dependencies": {
7288+ "@types/unist": "^3.0.0"
7289+ },
7290+ "funding": {
7291+ "type": "opencollective",
7292+ "url": "https://opencollective.com/unified"
7293+ }
7294+ },
7295+ "node_modules/unist-util-visit": {
7296+ "version": "5.0.0",
7297+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz",
7298+ "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==",
7299+ "dependencies": {
7300+ "@types/unist": "^3.0.0",
7301+ "unist-util-is": "^6.0.0",
7302+ "unist-util-visit-parents": "^6.0.0"
7303+ },
7304+ "funding": {
7305+ "type": "opencollective",
7306+ "url": "https://opencollective.com/unified"
7307+ }
7308+ },
7309+ "node_modules/unist-util-visit-parents": {
7310+ "version": "6.0.1",
7311+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz",
7312+ "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==",
7313+ "dependencies": {
7314+ "@types/unist": "^3.0.0",
7315+ "unist-util-is": "^6.0.0"
7316+ },
7317+ "funding": {
7318+ "type": "opencollective",
7319+ "url": "https://opencollective.com/unified"
7320+ }
7321+ },
62747322 "node_modules/unquote": {
62757323 "version": "1.1.1",
62767324 "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
@@ -6326,6 +7374,32 @@
63267374 "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
63277375 "peer": true
63287376 },
7377+ "node_modules/vfile": {
7378+ "version": "6.0.3",
7379+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
7380+ "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
7381+ "dependencies": {
7382+ "@types/unist": "^3.0.0",
7383+ "vfile-message": "^4.0.0"
7384+ },
7385+ "funding": {
7386+ "type": "opencollective",
7387+ "url": "https://opencollective.com/unified"
7388+ }
7389+ },
7390+ "node_modules/vfile-message": {
7391+ "version": "4.0.2",
7392+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz",
7393+ "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==",
7394+ "dependencies": {
7395+ "@types/unist": "^3.0.0",
7396+ "unist-util-stringify-position": "^4.0.0"
7397+ },
7398+ "funding": {
7399+ "type": "opencollective",
7400+ "url": "https://opencollective.com/unified"
7401+ }
7402+ },
63297403 "node_modules/vite": {
63307404 "version": "6.0.11",
63317405 "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz",
@@ -6578,6 +7652,15 @@
65787652 "funding": {
65797653 "url": "https://github.com/sponsors/sindresorhus"
65807654 }
7655+ },
7656+ "node_modules/zwitch": {
7657+ "version": "2.0.4",
7658+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
7659+ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
7660+ "funding": {
7661+ "type": "github",
7662+ "url": "https://github.com/sponsors/wooorm"
7663+ }
65817664 }
65827665 }
65837666 }
web-ui/package.jsonmodified+2−1View file
@@ -4,7 +4,7 @@
44 "version": "0.0.0",
55 "type": "module",
66 "scripts": {
7- "dev": "vite",
7+ "dev": "../devel/generate_posts_index.sh && vite",
88 "build": "tsc -b && vite build",
99 "lint": "eslint .",
1010 "preview": "vite preview",
@@ -18,6 +18,7 @@
1818 "plotly.js-dist-min": "^2.35.3",
1919 "react": "^18.3.1",
2020 "react-dom": "^18.3.1",
21+ "react-markdown": "^9.0.3",
2122 "react-plotly.js": "^2.6.0",
2223 "react-router-dom": "^7.1.3"
2324 },
web-ui/public/posts/2025-01-27-dataset-timeseries-view.mdadded+5−0View file
@@ -0,0 +1,5 @@
1+# Dataset timeseries view
2+
3+For each dataset, you can see an interactive view of the timeseries data on the Dataset page. Here's an example:
4+
5+[/zia/dataset/gaussian-8](/zia/dataset/gaussian-8)
\ No newline at end of file
web-ui/public/posts/index.txtadded+1−0View file
@@ -0,0 +1 @@
1+2025-01-27-dataset-timeseries-view.md
web-ui/src/App.cssmodified+24−31View file
@@ -1,42 +1,35 @@
1-#root {
2- max-width: 1280px;
3- margin: 0 auto;
4- padding: 2rem;
5- text-align: center;
6-}
1+/* Existing styles */
72
8-.logo {
9- height: 6em;
10- padding: 1.5em;
11- will-change: filter;
12- transition: filter 300ms;
13-}
14-.logo:hover {
15- filter: drop-shadow(0 0 2em #646cffaa);
3+/* Markdown content styles */
4+.markdown-content {
5+ font-family: system-ui, -apple-system, sans-serif;
6+ line-height: 1.6;
7+ color: #333;
168 }
17-.logo.react:hover {
18- filter: drop-shadow(0 0 2em #61dafbaa);
9+
10+.markdown-content h1 {
11+ font-size: 2.2rem;
12+ margin-bottom: 1.5rem;
13+ color: #1a1a1a;
1914 }
2015
21-@keyframes logo-spin {
22- from {
23- transform: rotate(0deg);
24- }
25- to {
26- transform: rotate(360deg);
27- }
16+.markdown-content h2 {
17+ font-size: 1.8rem;
18+ margin: 2rem 0 1rem;
19+ color: #1a1a1a;
2820 }
2921
30-@media (prefers-reduced-motion: no-preference) {
31- a:nth-of-type(2) .logo {
32- animation: logo-spin infinite 20s linear;
33- }
22+.markdown-content p {
23+ margin-bottom: 1.2rem;
24+ font-size: 1.1rem;
3425 }
3526
36-.card {
37- padding: 2em;
27+.markdown-content ul {
28+ margin: 1rem 0;
29+ padding-left: 2rem;
3830 }
3931
40-.read-the-docs {
41- color: #888;
32+.markdown-content li {
33+ margin: 0.5rem 0;
34+ font-size: 1.1rem;
4235 }
web-ui/src/App.tsxmodified+7−0View file
@@ -5,6 +5,7 @@ import Home from "./pages/Home";
55 import Datasets from "./pages/Datasets";
66 import Dataset from "./pages/Dataset";
77 import Algorithms from "./pages/Algorithms";
8+import Algorithm from "./pages/Algorithm";
89 import About from "./pages/About";
910 import { BenchmarkData } from "./types";
1011
@@ -148,6 +149,12 @@ function App() {
148149 path="/dataset/:datasetName"
149150 element={<Dataset datasets={benchmarkData?.datasets || []} />}
150151 />
152+ <Route
153+ path="/algorithm/:algorithmName"
154+ element={
155+ <Algorithm algorithms={benchmarkData?.algorithms || []} />
156+ }
157+ />
151158 <Route path="/about" element={<About />} />
152159 </Routes>
153160 )}
web-ui/src/components/TagFilter.tsxadded+47−0View file
@@ -0,0 +1,47 @@
1+import React from "react";
2+
3+interface TagFilterProps {
4+ availableTags: string[];
5+ selectedTags: string[];
6+ onTagToggle: (tag: string) => void;
7+ label: string;
8+}
9+
10+export function TagFilter({
11+ availableTags,
12+ selectedTags,
13+ onTagToggle,
14+ label,
15+}: TagFilterProps) {
16+ return (
17+ <div style={{ marginTop: "1rem" }}>
18+ <div style={{ display: "flex", alignItems: "center", gap: "1rem" }}>
19+ <div
20+ style={{ fontSize: "0.9rem", color: "#666", whiteSpace: "nowrap" }}
21+ >
22+ {label}:
23+ </div>
24+ <div style={{ display: "flex", flexWrap: "wrap", gap: "0.5rem" }}>
25+ {availableTags.map((tag) => (
26+ <button
27+ key={tag}
28+ onClick={() => onTagToggle(tag)}
29+ style={{
30+ padding: "4px 8px",
31+ border: "1px solid #ddd",
32+ borderRadius: "4px",
33+ background: selectedTags.includes(tag) ? "#0066cc" : "white",
34+ color: selectedTags.includes(tag) ? "white" : "#333",
35+ cursor: "pointer",
36+ fontSize: "0.8rem",
37+ transition: "all 0.2s ease",
38+ }}
39+ >
40+ {tag}
41+ </button>
42+ ))}
43+ </div>
44+ </div>
45+ </div>
46+ );
47+}
web-ui/src/components/benchmark/table/BenchmarkTable.tsxmodified+12−27View file
@@ -13,34 +13,20 @@ import { exportToCsv } from "../export/csvExport";
1313
1414 interface BenchmarkTableProps {
1515 results: BenchmarkResult[];
16+ availableDatasets: string[];
17+ availableAlgorithms: string[];
1618 }
1719
18-export function BenchmarkTable({ results }: BenchmarkTableProps) {
20+export function BenchmarkTable({
21+ results,
22+ availableDatasets,
23+ availableAlgorithms,
24+}: BenchmarkTableProps) {
1925 const [searchParams, setSearchParams] = useSearchParams();
2026 const selectedDataset = searchParams.get("dataset") || "";
2127 const selectedAlgorithm = searchParams.get("algorithm") || "";
2228
23- const availableDatasets = useMemo(() => {
24- return Array.from(new Set(results.map((result) => result.dataset))).sort();
25- }, [results]);
26-
27- const availableAlgorithms = useMemo(() => {
28- return Array.from(
29- new Set(results.map((result) => result.algorithm)),
30- ).sort();
31- }, [results]);
32-
33- // Memoize filtered data to prevent unnecessary recalculations
34- const filteredData = useMemo(() => {
35- let filtered = results;
36- if (selectedDataset) {
37- filtered = filtered.filter((row) => row.dataset === selectedDataset);
38- }
39- if (selectedAlgorithm) {
40- filtered = filtered.filter((row) => row.algorithm === selectedAlgorithm);
41- }
42- return filtered;
43- }, [results, selectedDataset, selectedAlgorithm]);
29+ const filteredData = results;
4430
4531 const table = useReactTable({
4632 data: filteredData || [],
@@ -49,10 +35,9 @@ export function BenchmarkTable({ results }: BenchmarkTableProps) {
4935 getSortedRowModel: getSortedRowModel(),
5036 });
5137
52- // Prepare data for bar charts when either dataset or algorithm is selected
5338 const chartData = useMemo(() => {
5439 if (selectedDataset) {
55- return results
40+ return filteredData
5641 .filter((row: BenchmarkResult) => row.dataset === selectedDataset)
5742 .map((row: BenchmarkResult) => ({
5843 algorithm: row.algorithm,
@@ -61,17 +46,17 @@ export function BenchmarkTable({ results }: BenchmarkTableProps) {
6146 decode_speed: row.decode_mb_per_sec,
6247 }));
6348 } else if (selectedAlgorithm) {
64- return results
49+ return filteredData
6550 .filter((row: BenchmarkResult) => row.algorithm === selectedAlgorithm)
6651 .map((row: BenchmarkResult) => ({
67- algorithm: row.dataset, // Use dataset as the x-axis label when algorithm is selected
52+ algorithm: row.dataset,
6853 compression_ratio: row.compression_ratio,
6954 encode_speed: row.encode_mb_per_sec,
7055 decode_speed: row.decode_mb_per_sec,
7156 }));
7257 }
7358 return [];
74- }, [results, selectedDataset, selectedAlgorithm]);
59+ }, [filteredData, selectedDataset, selectedAlgorithm]);
7560
7661 return (
7762 <div className="table-container">
web-ui/src/hooks/useMarkdownContent.tsadded+31−0View file
@@ -0,0 +1,31 @@
1+import { useState, useEffect } from "react";
2+
3+export const useMarkdownContent = (path: string) => {
4+ const [content, setContent] = useState<string>("");
5+ const [error, setError] = useState<string | null>(null);
6+
7+ useEffect(() => {
8+ const fetchContent = async () => {
9+ try {
10+ const response = await fetch(path);
11+ if (!response.ok) {
12+ throw new Error(
13+ `Failed to load markdown content: ${response.statusText}`,
14+ );
15+ }
16+ const text = await response.text();
17+ setContent(text);
18+ } catch (err) {
19+ setError(
20+ err instanceof Error
21+ ? err.message
22+ : "Failed to load markdown content",
23+ );
24+ }
25+ };
26+
27+ fetchContent();
28+ }, [path]);
29+
30+ return { content, error };
31+};
web-ui/src/hooks/useMarkdownPosts.tsadded+62−0View file
@@ -0,0 +1,62 @@
1+import { useState, useEffect } from "react";
2+
3+interface Post {
4+ path: string;
5+ content: string;
6+ date: Date;
7+}
8+
9+export const useMarkdownPosts = (directory: string) => {
10+ const [posts, setPosts] = useState<Post[]>([]);
11+ const [error, setError] = useState<string | null>(null);
12+ const [loading, setLoading] = useState(true);
13+
14+ useEffect(() => {
15+ const fetchPosts = async () => {
16+ try {
17+ // First fetch the index
18+ const indexResponse = await fetch(`${directory}/index.txt`);
19+ if (!indexResponse.ok) {
20+ throw new Error(
21+ `Failed to load post index: ${indexResponse.statusText}`,
22+ );
23+ }
24+ const indexContent = await indexResponse.text();
25+ const paths = indexContent.trim().split("\n");
26+
27+ // Then fetch all posts in parallel
28+ const postPromises = paths.map(async (path) => {
29+ const response = await fetch(`${directory}/${path}`);
30+ if (!response.ok) {
31+ throw new Error(
32+ `Failed to load post ${path}: ${response.statusText}`,
33+ );
34+ }
35+ const content = await response.text();
36+
37+ // Parse date from filename (format: YYYY-MM-DD-title.md)
38+ const dateMatch = path.match(/^(\d{4}-\d{2}-\d{2})/);
39+ if (!dateMatch) {
40+ throw new Error(`Invalid post filename format: ${path}`);
41+ }
42+ const date = new Date(dateMatch[1]);
43+
44+ return { path, content, date };
45+ });
46+
47+ const loadedPosts = await Promise.all(postPromises);
48+ // Sort posts by date, newest first
49+ loadedPosts.sort((a, b) => b.date.getTime() - a.date.getTime());
50+ setPosts(loadedPosts);
51+ setLoading(false);
52+ } catch (err) {
53+ setError(err instanceof Error ? err.message : "Failed to load posts");
54+ setLoading(false);
55+ }
56+ };
57+
58+ fetchPosts();
59+ }, [directory]);
60+
61+ return { posts, error, loading };
62+};
web-ui/src/hooks/useTagFilter.tsadded+37−0View file
@@ -0,0 +1,37 @@
1+import { useState, useMemo } from "react";
2+
3+interface TaggableItem {
4+ tags: string[];
5+}
6+
7+export function useTagFilter<T extends TaggableItem>(items: T[]) {
8+ const [selectedTags, setSelectedTags] = useState<string[]>([]);
9+
10+ const availableTags = useMemo(() => {
11+ const tagSet = new Set<string>();
12+ items.forEach((item) => {
13+ item.tags.forEach((tag) => tagSet.add(tag));
14+ });
15+ return Array.from(tagSet).sort();
16+ }, [items]);
17+
18+ const filteredItems = useMemo(() => {
19+ if (selectedTags.length === 0) return items;
20+ return items.filter((item) =>
21+ selectedTags.every((tag) => item.tags.includes(tag)),
22+ );
23+ }, [items, selectedTags]);
24+
25+ const toggleTag = (tag: string) => {
26+ setSelectedTags((prev) =>
27+ prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag],
28+ );
29+ };
30+
31+ return {
32+ selectedTags,
33+ availableTags,
34+ filteredItems,
35+ toggleTag,
36+ };
37+}
web-ui/src/pages/About.tsxmodified+32−0View file
@@ -1,6 +1,10 @@
11 import React from "react";
2+import ReactMarkdown from "react-markdown";
3+import { useMarkdownPosts } from "../hooks/useMarkdownPosts";
24
35 const About: React.FC = () => {
6+ const { posts, error, loading } = useMarkdownPosts("posts");
7+
48 return (
59 <div style={{ maxWidth: "800px", margin: "0 auto" }}>
610 <h1>About Zia</h1>
@@ -24,6 +28,34 @@ const About: React.FC = () => {
2428 View on GitHub
2529 </a>
2630 </p>
31+
32+ <hr />
33+
34+ {error ? (
35+ <div style={{ color: "red" }}>Error loading content: {error}</div>
36+ ) : loading ? (
37+ <div>Loading...</div>
38+ ) : (
39+ <div>
40+ {posts.map((post) => (
41+ <div
42+ key={post.path}
43+ className="markdown-content"
44+ style={{ marginBottom: "2rem" }}
45+ >
46+ <div style={{ color: "#666", marginBottom: "1rem" }}>
47+ {post.date.toLocaleDateString("en-US", {
48+ year: "numeric",
49+ month: "long",
50+ day: "numeric",
51+ })}
52+ </div>
53+ <ReactMarkdown>{post.content}</ReactMarkdown>
54+ {post.path !== posts[posts.length - 1].path && <hr />}
55+ </div>
56+ ))}
57+ </div>
58+ )}
2759 </div>
2860 );
2961 };
web-ui/src/pages/Algorithm.tsxadded+107−0View file
@@ -0,0 +1,107 @@
1+import { useParams } from "react-router-dom";
2+import { Algorithm as AlgorithmType } from "../types";
3+
4+interface AlgorithmProps {
5+ algorithms: AlgorithmType[];
6+}
7+
8+function Algorithm({ algorithms }: AlgorithmProps) {
9+ const { algorithmName } = useParams<{ algorithmName: string }>();
10+ const algorithm = algorithms.find((a) => a.name === algorithmName);
11+
12+ if (!algorithm) {
13+ return <div>Algorithm not found</div>;
14+ }
15+
16+ return (
17+ <div>
18+ <h1
19+ style={{
20+ fontSize: "2rem",
21+ fontWeight: "bold",
22+ color: "#333",
23+ marginBottom: "1rem",
24+ }}
25+ >
26+ {algorithm.name}
27+ </h1>
28+ <div>
29+ <div style={{ marginBottom: "1.5rem" }}>
30+ <p style={{ fontSize: "0.9rem", lineHeight: "1.5" }}>
31+ {algorithm.description}
32+ </p>
33+ </div>
34+ <div style={{ marginBottom: "1.5rem" }}>
35+ <h2
36+ style={{
37+ fontSize: "1.2rem",
38+ fontWeight: "bold",
39+ marginBottom: "0.5rem",
40+ }}
41+ >
42+ Version
43+ </h2>
44+ <p style={{ fontSize: "0.9rem" }}>{algorithm.version}</p>
45+ </div>
46+ <div style={{ marginBottom: "1.5rem" }}>
47+ <h2
48+ style={{
49+ fontSize: "1.2rem",
50+ fontWeight: "bold",
51+ marginBottom: "0.5rem",
52+ }}
53+ >
54+ Tags
55+ </h2>
56+ <div>
57+ {algorithm.tags.map((tag) => (
58+ <span
59+ key={tag}
60+ style={{
61+ display: "inline-block",
62+ backgroundColor: "#e1e1e1",
63+ padding: "2px 6px",
64+ borderRadius: "3px",
65+ margin: "2px",
66+ fontSize: "0.8rem",
67+ }}
68+ >
69+ {tag}
70+ </span>
71+ ))}
72+ </div>
73+ </div>
74+ {algorithm.source_file && (
75+ <div style={{ marginBottom: "1.5rem" }}>
76+ <h2
77+ style={{
78+ fontSize: "1.2rem",
79+ fontWeight: "bold",
80+ marginBottom: "0.5rem",
81+ }}
82+ >
83+ Source
84+ </h2>
85+ <a
86+ href={algorithm.source_file}
87+ target="_blank"
88+ rel="noopener noreferrer"
89+ style={{
90+ color: "#0066cc",
91+ textDecoration: "none",
92+ padding: "4px 8px",
93+ backgroundColor: "#f0f0f0",
94+ borderRadius: "4px",
95+ fontSize: "0.9rem",
96+ }}
97+ >
98+ View Source
99+ </a>
100+ </div>
101+ )}
102+ </div>
103+ </div>
104+ );
105+}
106+
107+export default Algorithm;
web-ui/src/pages/Algorithms.tsxmodified+29−12View file
@@ -1,23 +1,40 @@
11 import { Algorithm } from "../types";
22 import { Link } from "react-router-dom";
3+import { TagFilter } from "../components/TagFilter";
4+import { useTagFilter } from "../hooks/useTagFilter";
35
46 interface AlgorithmsProps {
57 algorithms: Algorithm[];
68 }
79
810 function Algorithms({ algorithms }: AlgorithmsProps) {
11+ const {
12+ selectedTags,
13+ availableTags,
14+ filteredItems: filteredAlgorithms,
15+ toggleTag,
16+ } = useTagFilter(algorithms);
17+
918 return (
1019 <div>
11- <h1
12- style={{
13- fontSize: "2rem",
14- fontWeight: "bold",
15- color: "#333",
16- marginBottom: "1rem",
17- }}
18- >
19- Compression Algorithms
20- </h1>
20+ <div style={{ marginBottom: "2rem" }}>
21+ <h1
22+ style={{
23+ fontSize: "2rem",
24+ fontWeight: "bold",
25+ color: "#333",
26+ marginBottom: "1rem",
27+ }}
28+ >
29+ Compression Algorithms
30+ </h1>
31+ <TagFilter
32+ availableTags={availableTags}
33+ selectedTags={selectedTags}
34+ onTagToggle={toggleTag}
35+ label="Filter algorithms"
36+ />
37+ </div>
2138 <div style={{ overflowX: "auto" }}>
2239 <table style={{ width: "100%", borderCollapse: "collapse" }}>
2340 <thead>
@@ -80,7 +97,7 @@ function Algorithms({ algorithms }: AlgorithmsProps) {
8097 </tr>
8198 </thead>
8299 <tbody>
83- {algorithms.map((algorithm, index) => (
100+ {filteredAlgorithms.map((algorithm, index) => (
84101 <tr
85102 key={`${algorithm.name}-${algorithm.version}`}
86103 style={{
@@ -95,7 +112,7 @@ function Algorithms({ algorithms }: AlgorithmsProps) {
95112 }}
96113 >
97114 <Link
98- to={`/home?algorithm=${encodeURIComponent(algorithm.name)}`}
115+ to={`/algorithm/${encodeURIComponent(algorithm.name)}`}
99116 style={{
100117 color: "#0066cc",
101118 textDecoration: "none",
web-ui/src/pages/Datasets.tsxmodified+28−11View file
@@ -1,23 +1,40 @@
11 import { Dataset } from "../types";
22 import { Link } from "react-router-dom";
3+import { TagFilter } from "../components/TagFilter";
4+import { useTagFilter } from "../hooks/useTagFilter";
35
46 interface DatasetsProps {
57 datasets: Dataset[];
68 }
79
810 function Datasets({ datasets }: DatasetsProps) {
11+ const {
12+ selectedTags,
13+ availableTags,
14+ filteredItems: filteredDatasets,
15+ toggleTag,
16+ } = useTagFilter(datasets);
17+
918 return (
1019 <div>
11- <h1
12- style={{
13- fontSize: "2rem",
14- fontWeight: "bold",
15- color: "#333",
16- marginBottom: "1rem",
17- }}
18- >
19- Benchmark Datasets
20- </h1>
20+ <div style={{ marginBottom: "2rem" }}>
21+ <h1
22+ style={{
23+ fontSize: "2rem",
24+ fontWeight: "bold",
25+ color: "#333",
26+ marginBottom: "1rem",
27+ }}
28+ >
29+ Benchmark Datasets
30+ </h1>
31+ <TagFilter
32+ availableTags={availableTags}
33+ selectedTags={selectedTags}
34+ onTagToggle={toggleTag}
35+ label="Filter datasets"
36+ />
37+ </div>
2138 <div style={{ overflowX: "auto" }}>
2239 <table style={{ width: "100%", borderCollapse: "collapse" }}>
2340 <thead>
@@ -91,7 +108,7 @@ function Datasets({ datasets }: DatasetsProps) {
91108 </tr>
92109 </thead>
93110 <tbody>
94- {datasets.map((dataset, index) => (
111+ {filteredDatasets.map((dataset, index) => (
95112 <tr
96113 key={`${dataset.name}-${dataset.version}`}
97114 style={{
web-ui/src/pages/Home.tsxmodified+100−1View file
@@ -1,11 +1,77 @@
11 import { BenchmarkTable } from "../components/benchmark/table/BenchmarkTable";
22 import { BenchmarkData } from "../types";
3+import { useSearchParams } from "react-router-dom";
4+import { useMemo } from "react";
5+import { TagFilter } from "../components/TagFilter";
6+import { useTagFilter } from "../hooks/useTagFilter";
37
48 interface HomeProps {
59 benchmarkData: BenchmarkData | null;
610 }
711
812 function Home({ benchmarkData }: HomeProps) {
13+ const [searchParams] = useSearchParams();
14+ const selectedDataset = searchParams.get("dataset") || "";
15+ const selectedAlgorithm = searchParams.get("algorithm") || "";
16+
17+ // Set up tag filtering for datasets
18+ const {
19+ selectedTags: selectedDatasetTags,
20+ availableTags: availableDatasetTags,
21+ filteredItems: filteredDatasets,
22+ toggleTag: toggleDatasetTag,
23+ } = useTagFilter(benchmarkData?.datasets || []);
24+
25+ // Set up tag filtering for algorithms
26+ const {
27+ selectedTags: selectedAlgorithmTags,
28+ availableTags: availableAlgorithmTags,
29+ filteredItems: filteredAlgorithms,
30+ toggleTag: toggleAlgorithmTag,
31+ } = useTagFilter(benchmarkData?.algorithms || []);
32+
33+ // Filter benchmark results based on selected dataset/algorithm and tags
34+ const filteredResults = useMemo(() => {
35+ if (!benchmarkData) return [];
36+
37+ let filtered = benchmarkData.results;
38+
39+ // Filter by selected dataset/algorithm
40+ if (selectedDataset) {
41+ filtered = filtered.filter(
42+ (result) => result.dataset === selectedDataset,
43+ );
44+ } else if (selectedDatasetTags.length > 0) {
45+ // Only apply dataset tag filtering if no specific dataset is selected
46+ const datasetNames = filteredDatasets.map((d) => d.name);
47+ filtered = filtered.filter((result) =>
48+ datasetNames.includes(result.dataset),
49+ );
50+ }
51+
52+ if (selectedAlgorithm) {
53+ filtered = filtered.filter(
54+ (result) => result.algorithm === selectedAlgorithm,
55+ );
56+ } else if (selectedAlgorithmTags.length > 0) {
57+ // Only apply algorithm tag filtering if no specific algorithm is selected
58+ const algorithmNames = filteredAlgorithms.map((a) => a.name);
59+ filtered = filtered.filter((result) =>
60+ algorithmNames.includes(result.algorithm),
61+ );
62+ }
63+
64+ return filtered;
65+ }, [
66+ benchmarkData,
67+ selectedDataset,
68+ selectedAlgorithm,
69+ selectedDatasetTags,
70+ selectedAlgorithmTags,
71+ filteredDatasets,
72+ filteredAlgorithms,
73+ ]);
74+
975 return (
1076 <div>
1177 <header style={{ marginBottom: "2rem" }}>
@@ -28,7 +94,40 @@ function Home({ benchmarkData }: HomeProps) {
2894 </p>
2995 </header>
3096 <main>
31- {benchmarkData && <BenchmarkTable results={benchmarkData.results} />}
97+ <div
98+ style={{
99+ marginBottom: "2rem",
100+ display: "flex",
101+ flexDirection: "column",
102+ gap: "1rem",
103+ }}
104+ >
105+ {!selectedDataset && (
106+ <TagFilter
107+ availableTags={availableDatasetTags}
108+ selectedTags={selectedDatasetTags}
109+ onTagToggle={toggleDatasetTag}
110+ label="Filter datasets"
111+ />
112+ )}
113+
114+ {!selectedAlgorithm && (
115+ <TagFilter
116+ availableTags={availableAlgorithmTags}
117+ selectedTags={selectedAlgorithmTags}
118+ onTagToggle={toggleAlgorithmTag}
119+ label="Filter algorithms"
120+ />
121+ )}
122+ </div>
123+
124+ {benchmarkData && (
125+ <BenchmarkTable
126+ results={filteredResults}
127+ availableDatasets={filteredDatasets.map((d) => d.name)}
128+ availableAlgorithms={filteredAlgorithms.map((a) => a.name)}
129+ />
130+ )}
32131 </main>
33132 </div>
34133 );
moveopenescclose