Compare commits

...

67 Commits

Author SHA1 Message Date
tim
1c28201cb8 fix: 侧边栏收起打开 有引导 #848 2025-09-07 14:13:48 +08:00
tim
0e26758585 fix: 首页帖子padding 写为15px 2025-09-07 14:10:04 +08:00
tim
786e60e8e5 fix: 帖子元素 -- 上下间距一样 #846 2025-09-07 14:08:37 +08:00
tim
d94302635a fix: 生产环境新增www 2025-09-07 13:58:22 +08:00
tim
9519f66474 fix: 首页帖子padding可以大一些 比如 20px #845 2025-09-07 13:43:40 +08:00
tim
92ba475f3b fix: 更新分类选择 2025-09-07 13:38:09 +08:00
tim
6fffdb0fd6 feat: 侧边栏按钮样式逻辑修改 2025-09-07 13:20:53 +08:00
tim
db8c896b71 fix: empty commit 2025-09-06 21:49:28 +08:00
Tim
2a090442cc Merge pull request #906 from nagisa77/codex/fix-unsatisfied-dependencies-in-services
Fix Resend email environment variable placeholder
2025-09-06 21:44:49 +08:00
Tim
aa86909598 Fix resend from email env placeholder 2025-09-06 21:44:36 +08:00
Tim
5eb1416c6b Merge pull request #885 from nagisa77/codex/separate-redis-databases-for-environments
feat: allow redis database override
2025-09-06 21:32:02 +08:00
Tim
7320df6d20 Merge pull request #905 from nagisa77/codex/set-redis-tags-sync-interval-to-1-hour
feat: refresh tag and category caches hourly
2025-09-06 21:30:15 +08:00
Tim
9406bf3392 feat: refresh tag and category caches hourly 2025-09-06 21:28:52 +08:00
Tim
ccaada8f4e Merge pull request #889 from nagisa77/feature/icon_park
feature: 图标迁移为字节系IconPark
2025-09-06 21:09:52 +08:00
tim
5738ce75e8 fix: 修改当前在线人数icon 2025-09-06 21:09:13 +08:00
tim
0cf3e8c0f8 Merge remote-tracking branch 'origin/main' into feature/icon_park 2025-09-06 21:05:52 +08:00
Tim
e2d16845f5 Merge pull request #904 from nagisa77/codex/adapt-points.vue-to-iconpark
chore: use iconpark icons in points page
2025-09-06 21:02:31 +08:00
Tim
cb531d1337 chore: use iconpark icons in points page 2025-09-06 21:02:14 +08:00
Tim
b538f99082 Merge pull request #903 from nagisa77/codex/adapt-iconpark-in-users-page
chore: migrate user page icons to IconPark
2025-09-06 21:01:36 +08:00
Tim
ba5f0148af chore: migrate user page icons to IconPark 2025-09-06 21:01:22 +08:00
Tim
7dc9903060 Merge pull request #888 from smallclover/main
功能追加:显示在线人数
2025-09-06 21:00:25 +08:00
Tim
337e7ca43f Merge pull request #891 from palmcivet/docs/fumadocs
docs: 使用 Fumadocs 部署 Open API 文档
2025-09-06 21:00:01 +08:00
Tim
cc333e4bca Merge pull request #902 from mewhz/main
📝 配置文件与部署文档多处修改
2025-09-06 20:59:09 +08:00
mewhz
9e4ad29c7f 🔧 配置文件和部署文档新增 resend 邮箱服务 2025-09-06 15:16:02 +08:00
mewhz
49092780e3 🔧 修改前端配置文件与环境变量 2025-09-06 14:48:17 +08:00
mewhz
6570cfd677 📝 环境变量和部署文档新增 Redis 部分 2025-09-06 14:41:15 +08:00
mewhz
1b3bd27655 📝 新增文档中用户名密码与其他说明 2025-09-06 14:24:38 +08:00
tim
cfe24b5e8e fix: 修改为小写拼写 2025-09-06 13:55:13 +08:00
Tim
52633c8073 Merge pull request #901 from nagisa77/codex/adapt-notification.js-for-iconpark
refactor: switch notification icons to iconpark
2025-09-06 13:50:52 +08:00
Tim
4802c78156 refactor: switch notification icons to iconpark 2025-09-06 13:50:39 +08:00
Tim
cf2299f9bf Merge pull request #900 from nagisa77/codex/adapt-tagselect-for-iconpark
feat: adapt TagSelect to IconPark icons
2025-09-06 11:50:52 +08:00
Tim
f03bf92641 feat: adapt TagSelect to IconPark icons 2025-09-06 11:50:38 +08:00
Tim
8bb9c3e3d9 Merge pull request #899 from nagisa77/codex/adapt-searchdropdown-to-iconpark
refactor: replace font awesome with iconpark in search dropdown
2025-09-06 11:48:40 +08:00
Tim
8c554465f6 refactor: replace font awesome with iconpark in search dropdown 2025-09-06 11:48:22 +08:00
tim
05d56df44e fix 2025-09-06 11:47:18 +08:00
Tim
5b0cbe8ce9 Merge pull request #898 from nagisa77/codex/adapt-basetimeline-for-icon-park
Adapt BaseTimeline for IconPark icons
2025-09-06 11:44:42 +08:00
Tim
140d33d024 feat: support IconPark icons in BaseTimeline 2025-09-06 11:44:13 +08:00
tim
6ad7e951fe feat: add few icons 2025-09-06 11:25:44 +08:00
Tim
da47d37dc5 Merge pull request #897 from nagisa77/codex/adapt-dropdown.vue-to-iconpark-6m72wf
feat: integrate icon park in dropdown
2025-09-06 10:10:06 +08:00
Tim
6293f572d8 feat: integrate icon park in dropdown 2025-09-06 10:09:55 +08:00
tim
94f4792a32 Revert "feat: switch dropdown icons to IconPark"
This reverts commit 7421ec8984.
2025-09-06 10:09:20 +08:00
Tim
069f4bb8c1 Merge pull request #896 from nagisa77/codex/adapt-dropdown.vue-to-iconpark-qtb5fv
feat: switch dropdown icons to IconPark
2025-09-06 10:08:00 +08:00
Tim
7421ec8984 feat: switch dropdown icons to IconPark 2025-09-06 10:07:42 +08:00
tim
90b9d75da2 fix: baseplaceholder修改 2025-09-06 02:05:29 +08:00
Tim
d69b094a7b Merge pull request #894 from nagisa77/codex/migrate-components-to-iconpark
refactor: migrate placeholders to IconPark
2025-09-06 02:02:51 +08:00
Tim
67d80a4edd Merge branch 'feature/icon_park' into codex/migrate-components-to-iconpark 2025-09-06 02:02:39 +08:00
Tim
78498c0ac3 refactor: migrate placeholders to IconPark 2025-09-06 02:02:02 +08:00
tim
47c997ad22 fix: baseinput 适配icon 2025-09-06 02:00:58 +08:00
tim
2cd220e8eb Merge branch 'feature/icon_park' of github.com:nagisa77/OpenIsle into feature/icon_park
# Conflicts:
#	frontend_nuxt/plugins/iconpark.client.ts
2025-09-06 01:57:05 +08:00
tim
8023fa1810 feat: add few icons 2025-09-06 01:56:21 +08:00
Tim
04b1b32b9c Merge pull request #893 from nagisa77/codex/migrate-baseinput-components-to-iconpark
feat(frontend): migrate BaseInput to IconPark
2025-09-06 01:56:05 +08:00
Tim
f5d8f37f96 feat(frontend): migrate BaseInput to IconPark 2025-09-06 01:55:50 +08:00
Tim
4a4c256568 Merge pull request #892 from nagisa77/codex/adapt-basetabs-to-use-iconpark
feat: use iconpark in base tabs
2025-09-06 01:42:43 +08:00
Tim
3bb14ca6a3 feat: use iconpark in base tabs 2025-09-06 01:42:15 +08:00
Palm Civet
080ec97943 fix: conditional overview 2025-09-06 01:25:39 +08:00
Palm Civet
29232afadc docs: 引入 Fumadocs
ci: set up github actions
2025-09-06 01:10:52 +08:00
Tim
4ed679c4f4 Merge pull request #890 from nagisa77/codex/adapt-menucomponent-and-headercomponent-for-iconpark
refactor: support iconpark in menu and header
2025-09-05 22:22:18 +08:00
Tim
50848e0da1 refactor: support iconpark in menu and header 2025-09-05 22:20:46 +08:00
tim
51819913a0 feat: user info page 2025-09-05 22:18:57 +08:00
tim
741bd115d5 feat: add few icons 2025-09-05 22:11:14 +08:00
Tim
d13ee2257f feat: 表情新增 2025-09-05 18:01:38 +08:00
Tim
06dea47bec feat: 引入iconpark并修改部分icon 2025-09-05 17:48:41 +08:00
wangshun
dbd322807d 功能追加:显示在线人数 2025-09-05 16:24:09 +08:00
Tim
f89a17f14d Merge pull request #887 from nagisa77/feature/lottery_ui
fix: 抽奖右上角统一文字icon颜色以及间距 #871
2025-09-05 15:33:51 +08:00
Tim
ac433d6a45 fix: 抽奖右上角统一文字icon颜色以及间距 #871 2025-09-05 15:32:53 +08:00
Tim
62e7795e11 Merge pull request #886 from nagisa77/feature/reply_ui
fix: 回复ui重新调整
2025-09-05 14:50:05 +08:00
Tim
35c6d29b8f feat: allow redis db override 2025-09-05 11:31:44 +08:00
97 changed files with 2067 additions and 288 deletions

40
.github/workflows/deploy-docs.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
name: Deploy Documentation
on:
push:
workflow_dispatch:
permissions:
contents: write
jobs:
build-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 1
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install Bun dependencies
run: bun install
working-directory: ./docs
- name: Generate API MDX
run: bun run generate
working-directory: ./docs
- name: Build documentation
run: bun run build
working-directory: ./docs
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: ./docs/out

2
.gitignore vendored
View File

@@ -21,6 +21,8 @@ dist
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-lock.yaml
pnpm-workspace.yaml
# env
*.env

View File

@@ -70,7 +70,9 @@ SERVER_PORT=8082
#### 配置 IDEA 参数
- 设置 JDK 版本为 java 17
- 设置 VM Option最好运行在其他端口非 `8080`,这里设置 `8081`
若上面在环境变量中设置了端口,那这里就不需要再额外设置
```shell
-Dserver.port=8081
@@ -101,14 +103,27 @@ SERVER_PORT=8082
```
3. 执行 [`db/init/init_script.sql`](backend/src/main/resources/db/init/init_script.sql) 脚本,导入基本的数据
管理员:**admin/123456**
普通用户1**user1/123456**
普通用户2**user2/123456**
![初始化脚本](assets/contributing/resources_img.png)
4. 处理完环境问题直接跑起来就能通了
#### 配置 Redis
![运行画面](assets/contributing/backend_img_4.png)
填写环境变量 `.env` 中的 Redis 相关配置并启动 Redis
```ini
REDIS_HOST=<Redis 地址>
REDIS_PORT=<Redis 端口>
```
处理完环境问题直接跑起来就能通了
![运行画面](assets/contributing/backend_img_4.png)
### Docker 环境
#### 配置环境变量
```shell
@@ -177,6 +192,8 @@ cd frontend_nuxt/
cp .env.dev.example .env
```
若依赖本机部署的后端,需要修改 `.env` 中的 `NUXT_PUBLIC_API_BASE_URL` 值与后端服务端口一致
### 安装依赖和运行
前端安装依赖并启动服务。
@@ -193,7 +210,7 @@ npm run dev
## 其他配置
配置第三方登录,这里以 GitHub 为例:
### 配置第三方登录,这里以 GitHub 为例:
- 修改 `application.properties` 配置
@@ -208,3 +225,24 @@ npm run dev
![github配置](assets/contributing/github_img.png)
![github配置2](assets/contributing/github_img_2.png)
### 配置 Resend 邮箱服务
https://resend.com/emails 创建账号并登录
- `Domains` -> `Add Domain`
![image-20250906150459400](assets/contributing/image-20250906150459400.png)
- 填写域名
![image-20250906150541817](assets/contributing/image-20250906150541817.png)
- 等待一段时间后解析成功,创建 key
`API Keys` -> `Create API Key`,输入名称,设置 `Permission` 为 `Sending access`
**Key 只能查看一次,务必保存下来**
![image-20250906150811572](assets/contributing/image-20250906150811572.png)
![image-20250906150924975](assets/contributing/image-20250906150924975.png)
![image-20250906150944130](assets/contributing/image-20250906150944130.png)
- 修改 `.env` 配置中的 `RESEND_API_KEY` 和 `RESEND_FROM_EMAIL`
`RESEND_FROM_EMAIL` **noreply@域名**
`RESEND_API_KEY`**刚刚复制的 Key**
![image-20250906151218330](assets/contributing/image-20250906151218330.png)

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -13,8 +13,13 @@ JWT_RESET_SECRET=<jwt reset secret>
JWT_INVITE_SECRET=<jwt invite secret>
JWT_EXPIRATION=2592000000
# === Redis ===
REDIS_HOST=<Redis 地址>
REDIS_PORT=<Redis 端口>
# === Resend ===
RESEND_API_KEY=<你的resend-api-key>
RESEND_FROM_EMAIL=<你的 resend 发送邮箱>
# === COS ===
# COS_BASE_URL=https://<你的cos>.cos.ap-guangzhou.myqcloud.com

View File

@@ -22,6 +22,8 @@ import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* Redis 缓存配置类
@@ -36,6 +38,8 @@ public class CachingConfig {
public static final String TAG_CACHE_NAME="openisle_tags";
// 分类缓存名
public static final String CATEGORY_CACHE_NAME="openisle_categories";
// 在线人数缓存名
public static final String ONLINE_CACHE_NAME="openisle_online";
/**
* 自定义Redis的序列化器
@@ -78,13 +82,16 @@ public class CachingConfig {
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.disableCachingNullValues(); // 禁止缓存 null 值
// 个别缓存单独设置TTL时间
// Map<String, RedisCacheConfiguration> cacheConfigs = new HashMap<>();
// cacheConfigs.put("openisle_tags", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ZERO));
// cacheConfigs.put("openisle_categories", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ZERO));
// 个别缓存单独设置 TTL 时间
Map<String, RedisCacheConfiguration> cacheConfigs = new HashMap<>();
RedisCacheConfiguration oneHourConfig = config.entryTtl(Duration.ofHours(1));
cacheConfigs.put(TAG_CACHE_NAME, oneHourConfig);
cacheConfigs.put(CATEGORY_CACHE_NAME, oneHourConfig);
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.withInitialCacheConfigurations(cacheConfigs)
.build();
}

View File

@@ -129,6 +129,8 @@ public class SecurityConfig {
.requestMatchers(HttpMethod.GET, "/api/sitemap.xml").permitAll()
.requestMatchers(HttpMethod.GET, "/api/channels").permitAll()
.requestMatchers(HttpMethod.GET, "/api/rss").permitAll()
.requestMatchers(HttpMethod.GET, "/api/online/**").permitAll()
.requestMatchers(HttpMethod.POST, "/api/online/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/point-goods").permitAll()
.requestMatchers(HttpMethod.POST, "/api/point-goods").permitAll()
.requestMatchers(HttpMethod.POST, "/api/categories/**").hasAuthority("ADMIN")
@@ -183,7 +185,8 @@ public class SecurityConfig {
}
} else if (!uri.startsWith("/api/auth") && !publicGet
&& !uri.startsWith("/api/ws") && !uri.startsWith("/api/sockjs")
&& !uri.startsWith("/api/v3/api-docs")) {
&& !uri.startsWith("/api/v3/api-docs")
&& !uri.startsWith("/api/online")) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json");
response.getWriter().write("{\"error\": \"Missing token\"}");

View File

@@ -0,0 +1,33 @@
package com.openisle.controller;
import com.openisle.config.CachingConfig;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import java.time.Duration;
/**
* @author smallclover
* @since 2025-09-05
* 统计在线人数
*/
@RestController
@RequestMapping("/api/online")
@RequiredArgsConstructor
public class OnlineController {
private final RedisTemplate redisTemplate;
private static final String ONLINE_KEY = CachingConfig.ONLINE_CACHE_NAME +":";
@PostMapping("/heartbeat")
public void ping(@RequestParam String userId){
redisTemplate.opsForValue().set(ONLINE_KEY+userId,"1", Duration.ofSeconds(150));
}
@GetMapping("/count")
public long count(){
return redisTemplate.keys(ONLINE_KEY+"*").size();
}
}

View File

@@ -18,6 +18,9 @@ public class ResendEmailSender extends EmailSender {
@Value("${resend.api.key}")
private String apiKey;
@Value("${resend.from.email}")
private String fromEmail;
private final RestTemplate restTemplate = new RestTemplate();
@Override
@@ -33,7 +36,7 @@ public class ResendEmailSender extends EmailSender {
body.put("to", to);
body.put("subject", subject);
body.put("text", text);
body.put("from", "openisle <noreply@chenjiating.com>"); // todo(tim): use config
body.put("from", "openisle <" + fromEmail + ">");
HttpEntity<Map<String, String>> entity = new HttpEntity<>(body, headers);
restTemplate.exchange(url, HttpMethod.POST, entity, String.class);

View File

@@ -12,7 +12,7 @@ spring.jpa.hibernate.ddl-auto=update
# for redis
spring.data.redis.host=${REDIS_HOST:localhost}
spring.data.redis.port=${REDIS_PORT:6379}
spring.data.redis.database=0
spring.data.redis.database=${REDIS_DATABASE:0}
# for jwt
app.jwt.secret=${JWT_SECRET:jwt_sec}
@@ -56,8 +56,10 @@ app.captcha.comment-enabled=${CAPTCHA_COMMENT_ENABLED:false}
# ========= Optional =========
# for resend email send service, you can improve your service by yourself
resend.api.key=${RESEND_API_KEY:}
resend.from.email=${RESEND_FROM_EMAIL:}
# your email services: ...
# for tencent cloud image upload service, you can improve your service by yourself
cos.base-url=${:https://example.com}
cos.secret-id=${COS_SECRET_ID:}

View File

@@ -35,9 +35,9 @@ DELETE FROM `users`;
-- 插入用户,两个普通用户,一个管理员
-- username:admin/user1/user2 password:123321
INSERT INTO `users` (`id`, `approved`, `avatar`, `created_at`, `display_medal`, `email`, `experience`, `introduction`, `password`, `password_reset_code`, `point`, `register_reason`, `role`, `username`, `verification_code`, `verified`) VALUES
(1, b'1', '', '2025-09-01 16:08:17.426430', 'PIONEER', 'adminmail@openisle.com', 70, NULL, '$2a$10$m.lLbT3wFtnzFMi7JqN17ecv/dzH704WzU1f/xvQ0nVz4XxTXPT0K', NULL, 110, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'ADMIN', 'admin', NULL, b'1'),
(2, b'1', '', '2025-09-03 16:08:17.426430', 'PIONEER', 'usermail2@openisle.com', 70, NULL, '$2a$10$m.lLbT3wFtnzFMi7JqN17ecv/dzH704WzU1f/xvQ0nVz4XxTXPT0K', NULL, 110, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user1', NULL, b'1'),
(3, b'1', '', '2025-09-02 17:21:21.617666', 'PIONEER', 'usermail1@openisle.com', 40, NULL, '$2a$10$m.lLbT3wFtnzFMi7JqN17ecv/dzH704WzU1f/xvQ0nVz4XxTXPT0K', NULL, 40, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user2', NULL, b'1');
(1, b'1', '', '2025-09-01 16:08:17.426430', 'PIONEER', 'adminmail@openisle.com', 70, NULL, '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'ADMIN', 'admin', NULL, b'1'),
(2, b'1', '', '2025-09-03 16:08:17.426430', 'PIONEER', 'usermail2@openisle.com', 70, NULL, '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 110, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user1', NULL, b'1'),
(3, b'1', '', '2025-09-02 17:21:21.617666', 'PIONEER', 'usermail1@openisle.com', 40, NULL, '$2a$10$dux.NXwW09cCsdZ05BgcnOtxVqqjcmnbj3.8xcxGl/iiIlv06y7Oe', NULL, 40, '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试', 'USER', 'user2', NULL, b'1');
-- 创建 tags 表(如果不存在)
CREATE TABLE IF NOT EXISTS `tags` (

9
docs/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
# generated content
.contentlayer
.content-collections
.source
.next/
.vercel
next-env.d.ts
openapi.json
openapi.yaml

21
docs/README.md Normal file
View File

@@ -0,0 +1,21 @@
# OpenIsle Documentation
## 要求
使用 [bun](https://bun.com/) 作为工具链的运行时,版本 1.2+。
使用 [Fumadocs](https://fumadocs.dev/) 作为文档工具。
## 开发调试
```bash
bun install
bun dev
```
## 项目结构
使用以下路由:
- `docs/frontend/` 前端技术文档
- `docs/backend/` 后端技术文档
- `docs/openapi/` 后端 API 文档

View File

@@ -0,0 +1,61 @@
import { source } from '@/lib/source';
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/page';
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { createRelativeLink } from 'fumadocs-ui/mdx';
import { getMDXComponents } from '@/mdx-components';
import { Card, Cards } from 'fumadocs-ui/components/card';
import { getPageTreePeers } from 'fumadocs-core/server';
function DocsCategory({ url }: { url: string }) {
return (
<Cards>
{getPageTreePeers(source.pageTree, url).map((peer) => (
<Card key={peer.url} title={peer.name} href={peer.url}>
<span className="font-mono">{peer.url}</span>
</Card>
))}
</Cards>
);
}
export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
const params = await props.params;
const page = source.getPage(params.slug);
if (!page) notFound();
const MDXContent = page.data.body;
return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription>{page.data.description}</DocsDescription>
<DocsBody>
<MDXContent
components={getMDXComponents({
// this allows you to link to other pages with relative file paths
a: createRelativeLink(source, page),
})}
/>
{page.data.full ? null : <DocsCategory url={page.url} />}
</DocsBody>
</DocsPage>
);
}
export async function generateStaticParams() {
return source.generateParams();
}
export async function generateMetadata(
props: PageProps<'/docs/[[...slug]]'>
): Promise<Metadata> {
const params = await props.params;
const page = source.getPage(params.slug);
if (!page) notFound();
return {
title: page.data.title,
description: page.data.description,
};
}

View File

@@ -0,0 +1,77 @@
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { baseOptions } from '@/lib/layout.shared';
import { source } from '@/lib/source';
import { CodeXmlIcon, CompassIcon, ServerIcon } from 'lucide-react';
function TabIcon({
color = 'var(--color-fd-foreground)',
children,
}: {
color?: string;
children: React.ReactNode;
}) {
return (
<div
className="[&_svg]:size-full rounded-lg size-full text-(--tab-color) max-md:bg-(--tab-color)/10 max-md:border max-md:p-1.5"
style={
{
'--tab-color': color,
} as React.CSSProperties
}
>
{children}
</div>
);
}
function TabTitle({ children }: { children: React.ReactNode }) {
return <span className="text-[11px]">{children}</span>;
}
export default function Layout({ children }: LayoutProps<'/docs'>) {
return (
// @ts-ignore
<DocsLayout
tree={source.pageTree}
sidebar={{
defaultOpenLevel: 1,
prefetch: true,
tabs: [
{
title: 'OpenIsle 前端',
description: <TabTitle></TabTitle>,
url: '/docs/frontend',
icon: (
<TabIcon color="#4ca154">
<CompassIcon />
</TabIcon>
),
},
{
title: 'OpenIsle 后端',
description: <TabTitle></TabTitle>,
url: '/docs/backend',
icon: (
<TabIcon color="#1f66f4">
<ServerIcon />
</TabIcon>
),
},
{
title: 'OpenIsle API',
description: <TabTitle> API </TabTitle>,
url: '/docs/openapi',
icon: (
<TabIcon color="#677489">
<CodeXmlIcon />
</TabIcon>
),
},
],
}}
{...baseOptions()}
>
{children}
</DocsLayout>
);
}

4
docs/app/global.css Normal file
View File

@@ -0,0 +1,4 @@
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
@import 'fumadocs-openapi/css/preset.css';

17
docs/app/layout.tsx Normal file
View File

@@ -0,0 +1,17 @@
import '@/app/global.css';
import { Provider } from '@/app/provider';
import { Inter } from 'next/font/google';
const inter = Inter({
subsets: ['latin'],
});
export default function Layout({ children }: LayoutProps<'/docs'>) {
return (
<html lang="zh" className={inter.className} suppressHydrationWarning>
<body className="flex flex-col min-h-screen">
<Provider>{children}</Provider>
</body>
</html>
);
}

8
docs/app/provider.tsx Normal file
View File

@@ -0,0 +1,8 @@
'use client';
import { RootProvider } from 'fumadocs-ui/provider';
import type { ReactNode } from 'react';
export function Provider({ children }: { children: ReactNode }) {
return <RootProvider>{children}</RootProvider>;
}

844
docs/bun.lock Normal file
View File

@@ -0,0 +1,844 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "openisle-docs",
"dependencies": {
"fumadocs-core": "15.7.7",
"fumadocs-mdx": "11.8.2",
"fumadocs-openapi": "^9.3.4",
"fumadocs-ui": "15.7.7",
"lucide-react": "^0.542.0",
"next": "15.5.2",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"shiki": "^3.12.1",
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.12",
"@types/mdx": "^2.0.13",
"@types/node": "24.3.0",
"@types/react": "^19.1.12",
"@types/react-dom": "^19.1.9",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.12",
"typescript": "^5.9.2",
},
},
},
"packages": {
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
"@apidevtools/json-schema-ref-parser": ["@apidevtools/json-schema-ref-parser@11.9.3", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0" } }, "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ=="],
"@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="],
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.9", "", { "os": "aix", "cpu": "ppc64" }, "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.9", "", { "os": "android", "cpu": "arm" }, "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ=="],
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.9", "", { "os": "android", "cpu": "arm64" }, "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg=="],
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.9", "", { "os": "android", "cpu": "x64" }, "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw=="],
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg=="],
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ=="],
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.9", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q=="],
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.9", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg=="],
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.9", "", { "os": "linux", "cpu": "arm" }, "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw=="],
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw=="],
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.9", "", { "os": "linux", "cpu": "ia32" }, "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A=="],
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ=="],
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA=="],
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.9", "", { "os": "linux", "cpu": "ppc64" }, "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w=="],
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg=="],
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.9", "", { "os": "linux", "cpu": "s390x" }, "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA=="],
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.9", "", { "os": "linux", "cpu": "x64" }, "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg=="],
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q=="],
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.9", "", { "os": "none", "cpu": "x64" }, "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g=="],
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.9", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ=="],
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.9", "", { "os": "openbsd", "cpu": "x64" }, "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA=="],
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg=="],
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.9", "", { "os": "sunos", "cpu": "x64" }, "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw=="],
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ=="],
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.9", "", { "os": "win32", "cpu": "ia32" }, "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww=="],
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.9", "", { "os": "win32", "cpu": "x64" }, "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ=="],
"@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="],
"@floating-ui/dom": ["@floating-ui/dom@1.7.4", "", { "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA=="],
"@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.6", "", { "dependencies": { "@floating-ui/dom": "^1.7.4" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw=="],
"@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="],
"@formatjs/intl-localematcher": ["@formatjs/intl-localematcher@0.6.1", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-ePEgLgVCqi2BBFnTMWPfIghu6FkbZnnBVhO2sSxvLfrdFw7wCHAHiDoM2h4NRgjbaY7+B7HgOLZGkK187pZTZg=="],
"@fumari/json-schema-to-typescript": ["@fumari/json-schema-to-typescript@1.1.3", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^11.9.3", "js-yaml": "^4.1.0", "prettier": "^3.5.3" } }, "sha512-KnaZAo5W769nOaxhPqEMTdjHdngugxmPpNS+Yr2U90iVxgmNAWwhSr8Nx3l+CUehJKNFzJi2C7clQXOfuPJegA=="],
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.0" }, "os": "darwin", "cpu": "arm64" }, "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg=="],
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.0" }, "os": "darwin", "cpu": "x64" }, "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA=="],
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ=="],
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg=="],
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.0", "", { "os": "linux", "cpu": "arm" }, "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw=="],
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA=="],
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ=="],
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw=="],
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg=="],
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q=="],
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.0", "", { "os": "linux", "cpu": "x64" }, "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q=="],
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.0" }, "os": "linux", "cpu": "arm" }, "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A=="],
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.0" }, "os": "linux", "cpu": "arm64" }, "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA=="],
"@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.0" }, "os": "linux", "cpu": "ppc64" }, "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA=="],
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.0" }, "os": "linux", "cpu": "s390x" }, "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ=="],
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.0" }, "os": "linux", "cpu": "x64" }, "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ=="],
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" }, "os": "linux", "cpu": "arm64" }, "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ=="],
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.0" }, "os": "linux", "cpu": "x64" }, "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ=="],
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.3", "", { "dependencies": { "@emnapi/runtime": "^1.4.4" }, "cpu": "none" }, "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg=="],
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ=="],
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw=="],
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.3", "", { "os": "win32", "cpu": "x64" }, "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g=="],
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
"@jsdevtools/ono": ["@jsdevtools/ono@7.1.3", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="],
"@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="],
"@next/env": ["@next/env@15.5.2", "", {}, "sha512-Qe06ew4zt12LeO6N7j8/nULSOe3fMXE4dM6xgpBQNvdzyK1sv5y4oAP3bq4LamrvGCZtmRYnW8URFCeX5nFgGg=="],
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.5.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-8bGt577BXGSd4iqFygmzIfTYizHb0LGWqH+qgIF/2EDxS5JsSdERJKA8WgwDyNBZgTIIA4D8qUtoQHmxIIquoQ=="],
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.5.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-2DjnmR6JHK4X+dgTXt5/sOCu/7yPtqpYt8s8hLkHFK3MGkka2snTv3yRMdHvuRtJVkPwCGsvBSwmoQCHatauFQ=="],
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.5.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-3j7SWDBS2Wov/L9q0mFJtEvQ5miIqfO4l7d2m9Mo06ddsgUK8gWfHGgbjdFlCp2Ek7MmMQZSxpGFqcC8zGh2AA=="],
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.5.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-s6N8k8dF9YGc5T01UPQ08yxsK6fUow5gG1/axWc1HVVBYQBgOjca4oUZF7s4p+kwhkB1bDSGR8QznWrFZ/Rt5g=="],
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.5.2", "", { "os": "linux", "cpu": "x64" }, "sha512-o1RV/KOODQh6dM6ZRJGZbc+MOAHww33Vbs5JC9Mp1gDk8cpEO+cYC/l7rweiEalkSm5/1WGa4zY7xrNwObN4+Q=="],
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.5.2", "", { "os": "linux", "cpu": "x64" }, "sha512-/VUnh7w8RElYZ0IV83nUcP/J4KJ6LLYliiBIri3p3aW2giF+PAVgZb6mk8jbQSB3WlTai8gEmCAr7kptFa1H6g=="],
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.5.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-sMPyTvRcNKXseNQ/7qRfVRLa0VhR0esmQ29DD6pqvG71+JdVnESJaHPA8t7bc67KD5spP3+DOCNLhqlEI2ZgQg=="],
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.5.2", "", { "os": "win32", "cpu": "x64" }, "sha512-W5VvyZHnxG/2ukhZF/9Ikdra5fdNftxI6ybeVKYvBPDtyx7x4jPPSNduUkfH5fo3zG0JQ0bPxgy41af2JX5D4Q=="],
"@orama/orama": ["@orama/orama@3.1.13", "", {}, "sha512-O0hdKt4K31i8fpq8Bw5RfdPVAqm0EdduBUcluPo2MRcfCOwUEf5JlnvRhf/J0ezOYOD8jQ/LumYZxOVi/XK/BA=="],
"@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
"@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collapsible": "1.1.12", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA=="],
"@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="],
"@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA=="],
"@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
"@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
"@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
"@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw=="],
"@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
"@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="],
"@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="],
"@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="],
"@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
"@radix-ui/react-navigation-menu": ["@radix-ui/react-navigation-menu@1.2.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w=="],
"@radix-ui/react-popover": ["@radix-ui/react-popover@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA=="],
"@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.8", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw=="],
"@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="],
"@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
"@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA=="],
"@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.10", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A=="],
"@radix-ui/react-select": ["@radix-ui/react-select@2.2.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ=="],
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="],
"@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
"@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
"@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="],
"@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
"@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
"@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ=="],
"@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="],
"@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="],
"@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.3", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug=="],
"@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="],
"@scalar/openapi-parser": ["@scalar/openapi-parser@0.18.3", "", { "dependencies": { "@scalar/openapi-types": "0.3.7", "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", "ajv-formats": "^3.0.1", "jsonpointer": "^5.0.1", "leven": "^4.0.0", "yaml": "2.8.0" } }, "sha512-j0OM3Y3JTVx50m7r5ogoADe2pT/ewhAnO7knjkcm7b+vjgKRpgjUMhXsYraBemFkqd2dNa1QfTX/mDVv7wEr9A=="],
"@scalar/openapi-types": ["@scalar/openapi-types@0.3.7", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-QHSvHBVDze3+dUwAhIGq6l1iOev4jdoqdBK7QpfeN1Q4h+6qpVEw3EEqBiH0AXUSh/iWwObBv4uMgfIx0aNZ5g=="],
"@shikijs/core": ["@shikijs/core@3.12.2", "", { "dependencies": { "@shikijs/types": "3.12.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-L1Safnhra3tX/oJK5kYHaWmLEBJi1irASwewzY3taX5ibyXyMkkSDZlq01qigjryOBwrXSdFgTiZ3ryzSNeu7Q=="],
"@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.12.2", "", { "dependencies": { "@shikijs/types": "3.12.2", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-Nm3/azSsaVS7hk6EwtHEnTythjQfwvrO5tKqMlaH9TwG1P+PNaR8M0EAKZ+GaH2DFwvcr4iSfTveyxMIvXEHMw=="],
"@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.12.2", "", { "dependencies": { "@shikijs/types": "3.12.2", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w=="],
"@shikijs/langs": ["@shikijs/langs@3.12.2", "", { "dependencies": { "@shikijs/types": "3.12.2" } }, "sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww=="],
"@shikijs/rehype": ["@shikijs/rehype@3.12.2", "", { "dependencies": { "@shikijs/types": "3.12.2", "@types/hast": "^3.0.4", "hast-util-to-string": "^3.0.1", "shiki": "3.12.2", "unified": "^11.0.5", "unist-util-visit": "^5.0.0" } }, "sha512-9wg+FKv0ByaQScTonpZdrDhADOoJP/yCWLAuiYYG6GehwNV5rGwnLvWKj33UmtLedKMSHzWUdB+Un6rfDFo/FA=="],
"@shikijs/themes": ["@shikijs/themes@3.12.2", "", { "dependencies": { "@shikijs/types": "3.12.2" } }, "sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A=="],
"@shikijs/transformers": ["@shikijs/transformers@3.12.2", "", { "dependencies": { "@shikijs/core": "3.12.2", "@shikijs/types": "3.12.2" } }, "sha512-+z1aMq4N5RoNGY8i7qnTYmG2MBYzFmwkm/yOd6cjEI7OVzcldVvzQCfxU1YbIVgsyB0xHVc2jFe1JhgoXyUoSQ=="],
"@shikijs/types": ["@shikijs/types@3.12.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q=="],
"@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
"@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
"@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
"@tailwindcss/node": ["@tailwindcss/node@4.1.13", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.5.1", "lightningcss": "1.30.1", "magic-string": "^0.30.18", "source-map-js": "^1.2.1", "tailwindcss": "4.1.13" } }, "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw=="],
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.13", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.13", "@tailwindcss/oxide-darwin-arm64": "4.1.13", "@tailwindcss/oxide-darwin-x64": "4.1.13", "@tailwindcss/oxide-freebsd-x64": "4.1.13", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.13", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.13", "@tailwindcss/oxide-linux-arm64-musl": "4.1.13", "@tailwindcss/oxide-linux-x64-gnu": "4.1.13", "@tailwindcss/oxide-linux-x64-musl": "4.1.13", "@tailwindcss/oxide-wasm32-wasi": "4.1.13", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.13", "@tailwindcss/oxide-win32-x64-msvc": "4.1.13" } }, "sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA=="],
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.13", "", { "os": "android", "cpu": "arm64" }, "sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew=="],
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ=="],
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw=="],
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.13", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ=="],
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13", "", { "os": "linux", "cpu": "arm" }, "sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw=="],
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ=="],
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg=="],
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.13", "", { "os": "linux", "cpu": "x64" }, "sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ=="],
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.13", "", { "os": "linux", "cpu": "x64" }, "sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ=="],
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.13", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@emnapi/wasi-threads": "^1.0.4", "@napi-rs/wasm-runtime": "^0.2.12", "@tybys/wasm-util": "^0.10.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA=="],
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg=="],
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.13", "", { "os": "win32", "cpu": "x64" }, "sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw=="],
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.13", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.13", "@tailwindcss/oxide": "4.1.13", "postcss": "^8.4.41", "tailwindcss": "4.1.13" } }, "sha512-HLgx6YSFKJT7rJqh9oJs/TkBFhxuMOfUKSBEPYwV+t78POOBsdQ7crhZLzwcH3T0UyUuOzU/GK5pk5eKr3wCiQ=="],
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
"@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
"@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
"@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
"@types/mdx": ["@types/mdx@2.0.13", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="],
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
"@types/node": ["@types/node@24.3.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow=="],
"@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="],
"@types/react-dom": ["@types/react-dom@19.1.9", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ=="],
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
"ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
"ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="],
"ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
"aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],
"astring": ["astring@1.9.0", "", { "bin": { "astring": "bin/astring" } }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="],
"bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
"caniuse-lite": ["caniuse-lite@1.0.30001741", "", {}, "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw=="],
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
"character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],
"character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="],
"character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="],
"character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="],
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
"class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
"client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
"collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="],
"color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
"compute-scroll-into-view": ["compute-scroll-into-view@3.1.1", "", {}, "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw=="],
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
"decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="],
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
"detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
"detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="],
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
"enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
"esast-util-from-estree": ["esast-util-from-estree@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "unist-util-position-from-estree": "^2.0.0" } }, "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ=="],
"esast-util-from-js": ["esast-util-from-js@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "acorn": "^8.0.0", "esast-util-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw=="],
"esbuild": ["esbuild@0.25.9", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.9", "@esbuild/android-arm": "0.25.9", "@esbuild/android-arm64": "0.25.9", "@esbuild/android-x64": "0.25.9", "@esbuild/darwin-arm64": "0.25.9", "@esbuild/darwin-x64": "0.25.9", "@esbuild/freebsd-arm64": "0.25.9", "@esbuild/freebsd-x64": "0.25.9", "@esbuild/linux-arm": "0.25.9", "@esbuild/linux-arm64": "0.25.9", "@esbuild/linux-ia32": "0.25.9", "@esbuild/linux-loong64": "0.25.9", "@esbuild/linux-mips64el": "0.25.9", "@esbuild/linux-ppc64": "0.25.9", "@esbuild/linux-riscv64": "0.25.9", "@esbuild/linux-s390x": "0.25.9", "@esbuild/linux-x64": "0.25.9", "@esbuild/netbsd-arm64": "0.25.9", "@esbuild/netbsd-x64": "0.25.9", "@esbuild/openbsd-arm64": "0.25.9", "@esbuild/openbsd-x64": "0.25.9", "@esbuild/openharmony-arm64": "0.25.9", "@esbuild/sunos-x64": "0.25.9", "@esbuild/win32-arm64": "0.25.9", "@esbuild/win32-ia32": "0.25.9", "@esbuild/win32-x64": "0.25.9" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g=="],
"escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
"esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],
"estree-util-attach-comments": ["estree-util-attach-comments@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw=="],
"estree-util-build-jsx": ["estree-util-build-jsx@3.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-walker": "^3.0.0" } }, "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ=="],
"estree-util-is-identifier-name": ["estree-util-is-identifier-name@3.0.0", "", {}, "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg=="],
"estree-util-scope": ["estree-util-scope@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0" } }, "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ=="],
"estree-util-to-js": ["estree-util-to-js@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "astring": "^1.8.0", "source-map": "^0.7.0" } }, "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg=="],
"estree-util-value-to-estree": ["estree-util-value-to-estree@3.4.0", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-Zlp+gxis+gCfK12d3Srl2PdX2ybsEA8ZYy6vQGVQTNNYLEGRQQ56XB64bjemN8kxIKXP1nC9ip4Z+ILy9LGzvQ=="],
"estree-util-visit": ["estree-util-visit@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/unist": "^3.0.0" } }, "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww=="],
"estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
"extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="],
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
"fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
"fast-xml-parser": ["fast-xml-parser@4.5.3", "", { "dependencies": { "strnum": "^1.1.1" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig=="],
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
"foreach": ["foreach@2.0.6", "", {}, "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg=="],
"fumadocs-core": ["fumadocs-core@15.7.7", "", { "dependencies": { "@formatjs/intl-localematcher": "^0.6.1", "@orama/orama": "^3.1.12", "@shikijs/rehype": "^3.12.0", "@shikijs/transformers": "^3.12.0", "github-slugger": "^2.0.0", "hast-util-to-estree": "^3.1.3", "hast-util-to-jsx-runtime": "^2.3.6", "image-size": "^2.0.2", "negotiator": "^1.0.0", "npm-to-yarn": "^3.0.1", "react-remove-scroll": "^2.7.1", "remark": "^15.0.0", "remark-gfm": "^4.0.1", "remark-rehype": "^11.1.2", "scroll-into-view-if-needed": "^3.1.0", "shiki": "^3.12.0", "unist-util-visit": "^5.0.0" }, "peerDependencies": { "@mixedbread/sdk": "^0.19.0", "@oramacloud/client": "1.x.x || 2.x.x", "@types/react": "*", "algoliasearch": "5.x.x", "next": "14.x.x || 15.x.x", "react": "18.x.x || 19.x.x", "react-dom": "18.x.x || 19.x.x", "react-router": "7.x.x" }, "optionalPeers": ["@mixedbread/sdk", "@oramacloud/client", "@types/react", "algoliasearch", "next", "react", "react-dom", "react-router"] }, "sha512-4mo8y1L2VV9TcrQ1gses3c5zzCaPwDPYjfrPET4Qf+m7GPOqZ7wiUeXMTYb98T+N5wS0G/fsr/xFPZkgwD44gQ=="],
"fumadocs-mdx": ["fumadocs-mdx@11.8.2", "", { "dependencies": { "@mdx-js/mdx": "^3.1.0", "@standard-schema/spec": "^1.0.0", "chokidar": "^4.0.3", "esbuild": "^0.25.9", "estree-util-value-to-estree": "^3.4.0", "js-yaml": "^4.1.0", "lru-cache": "^11.1.0", "picocolors": "^1.1.1", "remark-mdx": "^3.1.0", "remark-parse": "^11.0.0", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.14", "unified": "^11.0.5", "unist-util-visit": "^5.0.0", "zod": "^4.1.4" }, "peerDependencies": { "@fumadocs/mdx-remote": "^1.4.0", "fumadocs-core": "^14.0.0 || ^15.0.0", "next": "^15.3.0", "react": "*", "vite": "6.x.x || 7.x.x" }, "optionalPeers": ["@fumadocs/mdx-remote", "next", "react", "vite"], "bin": { "fumadocs-mdx": "bin.js" } }, "sha512-omv2jNrdXfZiAC2p6YeO3y3GYyQesMRzvsCDdgf7L/MbPIfgvtPkmRG2kL42dFEVsi45zwj0UugX6AG5IhDuUQ=="],
"fumadocs-openapi": ["fumadocs-openapi@9.3.6", "", { "dependencies": { "@fumari/json-schema-to-typescript": "^1.1.3", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-slot": "^1.2.3", "@scalar/openapi-parser": "0.18.3", "ajv": "^8.17.1", "class-variance-authority": "^0.7.1", "fumadocs-core": "15.7.9", "fumadocs-ui": "15.7.9", "github-slugger": "^2.0.0", "gray-matter": "^4.0.3", "hast-util-to-jsx-runtime": "^2.3.6", "js-yaml": "^4.1.0", "next-themes": "^0.4.6", "openapi-sampler": "^1.6.1", "react-hook-form": "^7.62.0", "remark": "^15.0.1", "remark-rehype": "^11.1.2", "shiki": "^3.12.0", "tinyglobby": "^0.2.14", "xml-js": "^1.6.11" }, "peerDependencies": { "@scalar/api-client-react": "*", "@types/react": "*", "react": "18.x.x || 19.x.x", "react-dom": "18.x.x || 19.x.x" }, "optionalPeers": ["@scalar/api-client-react", "@types/react"] }, "sha512-ndgqMTBvdoE6GmYpELcdLbixopqC6396vk4/OVu2P/6gbScqy33mP+XpGMxw4JzvTW6/cuhkbc8XyC0VkqZWuA=="],
"fumadocs-ui": ["fumadocs-ui@15.7.7", "", { "dependencies": { "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-direction": "^1.1.1", "@radix-ui/react-navigation-menu": "^1.2.14", "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-presence": "^1.1.5", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-tabs": "^1.1.13", "class-variance-authority": "^0.7.1", "fumadocs-core": "15.7.7", "lodash.merge": "^4.6.2", "next-themes": "^0.4.6", "postcss-selector-parser": "^7.1.0", "react-medium-image-zoom": "^5.3.0", "scroll-into-view-if-needed": "^3.1.0", "tailwind-merge": "^3.3.1" }, "peerDependencies": { "@types/react": "*", "next": "14.x.x || 15.x.x", "react": "18.x.x || 19.x.x", "react-dom": "18.x.x || 19.x.x", "tailwindcss": "^3.4.14 || ^4.0.0" }, "optionalPeers": ["@types/react", "next", "tailwindcss"] }, "sha512-nXeEnFI0h+JAbwWsKWcc6aBuR++jWlxhMpXQnPv4zbrrbds436lilrOu/xh5KxPiEe2M9HspKMN+Oee73jHQFw=="],
"get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="],
"github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="],
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
"gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="],
"hast-util-to-estree": ["hast-util-to-estree@3.1.3", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-attach-comments": "^3.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w=="],
"hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
"hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@2.3.6", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" } }, "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg=="],
"hast-util-to-string": ["hast-util-to-string@3.0.1", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A=="],
"hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="],
"html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
"image-size": ["image-size@2.0.2", "", { "bin": { "image-size": "bin/image-size.js" } }, "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w=="],
"inline-style-parser": ["inline-style-parser@0.2.4", "", {}, "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q=="],
"is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="],
"is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="],
"is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
"is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="],
"is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="],
"is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="],
"is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
"jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="],
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
"json-pointer": ["json-pointer@0.6.2", "", { "dependencies": { "foreach": "^2.0.4" } }, "sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw=="],
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
"jsonpointer": ["jsonpointer@5.0.1", "", {}, "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ=="],
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
"leven": ["leven@4.0.0", "", {}, "sha512-puehA3YKku3osqPlNuzGDUHq8WpwXupUg1V6NXdV38G+gr+gkBwFC8g1b/+YcIvp8gnqVIus+eJCH/eGsRmJNw=="],
"lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
"lru-cache": ["lru-cache@11.2.1", "", {}, "sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ=="],
"lucide-react": ["lucide-react@0.542.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-w3hD8/SQB7+lzU2r4VdFyzzOzKnUjTZIF/MQJGSSvni7Llewni4vuViRppfRAa2guOsY5k4jZyxw/i9DQHv+dw=="],
"magic-string": ["magic-string@0.30.18", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ=="],
"markdown-extensions": ["markdown-extensions@2.0.0", "", {}, "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q=="],
"markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="],
"mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="],
"mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA=="],
"mdast-util-gfm": ["mdast-util-gfm@3.1.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ=="],
"mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ=="],
"mdast-util-gfm-footnote": ["mdast-util-gfm-footnote@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0" } }, "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ=="],
"mdast-util-gfm-strikethrough": ["mdast-util-gfm-strikethrough@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg=="],
"mdast-util-gfm-table": ["mdast-util-gfm-table@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "markdown-table": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg=="],
"mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="],
"mdast-util-mdx": ["mdast-util-mdx@3.0.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w=="],
"mdast-util-mdx-expression": ["mdast-util-mdx-expression@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ=="],
"mdast-util-mdx-jsx": ["mdast-util-mdx-jsx@3.2.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q=="],
"mdast-util-mdxjs-esm": ["mdast-util-mdxjs-esm@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg=="],
"mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="],
"mdast-util-to-hast": ["mdast-util-to-hast@13.2.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA=="],
"mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="],
"mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="],
"micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="],
"micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="],
"micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="],
"micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="],
"micromark-extension-gfm-footnote": ["micromark-extension-gfm-footnote@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw=="],
"micromark-extension-gfm-strikethrough": ["micromark-extension-gfm-strikethrough@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw=="],
"micromark-extension-gfm-table": ["micromark-extension-gfm-table@2.1.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg=="],
"micromark-extension-gfm-tagfilter": ["micromark-extension-gfm-tagfilter@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg=="],
"micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw=="],
"micromark-extension-mdx-expression": ["micromark-extension-mdx-expression@3.0.1", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q=="],
"micromark-extension-mdx-jsx": ["micromark-extension-mdx-jsx@3.0.2", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ=="],
"micromark-extension-mdx-md": ["micromark-extension-mdx-md@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ=="],
"micromark-extension-mdxjs": ["micromark-extension-mdxjs@3.0.0", "", { "dependencies": { "acorn": "^8.0.0", "acorn-jsx": "^5.0.0", "micromark-extension-mdx-expression": "^3.0.0", "micromark-extension-mdx-jsx": "^3.0.0", "micromark-extension-mdx-md": "^2.0.0", "micromark-extension-mdxjs-esm": "^3.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ=="],
"micromark-extension-mdxjs-esm": ["micromark-extension-mdxjs-esm@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A=="],
"micromark-factory-destination": ["micromark-factory-destination@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA=="],
"micromark-factory-label": ["micromark-factory-label@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg=="],
"micromark-factory-mdx-expression": ["micromark-factory-mdx-expression@2.0.3", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ=="],
"micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="],
"micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="],
"micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ=="],
"micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="],
"micromark-util-chunked": ["micromark-util-chunked@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA=="],
"micromark-util-classify-character": ["micromark-util-classify-character@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q=="],
"micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.1", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg=="],
"micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.2", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw=="],
"micromark-util-decode-string": ["micromark-util-decode-string@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ=="],
"micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="],
"micromark-util-events-to-acorn": ["micromark-util-events-to-acorn@2.0.3", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg=="],
"micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.1", "", {}, "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="],
"micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q=="],
"micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.1", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg=="],
"micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="],
"micromark-util-subtokenize": ["micromark-util-subtokenize@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA=="],
"micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="],
"micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="],
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
"minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="],
"mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
"next": ["next@15.5.2", "", { "dependencies": { "@next/env": "15.5.2", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.5.2", "@next/swc-darwin-x64": "15.5.2", "@next/swc-linux-arm64-gnu": "15.5.2", "@next/swc-linux-arm64-musl": "15.5.2", "@next/swc-linux-x64-gnu": "15.5.2", "@next/swc-linux-x64-musl": "15.5.2", "@next/swc-win32-arm64-msvc": "15.5.2", "@next/swc-win32-x64-msvc": "15.5.2", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-H8Otr7abj1glFhbGnvUt3gz++0AF1+QoCXEBmd/6aKbfdFwrn0LpA836Ed5+00va/7HQSDD+mOoVhn3tNy3e/Q=="],
"next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="],
"npm-to-yarn": ["npm-to-yarn@3.0.1", "", {}, "sha512-tt6PvKu4WyzPwWUzy/hvPFqn+uwXO0K1ZHka8az3NnrhWJDmSqI8ncWq0fkL0k/lmmi5tAC11FXwXuh0rFbt1A=="],
"oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="],
"oniguruma-to-es": ["oniguruma-to-es@4.3.3", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg=="],
"openapi-sampler": ["openapi-sampler@1.6.1", "", { "dependencies": { "@types/json-schema": "^7.0.7", "fast-xml-parser": "^4.5.0", "json-pointer": "0.6.2" } }, "sha512-s1cIatOqrrhSj2tmJ4abFYZQK6l5v+V4toO5q1Pa0DyN8mtyqy2I+Qrj5W9vOELEtybIMQs/TBZGVO/DtTFK8w=="],
"parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
"postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="],
"prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],
"property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
"react": ["react@19.1.1", "", {}, "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ=="],
"react-dom": ["react-dom@19.1.1", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.1" } }, "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw=="],
"react-hook-form": ["react-hook-form@7.62.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA=="],
"react-medium-image-zoom": ["react-medium-image-zoom@5.3.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-RCIzVlsKqy3BYgGgYbolUfuvx0aSKC7YhX/IJGEp+WJxsqdIVYJHkBdj++FAj6VD7RiWj6VVmdCfa/9vJE9hZg=="],
"react-remove-scroll": ["react-remove-scroll@2.7.1", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA=="],
"react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
"react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
"recma-build-jsx": ["recma-build-jsx@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-build-jsx": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew=="],
"recma-jsx": ["recma-jsx@1.0.1", "", { "dependencies": { "acorn-jsx": "^5.0.0", "estree-util-to-js": "^2.0.0", "recma-parse": "^1.0.0", "recma-stringify": "^1.0.0", "unified": "^11.0.0" }, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w=="],
"recma-parse": ["recma-parse@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "esast-util-from-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ=="],
"recma-stringify": ["recma-stringify@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-to-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g=="],
"regex": ["regex@6.0.1", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA=="],
"regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="],
"regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="],
"rehype-recma": ["rehype-recma@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "hast-util-to-estree": "^3.0.0" } }, "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw=="],
"remark": ["remark@15.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A=="],
"remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="],
"remark-mdx": ["remark-mdx@3.1.1", "", { "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" } }, "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg=="],
"remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="],
"remark-rehype": ["remark-rehype@11.1.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw=="],
"remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="],
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
"sax": ["sax@1.4.1", "", {}, "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="],
"scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
"scroll-into-view-if-needed": ["scroll-into-view-if-needed@3.1.0", "", { "dependencies": { "compute-scroll-into-view": "^3.0.2" } }, "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ=="],
"section-matter": ["section-matter@1.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" } }, "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA=="],
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
"sharp": ["sharp@0.34.3", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.4", "semver": "^7.7.2" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.3", "@img/sharp-darwin-x64": "0.34.3", "@img/sharp-libvips-darwin-arm64": "1.2.0", "@img/sharp-libvips-darwin-x64": "1.2.0", "@img/sharp-libvips-linux-arm": "1.2.0", "@img/sharp-libvips-linux-arm64": "1.2.0", "@img/sharp-libvips-linux-ppc64": "1.2.0", "@img/sharp-libvips-linux-s390x": "1.2.0", "@img/sharp-libvips-linux-x64": "1.2.0", "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", "@img/sharp-libvips-linuxmusl-x64": "1.2.0", "@img/sharp-linux-arm": "0.34.3", "@img/sharp-linux-arm64": "0.34.3", "@img/sharp-linux-ppc64": "0.34.3", "@img/sharp-linux-s390x": "0.34.3", "@img/sharp-linux-x64": "0.34.3", "@img/sharp-linuxmusl-arm64": "0.34.3", "@img/sharp-linuxmusl-x64": "0.34.3", "@img/sharp-wasm32": "0.34.3", "@img/sharp-win32-arm64": "0.34.3", "@img/sharp-win32-ia32": "0.34.3", "@img/sharp-win32-x64": "0.34.3" } }, "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg=="],
"shiki": ["shiki@3.12.2", "", { "dependencies": { "@shikijs/core": "3.12.2", "@shikijs/engine-javascript": "3.12.2", "@shikijs/engine-oniguruma": "3.12.2", "@shikijs/langs": "3.12.2", "@shikijs/themes": "3.12.2", "@shikijs/types": "3.12.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-uIrKI+f9IPz1zDT+GMz+0RjzKJiijVr6WDWm9Pe3NNY6QigKCfifCEv9v9R2mDASKKjzjQ2QpFLcxaR3iHSnMA=="],
"simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="],
"source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
"sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
"stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
"strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g=="],
"strnum": ["strnum@1.1.2", "", {}, "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA=="],
"style-to-js": ["style-to-js@1.1.17", "", { "dependencies": { "style-to-object": "1.0.9" } }, "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA=="],
"style-to-object": ["style-to-object@1.0.9", "", { "dependencies": { "inline-style-parser": "0.2.4" } }, "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw=="],
"styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="],
"tailwind-merge": ["tailwind-merge@3.3.1", "", {}, "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="],
"tailwindcss": ["tailwindcss@4.1.13", "", {}, "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w=="],
"tapable": ["tapable@2.2.3", "", {}, "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg=="],
"tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="],
"tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="],
"tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
"trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
"undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
"unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="],
"unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="],
"unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="],
"unist-util-position-from-estree": ["unist-util-position-from-estree@2.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ=="],
"unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="],
"unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="],
"unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="],
"use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="],
"use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="],
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
"vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
"xml-js": ["xml-js@1.6.11", "", { "dependencies": { "sax": "^1.2.4" }, "bin": { "xml-js": "./bin/cli.js" } }, "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g=="],
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
"yaml": ["yaml@2.8.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ=="],
"zod": ["zod@4.1.5", "", {}, "sha512-rcUUZqlLJgBC33IT3PNMgsCq6TzLQEG/Ei/KTCU0PedSWRMAXoOUN+4t/0H+Q8bdnLPdqUYnvboJT0bn/229qg=="],
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
"@scalar/openapi-types/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" }, "bundled": true }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="],
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"fumadocs-openapi/fumadocs-core": ["fumadocs-core@15.7.9", "", { "dependencies": { "@formatjs/intl-localematcher": "^0.6.1", "@orama/orama": "^3.1.12", "@shikijs/rehype": "^3.12.0", "@shikijs/transformers": "^3.12.0", "github-slugger": "^2.0.0", "hast-util-to-estree": "^3.1.3", "hast-util-to-jsx-runtime": "^2.3.6", "image-size": "^2.0.2", "negotiator": "^1.0.0", "npm-to-yarn": "^3.0.1", "react-remove-scroll": "^2.7.1", "remark": "^15.0.0", "remark-gfm": "^4.0.1", "remark-rehype": "^11.1.2", "scroll-into-view-if-needed": "^3.1.0", "shiki": "^3.12.0", "unist-util-visit": "^5.0.0" }, "peerDependencies": { "@mixedbread/sdk": "^0.19.0", "@oramacloud/client": "1.x.x || 2.x.x", "@tanstack/react-router": "1.x.x", "@types/react": "*", "algoliasearch": "5.x.x", "next": "14.x.x || 15.x.x", "react": "18.x.x || 19.x.x", "react-dom": "18.x.x || 19.x.x", "react-router": "7.x.x", "waku": "^0.26.0" }, "optionalPeers": ["@mixedbread/sdk", "@oramacloud/client", "@tanstack/react-router", "@types/react", "algoliasearch", "next", "react", "react-dom", "react-router", "waku"] }, "sha512-GaD8UXcpJgp0CTXVd+sKL1Qt+tCN5cQsBxOXneGpEzoida4MRS83IphodLsvMqz33uVHJY+J22g8ijTnpgWj4A=="],
"fumadocs-openapi/fumadocs-ui": ["fumadocs-ui@15.7.9", "", { "dependencies": { "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-direction": "^1.1.1", "@radix-ui/react-navigation-menu": "^1.2.14", "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-presence": "^1.1.5", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-tabs": "^1.1.13", "class-variance-authority": "^0.7.1", "fumadocs-core": "15.7.9", "lodash.merge": "^4.6.2", "next-themes": "^0.4.6", "postcss-selector-parser": "^7.1.0", "react-medium-image-zoom": "^5.3.0", "scroll-into-view-if-needed": "^3.1.0", "tailwind-merge": "^3.3.1" }, "peerDependencies": { "@types/react": "*", "next": "14.x.x || 15.x.x", "react": "18.x.x || 19.x.x", "react-dom": "18.x.x || 19.x.x", "tailwindcss": "^3.4.14 || ^4.0.0" }, "optionalPeers": ["@types/react", "next", "tailwindcss"] }, "sha512-6ZOniTWBRB9DSBV6ae2hX+wYNhkzosqN4N2kT2RUGsp2MuPr+pLyKazbUsOj+pSat1BuDZpkBtBa2ht1ky7L2g=="],
"gray-matter/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
"next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
"parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"gray-matter/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
}
}

View File

@@ -0,0 +1,43 @@
---
title: 后端开发
description: OpenIsle 后端服务开发指南
---
# 后端开发
OpenIsle 后端基于 Spring Boot 框架构建,提供完整的 RESTful API 服务。
## 技术栈
- **Spring Boot** - 主框架
- **Spring Security** - 安全认证
- **MyBatis** - 数据访问层
- **MySQL** - 数据库
- **Redis** - 缓存和会话存储
## 项目结构
```
backend/
├── src/main/java/com/
│ ├── controller/ # 控制器层
│ ├── service/ # 业务逻辑层
│ ├── mapper/ # 数据访问层
│ ├── entity/ # 实体类
│ └── config/ # 配置类
└── src/main/resources/
├── application.properties
└── mapper/ # MyBatis 映射文件
```
## 开发环境设置
1. 安装 Java 17+
2. 安装 MySQL 8.0+
3. 安装 Redis
4. 配置数据库连接
5. 启动应用
## API 接口
详细的 API 接口文档请查看 [API 文档](/docs/openapi)。

View File

@@ -0,0 +1,3 @@
{
"root": true
}

View File

@@ -0,0 +1,53 @@
---
title: 前端开发
description: OpenIsle 前端应用开发指南
---
# 前端开发
OpenIsle 前端基于 Nuxt.js 框架构建,提供现代化的用户界面和交互体验。
## 技术栈
- **Nuxt.js** - Vue.js 全栈框架
- **Vue 3** - 前端框架
- **TypeScript** - 类型安全
- **Tailwind CSS** - 样式框架
- **Pinia** - 状态管理
## 项目结构
```
frontend_nuxt/
├── components/ # Vue 组件
├── pages/ # 页面路由
├── composables/ # 组合式函数
├── plugins/ # 插件配置
├── utils/ # 工具函数
└── assets/ # 静态资源
```
## 开发环境设置
1. 安装 Node.js 18+
2. 安装依赖:`npm install`
3. 启动开发服务器:`npm run dev`
4. 访问 http://localhost:3000
## 主要功能
- 用户认证和授权
- 文章发布和管理
- 评论和互动
- 实时消息
- 用户个人资料
- 管理后台
## 组件库
项目使用自定义组件库,主要组件包括:
- `BaseInput` - 输入框组件
- `BasePopup` - 弹窗组件
- `PostEditor` - 文章编辑器
- `CommentEditor` - 评论编辑器

View File

@@ -0,0 +1,3 @@
{
"root": true
}

View File

@@ -0,0 +1,14 @@
---
title: 欢迎使用 OpenIsle
description: OpenIsle 文档首页
---
# 欢迎使用 OpenIsle
OpenIsle 是一个现代化的社区平台,提供完整的社交功能。
## 快速开始
- [后端开发指南](/docs/backend) - 了解后端架构和开发
- [前端开发指南](/docs/frontend) - 了解前端技术栈和组件
- [API 文档](/docs/openapi) - 查看完整的 API 接口文档

View File

@@ -0,0 +1,3 @@
{
"pages": ["index", "frontend", "backend", "openapi"]
}

1
docs/content/docs/openapi/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
(generated)/

View File

@@ -0,0 +1,4 @@
---
title: API 概览
description: Open API 接口文档
---

View File

@@ -0,0 +1,4 @@
{
"pages": ["index", "...(generated)"],
"root": true
}

View File

@@ -0,0 +1,19 @@
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
/**
* Shared layout configurations
*/
export function baseOptions(): BaseLayoutProps {
return {
githubUrl: 'https://github.com/nagisa77/OpenIsle',
nav: {
title: 'OpenIsle Docs',
url: '/docs',
},
searchToggle: {
enabled: false,
},
// see https://fumadocs.dev/docs/ui/navigation/links
links: [],
};
}

View File

@@ -0,0 +1,4 @@
'use client';
// forward them so that Fumadocs can also use your media adapter in a client component
export { OpenIsleMediaAdapter } from './media-adapter';

23
docs/lib/media-adapter.ts Normal file
View File

@@ -0,0 +1,23 @@
import type { MediaAdapter } from 'fumadocs-openapi';
export const OpenIsleMediaAdapter: MediaAdapter = {
encode(data) {
return JSON.stringify(data.body);
},
// returns code that inits a `body` variable, used for request body
generateExample(data, ctx) {
if (ctx.lang === 'js') {
return `const body = "hello world"`;
}
if (ctx.lang === 'python') {
return `body = "hello world"`;
}
if (ctx.lang === 'go' && 'addImport' in ctx) {
ctx.addImport('strings');
return `body := strings.NewReader("hello world")`;
}
},
};

5
docs/lib/openapi.ts Normal file
View File

@@ -0,0 +1,5 @@
import { createOpenAPI } from 'fumadocs-openapi/server';
export const openapi = createOpenAPI({
input: ['https://staging.open-isle.com/api/v3/api-docs'],
});

37
docs/lib/source.ts Normal file
View File

@@ -0,0 +1,37 @@
import { createElement } from 'react';
import { icons } from 'lucide-react';
import { loader } from 'fumadocs-core/source';
import { transformerOpenAPI } from 'fumadocs-openapi/server';
import { createOpenAPI } from 'fumadocs-openapi/server';
import { docs } from '@/.source';
import * as Adapters from './media-adapter';
import * as ClientAdapters from './media-adapter.client';
// See https://fumadocs.vercel.app/docs/headless/source-api for more info
export const source = loader({
// it assigns a URL to your pages
baseUrl: '/docs',
source: docs.toFumadocsSource(),
pageTree: {
transformers: [transformerOpenAPI()],
},
icon(icon) {
if (!icon) {
return;
}
if (icon in icons) {
return createElement(icons[icon as keyof typeof icons]);
}
},
});
export const openapi = createOpenAPI({
proxyUrl: '/api/proxy',
mediaAdapters: {
// override the default adapter of `application/json`
'application/json': {
...Adapters.OpenIsleMediaAdapter,
client: ClientAdapters.OpenIsleMediaAdapter,
},
},
});

13
docs/mdx-components.tsx Normal file
View File

@@ -0,0 +1,13 @@
import defaultMdxComponents from 'fumadocs-ui/mdx';
import type { MDXComponents } from 'mdx/types';
import { APIPage } from 'fumadocs-openapi/ui';
import { openapi } from '@/lib/openapi';
// use this function to get MDX components, you will need it for rendering MDX
export function getMDXComponents(components?: MDXComponents): MDXComponents {
return {
...defaultMdxComponents,
...components,
APIPage: (props) => <APIPage {...openapi.getAPIPageProps(props)} />,
};
}

11
docs/next.config.mjs Normal file
View File

@@ -0,0 +1,11 @@
import { createMDX } from 'fumadocs-mdx/next';
const withMDX = createMDX();
/** @type {import('next').NextConfig} */
const config = {
output: 'export',
reactStrictMode: true,
};
export default withMDX(config);

33
docs/package.json Normal file
View File

@@ -0,0 +1,33 @@
{
"name": "openisle-docs",
"version": "0.0.0",
"private": true,
"scripts": {
"postinstall": "fumadocs-mdx",
"build": "next build",
"dev": "next dev --turbo -p 7890",
"start": "next start",
"generate": "bun ./scripts/generate-docs.ts"
},
"dependencies": {
"fumadocs-core": "15.7.7",
"fumadocs-mdx": "11.8.2",
"fumadocs-openapi": "^9.3.4",
"fumadocs-ui": "15.7.7",
"lucide-react": "^0.542.0",
"next": "15.5.2",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"shiki": "^3.12.1"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.12",
"@types/mdx": "^2.0.13",
"@types/node": "24.3.0",
"@types/react": "^19.1.12",
"@types/react-dom": "^19.1.9",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.12",
"typescript": "^5.9.2"
}
}

5
docs/postcss.config.mjs Normal file
View File

@@ -0,0 +1,5 @@
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};

View File

@@ -0,0 +1,10 @@
import { generateFiles } from 'fumadocs-openapi';
import { openapi } from '@/lib/openapi';
void generateFiles({
input: openapi,
output: './content/docs/openapi/(generated)',
// we recommend to enable it
// make sure your endpoint description doesn't break MDX syntax.
includeDescription: true,
});

23
docs/source.config.ts Normal file
View File

@@ -0,0 +1,23 @@
import {
defineConfig,
defineDocs,
frontmatterSchema,
metaSchema,
} from 'fumadocs-mdx/config';
// You can customise Zod schemas for frontmatter and `meta.json` here
// see https://fumadocs.dev/docs/mdx/collections#define-docs
export const docs = defineDocs({
docs: {
schema: frontmatterSchema,
},
meta: {
schema: metaSchema,
},
});
export default defineConfig({
mdxOptions: {
// MDX options
},
});

30
docs/tsconfig.json Normal file
View File

@@ -0,0 +1,30 @@
{
"compilerOptions": {
"baseUrl": ".",
"target": "ESNext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"paths": {
"@/.source": ["./.source/index.ts"],
"@/*": ["./*"]
},
"plugins": [
{
"name": "next"
}
]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}

View File

@@ -1,5 +1,5 @@
; 本地部署后端
NUXT_PUBLIC_API_BASE_URL=https://127.0.0.1:8081
NUXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8080
NUXT_PUBLIC_WEBSOCKET_URL=https://127.0.0.1:8082
NUXT_PUBLIC_WEBSITE_BASE_URL=http://localhost:3000

View File

@@ -1,10 +1,10 @@
; 生产环境后端
NUXT_PUBLIC_API_BASE_URL=https://open-isle.com
NUXT_PUBLIC_API_BASE_URL=https://www.open-isle.com
; 正式环境/生产环境
NUXT_PUBLIC_WEBSITE_BASE_URL=https://open-isle.com
NUXT_PUBLIC_WEBSITE_BASE_URL=https://www.open-isle.com
; 生产环境ws后端
NUXT_PUBLIC_WEBSOCKET_URL=https://open-isle.com/websocket
NUXT_PUBLIC_WEBSOCKET_URL=https://www.open-isle.com/websocket
NUXT_PUBLIC_GOOGLE_CLIENT_ID=777830451304-nt8afkkap18gui4f9entcha99unal744.apps.googleusercontent.com
NUXT_PUBLIC_GITHUB_CLIENT_ID=Ov23liVkO1NPAX5JyWxJ

View File

@@ -1,5 +1,5 @@
; 本地部署后端
; NUXT_PUBLIC_API_BASE_URL=https://127.0.0.1:8081
; NUXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8080
; 预发环境后端
NUXT_PUBLIC_API_BASE_URL=https://staging.open-isle.com

View File

@@ -1,5 +1,2 @@
node_modules
.nuxt
dist
.output
.env

View File

@@ -25,7 +25,7 @@
class="app-new-post-icon"
@click="goToNewPost"
>
<i class="fas fa-edit"></i>
<edit />
</div>
</div>
<GlobalPopups />

View File

@@ -2,11 +2,12 @@
<div class="article-category-container" v-if="category">
<div class="article-info-item" @click="gotoCategory">
<BaseImage
v-if="category.smallIcon"
v-if="isImageIcon(category.smallIcon)"
class="article-info-item-img"
:src="category.smallIcon"
:alt="category.name"
/>
<component v-else :is="category.smallIcon || category.icon" class="article-info-item-img" />
<div class="article-info-item-text">{{ category.name }}</div>
</div>
</div>
@@ -22,6 +23,11 @@ const gotoCategory = async () => {
const value = encodeURIComponent(props.category.id ?? props.category.name)
await navigateTo({ path: '/', query: { category: value } }, { replace: true })
}
const isImageIcon = (icon) => {
if (!icon) return false
return /^https?:\/\//.test(icon) || icon.startsWith('/')
}
</script>
<style scoped>

View File

@@ -7,11 +7,17 @@
@click="gotoTag(tag)"
>
<BaseImage
v-if="tag.smallIcon"
v-if="isImageIcon(tag.smallIcon)"
class="article-info-item-img"
:src="tag.smallIcon"
:alt="tag.name"
/>
<component
v-else-if="tag.smallIcon || tag.icon"
:is="tag.smallIcon || tag.icon"
class="article-info-item-img"
/>
<tag-one v-else class="article-info-item-img" />
<div class="article-info-item-text">{{ tag.name }}</div>
</div>
</div>
@@ -26,6 +32,11 @@ const gotoTag = async (tag) => {
const value = encodeURIComponent(tag.id ?? tag.name)
await navigateTo({ path: '/', query: { tags: value } }, { replace: true })
}
const isImageIcon = (icon) => {
if (!icon) return false
return /^https?:\/\//.test(icon) || icon.startsWith('/')
}
</script>
<style scoped>

View File

@@ -1,6 +1,6 @@
<template>
<div class="base-input">
<i v-if="icon" :class="['base-input-icon', icon]" />
<component v-if="icon" :is="icon" class="base-input-icon" size="14" />
<!-- 普通输入框 -->
<input
@@ -29,7 +29,7 @@ export default {
inheritAttrs: false,
props: {
modelValue: { type: [String, Number], default: '' },
icon: { type: String, default: '' },
icon: { type: [String, Object], default: '' },
type: { type: String, default: 'text' },
textarea: { type: Boolean, default: false },
},
@@ -66,7 +66,6 @@ export default {
.base-input-icon {
opacity: 0.5;
font-size: 14px;
}
.base-input-text {

View File

@@ -1,6 +1,6 @@
<template>
<div class="base-placeholder">
<i :class="['base-placeholder-icon', icon]" />
<component :is="icon" class="base-placeholder-icon" theme="outline" />
<div class="base-placeholder-text">
<slot>{{ text }}</slot>
</div>
@@ -12,7 +12,7 @@ export default {
name: 'BasePlaceholder',
props: {
text: { type: String, default: '' },
icon: { type: String, default: 'fas fa-inbox' },
icon: { type: String, default: 'inbox' },
},
}
</script>
@@ -27,6 +27,7 @@ export default {
height: 300px;
opacity: 0.5;
}
.base-placeholder-icon,
.base-placeholder-text {
font-size: 16px;
color: var(--text-color);

View File

@@ -8,7 +8,11 @@
:class="['base-tabs-item', { selected: modelValue === tab.key }]"
@click="$emit('update:modelValue', tab.key)"
>
<i v-if="tab.icon" :class="tab.icon"></i>
<component
v-if="tab.icon && (typeof tab.icon !== 'string' || !tab.icon.includes(' '))"
:is="tab.icon"
class="base-tabs-item-icon"
/>
<div class="base-tabs-item-label">{{ tab.label }}</div>
</div>
</div>
@@ -72,6 +76,7 @@ function onTouchEnd(e) {
align-items: center;
}
.base-tabs-item-icon,
.base-tabs-item i {
margin-right: 6px;
}

View File

@@ -7,7 +7,11 @@
@click="item.iconClick && item.iconClick()"
>
<BaseImage v-if="item.src" :src="item.src" class="timeline-img" alt="timeline item" />
<i v-else-if="item.icon" :class="item.icon"></i>
<component
v-else-if="item.icon && (typeof item.icon !== 'string' || !item.icon.includes(' '))"
:is="item.icon"
:size="20"
/>
<BaseImage v-else-if="item.emoji" :src="item.emoji" class="timeline-emoji" alt="emoji" />
</div>
<div class="timeline-content">

View File

@@ -15,7 +15,7 @@
class="option-icon"
:alt="option.name"
/>
<i v-else :class="['option-icon', option.icon]"></i>
<component v-else :is="option.smallIcon || option.icon" class="option-icon" />
</template>
<span>{{ option.name }}</span>
<span class="option-count" v-if="option.count > 0"> x {{ option.count }}</span>

View File

@@ -7,7 +7,7 @@
<div class="comment-bottom-container">
<div class="comment-submit" :class="{ disabled: isDisabled }" @click="submit">
<template v-if="!loading"> 发布评论 </template>
<template v-else> <i class="fa-solid fa-spinner fa-spin"></i> 发布中... </template>
<template v-else> <loading-four /> 发布中... </template>
</div>
</div>
</div>

View File

@@ -15,16 +15,16 @@
<div class="common-info-content-header">
<div class="info-content-header-left">
<span class="user-name">{{ comment.userName }}</span>
<i class="fas fa-medal medal-icon"></i>
<medal-one class="medal-icon" />
<NuxtLink
v-if="comment.medal"
class="medal-name"
:to="`/users/${comment.userId}?tab=achievements`"
>{{ getMedalTitle(comment.medal) }}</NuxtLink
>
<i v-if="comment.pinned" class="fas fa-thumbtack pin-icon"></i>
<pin v-if="comment.pinned" class="pin-icon" />
<span v-if="level >= 2" class="reply-item">
<i class="fas fa-reply reply-icon"></i>
<next class="reply-icon" />
<span class="reply-info">
<BaseImage
class="reply-avatar"
@@ -40,7 +40,7 @@
<div class="info-content-header-right">
<DropdownMenu v-if="commentMenuItems.length > 0" :items="commentMenuItems">
<template #trigger>
<i class="fas fa-ellipsis-vertical action-menu-icon"></i>
<more-one class="action-menu-icon" />
</template>
</DropdownMenu>
</div>
@@ -53,10 +53,10 @@
<div class="article-footer-container">
<ReactionsGroup v-model="comment.reactions" content-type="comment" :content-id="comment.id">
<div class="make-reaction-item comment-reaction" @click="toggleEditor">
<i class="far fa-comment"></i>
<comment-icon />
</div>
<div class="make-reaction-item copy-link" @click="copyCommentLink">
<i class="fas fa-link"></i>
<link-icon />
</div>
</ReactionsGroup>
</div>
@@ -71,8 +71,8 @@
/>
</div>
<div v-if="replyCount && level < 2" class="reply-toggle" @click="toggleReplies">
<i v-if="showReplies" class="fas fa-chevron-up reply-toggle-icon"></i>
<i v-else class="fas fa-chevron-down reply-toggle-icon"></i>
<up v-if="showReplies" class="reply-toggle-icon" />
<down v-else class="reply-toggle-icon" />
{{ replyCount }}条回复
</div>
<div v-if="showReplies && level < 2" class="reply-list">
@@ -375,7 +375,6 @@ const handleContentClick = (e) => {
}
.reply-toggle-icon {
margin-right: 5px;
}
.common-info-content-header {
@@ -405,7 +404,6 @@ const handleContentClick = (e) => {
margin-left: 10px;
margin-right: 10px;
opacity: 0.5;
transform: scaleX(-1);
}
.reply-user-name {

View File

@@ -19,7 +19,7 @@
class="option-icon"
:alt="label.name"
/>
<i v-else :class="['option-icon', label.icon]"></i>
<component v-else :is="label.icon" class="option-icon" :size="16" />
</template>
<span>{{ label.name }}</span>
</div>
@@ -38,14 +38,14 @@
class="option-icon"
:alt="selectedLabels[0].name"
/>
<i v-else :class="['option-icon', selectedLabels[0].icon]"></i>
<component v-else :is="selectedLabels[0].icon" class="option-icon" :size="16" />
</template>
<span>{{ selectedLabels[0].name }}</span>
</div>
</span>
<span v-else class="placeholder">{{ placeholder }}</span>
</template>
<i class="fas fa-caret-down dropdown-caret"></i>
<down class="dropdown-caret" />
</slot>
</div>
<div
@@ -54,7 +54,7 @@
v-click-outside="close"
>
<div v-if="showSearch" class="dropdown-search">
<i class="fas fa-search search-icon"></i>
<search-icon class="search-icon" />
<input type="text" v-model="search" placeholder="搜索" />
</div>
<div v-if="loading" class="dropdown-loading">
@@ -75,7 +75,7 @@
class="option-icon"
:alt="o.name"
/>
<i v-else :class="['option-icon', o.icon]"></i>
<component v-else :is="o.icon" class="option-icon" :size="16" />
</template>
<span>{{ o.name }}</span>
</slot>
@@ -85,12 +85,12 @@
<Teleport to="body">
<div v-if="open && isMobile" class="dropdown-mobile-page">
<div class="dropdown-mobile-header">
<i class="fas fa-arrow-left" @click="close"></i>
<next class="back-icon" @click="close" />
<span class="mobile-title">{{ placeholder }}</span>
</div>
<div class="dropdown-mobile-menu">
<div v-if="showSearch" class="dropdown-search">
<i class="fas fa-search search-icon"></i>
<search-icon class="search-icon" />
<input type="text" v-model="search" placeholder="搜索" />
</div>
<div v-if="loading" class="dropdown-loading">
@@ -111,7 +111,7 @@
class="option-icon"
:alt="o.name"
/>
<i v-else :class="['option-icon', o.icon]"></i>
<component v-else :is="o.icon" class="option-icon" :size="16" />
</template>
<span>{{ o.name }}</span>
</slot>
@@ -303,6 +303,10 @@ export default {
overflow-y: auto;
}
.dropdown-caret {
margin-left: 5px;
}
.selected-label {
display: inline-flex;
align-items: center;
@@ -326,6 +330,10 @@ export default {
color: var(--text-color);
}
.search-icon {
font-size: 14px;
}
.dropdown-option {
display: flex;
align-items: center;
@@ -376,6 +384,11 @@ export default {
border-bottom: 1px solid var(--normal-border-color);
}
.back-icon {
transform: rotate(180deg);
cursor: pointer;
}
.dropdown-mobile-menu {
flex: 1;
overflow-y: auto;

View File

@@ -4,7 +4,9 @@
<div class="header-content-left">
<div v-if="showMenuBtn" class="menu-btn-wrapper">
<button class="menu-btn" ref="menuBtn" @click="$emit('toggle-menu')">
<i class="fas fa-bars micon"></i>
<ToolTip content="展开/收起菜单" placement="bottom">
<application-menu class="micon"></application-menu>
</ToolTip>
</button>
<span
v-if="isMobile && (unreadMessageCount > 0 || hasChannelUnread)"
@@ -25,34 +27,39 @@
<ClientOnly>
<div class="header-content-right">
<div v-if="isMobile" class="search-icon" @click="search">
<i class="fas fa-search"></i>
<search-icon />
</div>
<div v-if="isMobile" class="theme-icon" @click="cycleTheme">
<i :class="iconClass"></i>
<component :is="iconClass" />
</div>
<div v-if="!isMobile" class="invite_text" @click="copyInviteLink">
<i class="fas fa-copy"></i>
<copy />
邀请
<i v-if="isCopying" class="fas fa-spinner fa-spin"></i>
<loading v-if="isCopying" />
</div>
<ToolTip v-if="!isMobile" content="当前在线人数" placement="bottom">
<div class="online-count">
<peoples-two />
<span>{{ onlineCount }}</span>
</div>
</ToolTip>
<ToolTip content="复制RSS链接" placement="bottom">
<div class="rss-icon" @click="copyRssLink">
<i class="fas fa-rss"></i>
<rss />
</div>
</ToolTip>
<ToolTip v-if="!isMobile && isLogin" content="发帖" placement="bottom">
<div class="new-post-icon" @click="goToNewPost">
<i class="fas fa-edit"></i>
<edit />
</div>
</ToolTip>
<ToolTip v-if="isLogin" content="站内信和频道" placement="bottom">
<div class="messages-icon" @click="goToMessages">
<i class="fas fa-comments"></i>
<message-emoji />
<span v-if="unreadMessageCount > 0" class="unread-badge">{{
unreadMessageCount
}}</span>
@@ -64,7 +71,7 @@
<template #trigger>
<div class="avatar-container">
<img class="avatar-img" :src="avatar" alt="avatar" />
<i class="fas fa-caret-down dropdown-icon"></i>
<down />
</div>
</template>
</DropdownMenu>
@@ -115,6 +122,45 @@ const userMenu = ref(null)
const menuBtn = ref(null)
const isCopying = ref(false)
const onlineCount = ref(0)
// 心跳检测
async function sendPing() {
try {
// 已登录就用 userId否则随机生成游客ID
let userId = authState.userId
if (userId) {
// 用户已登录,清理游客 ID
localStorage.removeItem('guestId')
} else {
// 游客模式
let savedId = localStorage.getItem('guestId')
if (!savedId) {
savedId = `guest-${crypto.randomUUID()}`
localStorage.setItem('guestId', savedId)
}
userId = savedId
}
const res = await fetch(`${API_BASE_URL}/api/online/heartbeat?userId=${userId}`, {
method: 'POST',
})
} catch (e) {
console.error('心跳失败', e)
}
}
// 获取在线人数
async function fetchCount() {
try {
const res = await fetch(`${API_BASE_URL}/api/online/count`, {
method: 'GET',
})
onlineCount.value = await res.json()
} catch (e) {
console.error('获取在线人数失败', e)
}
}
const search = () => {
showSearch.value = true
nextTick(() => {
@@ -226,11 +272,11 @@ const headerMenuItems = computed(() => [
const iconClass = computed(() => {
switch (themeState.mode) {
case ThemeMode.DARK:
return 'fas fa-moon'
return 'Moon'
case ThemeMode.LIGHT:
return 'fas fa-sun'
return 'SunOne'
default:
return 'fas fa-desktop'
return 'ComputerOne'
}
})
@@ -262,6 +308,12 @@ onMounted(async () => {
await updateUnread()
},
)
// 新增的在线人数逻辑
sendPing()
fetchCount()
setInterval(sendPing, 120000) // 每 2 分钟发一次心跳
setInterval(fetchCount, 60000) // 每 1 分更新 UI
})
</script>
@@ -452,6 +504,15 @@ onMounted(async () => {
animation: rss-glow 2s 3;
}
.online-count {
font-size: 14px;
display: flex;
align-items: center;
gap: 5px;
color: var(--primary-color);
cursor: default;
}
@keyframes rss-glow {
0% {
text-shadow: 0 0 0px var(--primary-color);

View File

@@ -2,7 +2,7 @@
<div class="invite-code-activity">
<div class="invite-code-description">
<div class="invite-code-description-title">
<i class="fas fa-info-circle"></i>
<info-icon />
<span class="invite-code-description-title-text">邀请规则说明</span>
</div>
<div class="invite-code-description-content">
@@ -17,7 +17,7 @@
<div v-if="inviteLink" class="invite-code-link-content">
<p class="invite-code-link-content-text">
邀请链接{{ inviteLink }}
<span @click="copyLink"><i class="fas fa-copy copy-icon"></i></span>
<span @click="copyLink"><copy class="copy-icon" /></span>
</p>
</div>

View File

@@ -2,7 +2,7 @@
<div class="login-overlay">
<div class="login-overlay-blur"></div>
<div class="login-overlay-content">
<i class="fa-solid fa-user login-overlay-icon"></i>
<user-icon class="login-overlay-icon" />
<div class="login-overlay-text">请先登录点击跳转到登录页面</div>
<div class="login-overlay-button" @click="goLogin">登录</div>
</div>

View File

@@ -10,7 +10,7 @@
<span class="prize-row-title">奖品图片</span>
<label class="prize-container">
<BaseImage v-if="data.prizeIcon" :src="data.prizeIcon" class="prize-preview" alt="prize" />
<i v-else class="fa-solid fa-image default-prize-icon"></i>
<image-files v-else class="default-prize-icon" />
<div class="prize-overlay">上传奖品图片</div>
<input type="file" class="prize-input" accept="image/*" @change="onPrizeIconChange" />
</label>

View File

@@ -4,7 +4,7 @@
<div class="menu-content">
<div class="menu-item-container">
<NuxtLink class="menu-item" exact-active-class="selected" to="/" @click="handleItemClick">
<i class="menu-item-icon fas fa-hashtag"></i>
<hashtag-key class="menu-item-icon" />
<span class="menu-item-text">话题</span>
</NuxtLink>
<NuxtLink
@@ -13,7 +13,7 @@
to="/new-post"
@click="handleItemClick"
>
<i class="menu-item-icon fas fa-edit"></i>
<edit class="menu-item-icon" />
<span class="menu-item-text">发帖</span>
</NuxtLink>
<NuxtLink
@@ -22,7 +22,7 @@
to="/message"
@click="handleItemClick"
>
<i class="menu-item-icon fas fa-envelope"></i>
<remind class="menu-item-icon" />
<span class="menu-item-text">我的消息</span>
<span v-if="unreadCount > 0" class="unread-container">
<span class="unread"> {{ showUnreadCount }} </span>
@@ -34,7 +34,7 @@
to="/about"
@click="handleItemClick"
>
<i class="menu-item-icon fas fa-info-circle"></i>
<info-icon class="menu-item-icon" />
<span class="menu-item-text">关于</span>
</NuxtLink>
<NuxtLink
@@ -43,7 +43,7 @@
to="/activities"
@click="handleItemClick"
>
<i class="menu-item-icon fas fa-gift"></i>
<gift class="menu-item-icon" />
<span class="menu-item-text">🔥 活动</span>
</NuxtLink>
<NuxtLink
@@ -53,7 +53,7 @@
to="/about/stats"
@click="handleItemClick"
>
<i class="menu-item-icon fas fa-chart-line"></i>
<chart-line class="menu-item-icon" />
<span class="menu-item-text">站点统计</span>
</NuxtLink>
<NuxtLink
@@ -63,7 +63,7 @@
to="/points"
@click="handleItemClick"
>
<i class="menu-item-icon fas fa-coins"></i>
<finance class="menu-item-icon" />
<span class="menu-item-text">
积分商城
<span v-if="myPoint !== null" class="point-count">{{ myPoint }}</span>
@@ -74,7 +74,8 @@
<div class="menu-section">
<div class="section-header" @click="categoryOpen = !categoryOpen">
<span>类别</span>
<i :class="categoryOpen ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></i>
<up v-if="categoryOpen" class="menu-item-icon" />
<down v-else class="menu-item-icon" />
</div>
<div v-if="categoryOpen" class="section-items">
<div v-if="isLoadingCategory" class="menu-loading-container">
@@ -94,7 +95,7 @@
class="section-item-icon"
:alt="c.name"
/>
<i v-else :class="['section-item-icon', c.smallIcon || c.icon]"></i>
<component v-else :is="c.smallIcon || c.icon" class="section-item-icon" />
</template>
<span class="section-item-text">
{{ c.name }}
@@ -107,7 +108,8 @@
<div class="menu-section">
<div class="section-header" @click="tagOpen = !tagOpen">
<span>标签</span>
<i :class="tagOpen ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></i>
<up v-if="tagOpen" class="menu-item-icon" />
<down v-else class="menu-item-icon" />
</div>
<div v-if="tagOpen" class="section-items">
<div v-if="isLoadingTag" class="menu-loading-container">
@@ -120,7 +122,12 @@
class="section-item-icon"
:alt="t.name"
/>
<i v-else class="section-item-icon fas fa-hashtag"></i>
<component
v-else-if="t.smallIcon || t.icon"
:is="t.smallIcon || t.icon"
class="section-item-icon"
/>
<tag-one v-else class="section-item-icon" />
<span class="section-item-text"
>{{ t.name }} <span class="section-item-text-count">x {{ t.count }}</span></span
>
@@ -133,7 +140,7 @@
<ClientOnly v-if="!isMobile">
<div class="menu-footer">
<div class="menu-footer-btn" @click="cycleTheme">
<i :class="iconClass"></i>
<component :is="iconClass" class="menu-item-icon" />
</div>
</div>
</ClientOnly>
@@ -193,11 +200,11 @@ const {
const iconClass = computed(() => {
switch (themeState.mode) {
case ThemeMode.DARK:
return 'fas fa-moon'
return 'Moon'
case ThemeMode.LIGHT:
return 'fas fa-sun'
return 'SunOne'
default:
return 'fas fa-desktop'
return 'ComputerOne'
}
})

View File

@@ -6,7 +6,7 @@
<div class="message-bottom-container">
<div class="message-submit" :class="{ disabled: isDisabled }" @click="submit">
<template v-if="!loading"> 发送 </template>
<template v-else> <i class="fa-solid fa-spinner fa-spin"></i> 发送中... </template>
<template v-else> <loading-four /> 发送中... </template>
</div>
</div>
</div>

View File

@@ -3,20 +3,10 @@
<iframe :src="iframeSrc" frameborder="0" ref="iframeRef" @load="injectBaseTag"></iframe>
<div class="float-actions">
<i
class="fas fa-chevron-down"
v-if="floatHeight !== MINI_HEIGHT"
title="收起至 100px"
@click="collapseToMini"
></i>
<i
class="fas fa-chevron-up"
v-if="floatHeight !== DEFAULT_HEIGHT"
title="回弹至 60vh"
@click="reboundToDefault"
></i>
<i class="fas fa-expand" title="在页面中打开" @click="expand"></i>
<i class="fas fa-times" title="关闭" @click="close"></i>
<down v-if="floatHeight !== MINI_HEIGHT" title="收起至 100px" @click="collapseToMini" />
<up v-if="floatHeight !== DEFAULT_HEIGHT" title="回弹至 60vh" @click="reboundToDefault" />
<expand-up title="在页面中打开" @click="expand" />
<close-icon title="关闭" @click="close" />
</div>
</div>
</template>

View File

@@ -2,7 +2,7 @@
<div class="milk-tea-activity">
<div class="milk-tea-description">
<div class="milk-tea-description-title">
<i class="fas fa-info-circle"></i>
<info-icon />
<span class="milk-tea-description-title-text">升级规则说明</span>
</div>
<div class="milk-tea-description-content">
@@ -29,7 +29,7 @@
/>
</div>
<div v-else class="user-level">
<div class="user-level-text"><i class="fas fa-user-circle"></i> 请登录查看自身等级</div>
<div class="user-level-text"><user-icon /> 请登录查看自身等级</div>
</div>
</div>
<div

View File

@@ -10,14 +10,14 @@
:src="lottery.prizeIcon"
alt="prize"
/>
<i v-else class="fa-solid fa-gift default-prize-icon"></i>
<gift v-else class="default-prize-icon" />
</div>
<div class="prize-name">{{ lottery.prizeDescription }}</div>
<div class="prize-count">x {{ lottery.prizeCount }}</div>
</div>
<div class="prize-end-time prize-info-right">
<i class="fas fa-stopwatch prize-end-time-icon"></i>
<div v-if="!isMobile" class="prize-end-time-title">离结束</div>
<stopwatch v-if="!lotteryEnded" class="prize-end-time-icon" />
<div v-if="!isMobile && !lotteryEnded" class="prize-end-time-title">离结束</div>
<div class="prize-end-time-value">{{ countdown }}</div>
<div v-if="!isMobile" class="join-prize-button-container-desktop">
<div
@@ -26,7 +26,8 @@
@click="joinLottery"
>
<div class="join-prize-button-text">
参与抽奖 <i class="fas fa-coins"></i> {{ lottery.pointCost }}
参与抽奖 <paper-money-two class="join-prize-button-text-icon" />
{{ lottery.pointCost }}
</div>
</div>
<div v-else-if="hasJoined" class="join-prize-button-disabled">
@@ -43,7 +44,7 @@
@click="joinLottery"
>
<div class="join-prize-button-text">
参与抽奖 <i class="fas fa-coins"></i> {{ lottery.pointCost }}
参与抽奖 <paper-money-two class="join-prize-button-text-icon" /> {{ lottery.pointCost }}
</div>
</div>
<div v-else-if="hasJoined" class="join-prize-button-disabled">
@@ -61,7 +62,7 @@
@click="gotoUser(p.id)"
/>
<div v-if="lotteryEnded && lotteryWinners.length" class="prize-member-winner">
<i class="fas fa-medal medal-icon"></i>
<medal-one class="medal-icon"></medal-one>
<span class="prize-member-winner-name">获奖者: </span>
<BaseImage
v-for="w in lotteryWinners"
@@ -193,6 +194,7 @@ const joinLottery = async () => {
.prize-end-time-icon {
font-size: 13px;
margin-right: 5px;
}
.prize-end-time-title {

View File

@@ -34,7 +34,7 @@
<div class="poll-option-title" v-else>单选</div>
<div class="poll-left-time">
<i class="fas fa-stopwatch poll-left-time-icon"></i>
<stopwatch class="poll-left-time-icon" />
<div class="poll-left-time-title">离结束</div>
<div class="poll-left-time-value">{{ countdown }}</div>
</div>
@@ -55,9 +55,7 @@
</div>
<div class="multi-selection-container">
<div class="join-poll-button" @click="submitMultiPoll">
<i class="fas fa-check"></i> 确认投票
</div>
<div class="join-poll-button" @click="submitMultiPoll"><check /> 确认投票</div>
</div>
</template>
<template v-else>
@@ -77,9 +75,7 @@
</div>
<div class="single-selection-container">
<div class="join-poll-button" @click="submitSinglePoll">
<i class="fas fa-check"></i> 确认投票
</div>
<div class="join-poll-button" @click="submitSinglePoll"><check /> 确认投票</div>
</div>
</template>
</div>
@@ -95,22 +91,20 @@
class="poll-option-button"
@click="showPollResult = false"
>
<i class="fas fa-chevron-left"></i> 投票
<arrow-left /> 投票
</div>
<div
v-else-if="!pollEnded && !hasVoted"
class="poll-option-button"
@click="showPollResult = true"
>
<i class="fas fa-chart-bar"></i> 结果
</div>
<div v-else-if="pollEnded" class="poll-option-hint">
<i class="fas fa-stopwatch"></i> 投票已结束
<chart-histogram /> 结果
</div>
<div v-else-if="pollEnded" class="poll-option-hint"><stopwatch /> 投票已结束</div>
<div v-else class="poll-option-hint">
<div>您已投票等待结束查看结果</div>
<div class="poll-left-time">
<i class="fas fa-stopwatch poll-left-time-icon"></i>
<stopwatch class="poll-left-time-icon" />
<div class="poll-left-time-title">离结束</div>
<div class="poll-left-time-value">{{ countdown }}</div>
</div>

View File

@@ -31,9 +31,9 @@ export default {
const fetchTypes = async () => {
return [
{ id: 'NORMAL', name: '普通帖子', icon: 'fa-regular fa-file' },
{ id: 'LOTTERY', name: '抽奖帖子', icon: 'fa-solid fa-gift' },
{ id: 'POLL', name: '投票帖子', icon: 'fa-solid fa-square-poll-vertical' },
{ id: 'NORMAL', name: '普通帖子', icon: 'file-text' },
{ id: 'LOTTERY', name: '抽奖帖子', icon: 'gift' },
{ id: 'POLL', name: '投票帖子', icon: 'ranking-list' },
]
}

View File

@@ -19,8 +19,7 @@
</div>
<div class="reactions-viewer-item placeholder" @click="openPanel">
<i class="far fa-smile reactions-viewer-item-placeholder-icon"></i>
<!-- <span class="reactions-viewer-item-placeholder-text">点击以表态</span> -->
<sly-face-whit-smile class="reactions-viewer-item-placeholder-icon" />
</div>
</template>
<template v-else-if="displayedReactions.length">
@@ -42,8 +41,8 @@
class="make-reaction-item like-reaction"
@click="toggleReaction('LIKE')"
>
<i v-if="!userReacted('LIKE')" class="far fa-heart"></i>
<i v-else class="fas fa-heart"></i>
<like v-if="!userReacted('LIKE')" />
<like v-else theme="filled" />
<span class="reactions-count" v-if="likeCount">{{ likeCount }}</span>
</div>
<slot></slot>

View File

@@ -13,7 +13,7 @@
>
<template #display="{ setSearch }">
<div class="search-input">
<i class="search-input-icon fas fa-search"></i>
<search-icon class="search-input-icon" />
<input
class="text-input"
v-model="keyword"
@@ -24,7 +24,7 @@
</template>
<template #option="{ option }">
<div class="search-option-item">
<i :class="['result-icon', iconMap[option.type] || 'fas fa-question']"></i>
<component :is="iconMap[option.type]" class="result-icon" />
<div class="result-body">
<div class="result-main" v-html="highlight(option.text)"></div>
<div v-if="option.subText" class="result-sub" v-html="highlight(option.subText)"></div>
@@ -83,11 +83,12 @@ const highlight = (text) => {
}
const iconMap = {
user: 'fas fa-user',
post: 'fas fa-file-alt',
comment: 'fas fa-comment',
category: 'fas fa-folder',
tag: 'fas fa-hashtag',
user: 'UserIcon',
post: 'FileText',
post_title: 'FileText',
comment: 'CommentIcon',
category: 'Inbox',
tag: 'TagOne',
}
watch(selected, (val) => {

View File

@@ -13,7 +13,7 @@
>
<template #display="{ setSearch }">
<div class="search-input">
<i class="search-input-icon fas fa-search"></i>
<search-icon class="search-input-icon" />
<input
class="text-input"
v-model="keyword"

View File

@@ -10,14 +10,14 @@
<template #option="{ option }">
<div class="option-container">
<div class="option-main">
<template v-if="option.icon">
<template v-if="option.smallIcon || option.icon">
<BaseImage
v-if="isImageIcon(option.icon)"
:src="option.icon"
v-if="isImageIcon(option.smallIcon || option.icon)"
:src="option.smallIcon || option.icon"
class="option-icon"
:alt="option.name"
/>
<i v-else :class="['option-icon', option.icon]"></i>
<component v-else :is="option.smallIcon || option.icon" class="option-icon" />
</template>
<span>{{ option.name }}</span>
<span class="option-count" v-if="option.count > 0"> x {{ option.count }}</span>

View File

@@ -56,7 +56,6 @@ import {
onBeforeUnmount,
nextTick,
watch,
defineProps,
defineEmits,
defineOptions,
useId,

View File

@@ -1,6 +1,6 @@
<template>
<div class="user-list">
<BasePlaceholder v-if="users.length === 0" text="暂无用户" icon="fas fa-inbox" />
<BasePlaceholder v-if="users.length === 0" text="暂无用户" icon="inbox" />
<div v-for="u in users" :key="u.id" class="user-item" @click="handleUserClick(u)">
<BaseImage :src="u.avatar" alt="avatar" class="user-avatar" />
<div class="user-info">

View File

@@ -1,6 +1,10 @@
import { defineNuxtConfig } from 'nuxt/config'
export default defineNuxtConfig({
devServer: {
host: '0.0.0.0',
port: 3000
},
ssr: true,
modules: ['@nuxt/image'],
runtimeConfig: {
@@ -15,7 +19,12 @@ export default defineNuxtConfig({
telegramBotId: process.env.NUXT_PUBLIC_TELEGRAM_BOT_ID || '',
},
},
css: ['vditor/dist/index.css', '~/assets/fonts.css', '~/assets/global.css'],
css: [
'vditor/dist/index.css',
'~/assets/fonts.css',
'~/assets/global.css',
'@icon-park/vue-next/styles/index.css',
],
app: {
pageTransition: { name: 'page', mode: 'out-in' },
head: {
@@ -72,11 +81,11 @@ export default defineNuxtConfig({
rel: 'manifest',
href: '/manifest.webmanifest',
},
{
rel: 'stylesheet',
href: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css',
referrerpolicy: 'no-referrer',
},
// {
// rel: 'stylesheet',
// href: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css',
// referrerpolicy: 'no-referrer',
// },
],
},
baseURL: '/',

View File

@@ -6,6 +6,7 @@
"": {
"name": "frontend_nuxt",
"dependencies": {
"@icon-park/vue-next": "^1.4.2",
"@nuxt/image": "^1.11.0",
"@stomp/stompjs": "^7.0.0",
"cropperjs": "^1.6.2",
@@ -25,6 +26,9 @@
"vue-echarts": "^7.0.3",
"vue-flatpickr-component": "^12.0.0",
"vue-toastification": "^2.0.0-rc.5"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@ampproject/remapping": {
@@ -990,6 +994,19 @@
"integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==",
"license": "MIT"
},
"node_modules/@icon-park/vue-next": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@icon-park/vue-next/-/vue-next-1.4.2.tgz",
"integrity": "sha512-+QklF255wkfBOabY+xw6FAI0Bwln/RhdwCunNy/9sKdKuChtaU67QZqU67KGAvZUTeeBgsL+yaHHxqfQeGZXEQ==",
"license": "Apache-2.0",
"engines": {
"node": ">= 8.0.0",
"npm": ">= 5.0.0"
},
"peerDependencies": {
"vue": "3.x"
}
},
"node_modules/@img/sharp-darwin-arm64": {
"version": "0.34.3",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz",

View File

@@ -12,6 +12,7 @@
"generate": "nuxt generate"
},
"dependencies": {
"@icon-park/vue-next": "^1.4.2",
"@nuxt/image": "^1.11.0",
"@stomp/stompjs": "^7.0.0",
"cropperjs": "^1.6.2",

View File

@@ -18,7 +18,7 @@
<div class="activity-list-page-card-content">{{ a.content }}</div>
<div class="activity-list-page-card-footer">
<div class="activity-list-page-card-footer-start-time">
<i class="fas fa-clock"></i>
<stopwatch />
<span>开始于 {{ TimeManager.format(a.startTime) }}</span>
</div>
</div>

View File

@@ -2,26 +2,26 @@
<div class="forgot-page">
<div class="forgot-content">
<div class="forgot-title">找回密码</div>
<div v-if="step === 0" class="step-content">
<BaseInput icon="fas fa-envelope" v-model="email" placeholder="邮箱" />
<BaseInput icon="mail" v-model="email" placeholder="邮箱" />
<div v-if="emailError" class="error-message">{{ emailError }}</div>
<div class="primary-button" @click="sendCode" v-if="!isSending">发送验证码</div>
<div class="primary-button disabled" v-else>发送中...</div>
</div>
<div v-else-if="step === 1" class="step-content">
<BaseInput icon="fas fa-envelope" v-model="code" placeholder="邮箱验证码" />
<BaseInput icon="mail" v-model="code" placeholder="邮箱验证码" />
<div class="primary-button" @click="verifyCode" v-if="!isVerifying">验证</div>
<div class="primary-button disabled" v-else>验证中...</div>
</div>
<div v-else class="step-content">
<BaseInput icon="fas fa-lock" v-model="password" type="password" placeholder="新密码" />
<BaseInput icon="lock" v-model="password" type="password" placeholder="新密码" />
<div v-if="passwordError" class="error-message">{{ passwordError }}</div>
<div class="primary-button" @click="resetPassword" v-if="!isResetting">重置密码</div>
<div class="primary-button disabled" v-else>提交中...</div>
</div>
<div class="hint-message">
<i class="fas fa-info-circle"></i>
<info-icon />
使用 Google 注册的用户可使用对应的邮箱进行找回密码
</div>
</div>

View File

@@ -68,13 +68,10 @@
>
<div class="article-main-container">
<NuxtLink class="article-item-title main-item" :to="`/posts/${article.id}`">
<i v-if="article.pinned" class="fas fa-thumbtack pinned-icon"></i>
<i v-if="article.type === 'LOTTERY'" class="fa-solid fa-gift lottery-icon"></i>
<i
v-else-if="article.type === 'POLL'"
class="fa-solid fa-square-poll-vertical poll-icon"
></i>
<i v-if="!article.rssExcluded" class="fa-solid fa-star featured-icon"></i>
<pin v-if="article.pinned" theme="outline" class="pinned-icon" />
<gift v-if="article.type === 'LOTTERY'" class="lottery-icon" />
<ranking-list v-else-if="article.type === 'POLL'" class="poll-icon" />
<star v-if="!article.rssExcluded" class="featured-icon" />
{{ article.title }}
</NuxtLink>
<NuxtLink class="article-item-description main-item" :to="`/posts/${article.id}`">
@@ -141,7 +138,6 @@ import { getToken } from '~/utils/auth'
import { stripMarkdown } from '~/utils/markdown'
import { useIsMobile } from '~/utils/screen'
import TimeManager from '~/utils/time'
useHead({
title: 'OpenIsle - 全面开源的自由社区',
meta: [
@@ -533,7 +529,7 @@ const sanitizeDescription = (text) => stripMarkdown(text)
}
.article-item-title {
margin-top: 10px;
margin-top: 15px;
font-size: 18px;
text-decoration: none;
color: var(--text-color);
@@ -562,7 +558,7 @@ const sanitizeDescription = (text) => stripMarkdown(text)
.article-item-description {
max-width: 100%;
margin-top: 10px;
margin-top: 5px;
font-size: 13px;
color: rgba(140, 140, 140, 0.888);
display: -webkit-box;
@@ -609,6 +605,7 @@ const sanitizeDescription = (text) => stripMarkdown(text)
display: flex;
flex-direction: column;
align-items: flex-start;
padding-bottom: 5px;
}
.article-member-avatars-container {
@@ -723,10 +720,15 @@ const sanitizeDescription = (text) => stripMarkdown(text)
}
.article-item-title {
margin-top: 10px;
font-size: 16px;
font-weight: bold;
}
.article-main-container {
padding-bottom: 0px;
}
.article-item-description {
margin-top: 2px;
font-size: 10px;

View File

@@ -6,9 +6,9 @@
</div>
<div class="email-login-page-content">
<BaseInput icon="fas fa-envelope" v-model="username" placeholder="邮箱/用户名" />
<BaseInput icon="mail" v-model="username" placeholder="邮箱/用户名" />
<BaseInput icon="fas fa-lock" v-model="password" type="password" placeholder="密码" />
<BaseInput icon="lock" v-model="password" type="password" placeholder="密码" />
<div v-if="!isWaitingForLogin" class="login-page-button-primary" @click="submitLogin">
<div class="login-page-button-text">登录</div>
@@ -16,7 +16,7 @@
<div v-else class="login-page-button-primary disabled">
<div class="login-page-button-text">
<i class="fas fa-spinner fa-spin"></i>
<loading-four />
登录中...
</div>
</div>
@@ -28,7 +28,7 @@
>
</div>
<div class="hint-message">
<i class="fas fa-info-circle"></i>
<info-icon />
使用右侧第三方OAuth注册/登录的用户可使用对应的邮箱进行重设密码
</div>
</div>

View File

@@ -3,14 +3,14 @@
<div v-if="!loading" class="chat-header">
<div class="header-main">
<div class="back-button" @click="goBack">
<i class="fas fa-arrow-left"></i>
<arrow-left />
</div>
<h2 class="participant-name">
{{ isChannel ? conversationName : otherParticipant?.username }}
</h2>
</div>
<div v-if="!isFloatMode" class="float-control">
<i class="fas fa-compress" @click="minimize" title="最小化"></i>
<collapse-text-input class="float-control-icon" @click="minimize" title="最小化" />
</div>
</div>
@@ -48,7 +48,7 @@
:content-id="item.id"
@update:modelValue="(v) => (item.reactions = v)"
>
<i class="fas fa-reply reply-btn" @click="setReply(item)"> 写个回复...</i>
<div class="reply-btn"><next @click="setReply(item)" /> 写个回复...</div>
</ReactionsGroup>
</template>
</BaseTimeline>
@@ -56,7 +56,7 @@
<BasePlaceholder
v-if="messages.length === 0"
text="暂无会话,发送消息试试 🎉"
icon="fas fa-inbox"
icon="inbox"
/>
</div>
</template>
@@ -66,7 +66,7 @@
<div v-if="replyTo" class="active-reply">
正在回复 {{ replyTo.sender.username }}:
{{ stripMarkdownLength(replyTo.content, 50) }}
<i class="fas fa-times close-reply" @click="replyTo = null"></i>
<close-icon class="close-reply" @click="replyTo = null" />
</div>
<MessageEditor :loading="sending" @submit="sendMessage" />
</div>
@@ -351,9 +351,9 @@ onMounted(async () => {
})
const subscribeToConversation = () => {
if (!currentUser.value) return;
if (!currentUser.value) return
const destination = `/topic/conversation/${conversationId}`
subscribe(destination, async (message) => {
try {
const parsedMessage = JSON.parse(message.body)
@@ -370,12 +370,12 @@ const subscribeToConversation = () => {
await markConversationAsRead()
await nextTick()
if (isUserNearBottom.value) {
scrollToBottomSmooth()
}
} catch (e) {
console.error("Failed to parse websocket message", e)
console.error('Failed to parse websocket message', e)
}
})
}
@@ -394,7 +394,7 @@ onActivated(async () => {
await nextTick()
scrollToBottomSmooth()
updateNearBottom()
if (isConnected.value) {
// 如果已连接,重新订阅
subscribeToConversation()

View File

@@ -1,11 +1,11 @@
<template>
<div class="messages-container">
<div class="page-title">
<i class="fas fa-comments"></i>
<message-emoji />
<span class="page-title-text">选择聊天</span>
</div>
<div v-if="!isFloatMode" class="float-control">
<i class="fas fa-compress" @click="minimize" title="最小化"></i>
<collapse-text-input class="float-control-icon" @click="minimize" title="最小化" />
</div>
<BaseTabs v-model="activeTab" :tabs="tabs">
<div v-if="activeTab === 'messages'">
@@ -22,7 +22,7 @@
</div>
<div v-if="!loading && conversations.length === 0" class="empty-container">
<BasePlaceholder v-if="conversations.length === 0" text="暂无会话" icon="fas fa-inbox" />
<BasePlaceholder v-if="conversations.length === 0" text="暂无会话" icon="inbox" />
</div>
<div
@@ -73,7 +73,7 @@
</div>
<div v-else>
<div v-if="channels.length === 0" class="empty-container">
<BasePlaceholder text="暂无频道" icon="fas fa-inbox" />
<BasePlaceholder text="暂无频道" icon="inbox" />
</div>
<div
v-for="ch in channels"
@@ -273,9 +273,9 @@ onActivated(async () => {
})
const subscribeToUserMessages = () => {
if (!currentUser.value) return;
if (!currentUser.value) return
const destination = `/topic/user/${currentUser.value.id}/messages`
subscribe(destination, (message) => {
if (activeTab.value === 'messages') {
fetchConversations()

View File

@@ -4,7 +4,7 @@
<template #right>
<div class="message-page-header-right">
<div class="message-page-header-right-item" @click="markAllRead">
<i class="fas fa-bolt message-page-header-right-item-button-icon"></i>
<check-correct class="message-page-header-right-item-button-icon" />
<span class="message-page-header-right-item-button-text"> 已读所有消息 </span>
</div>
</div>
@@ -14,8 +14,12 @@
<div class="message-control-container">
<div class="message-control-title">通知设置</div>
<div class="message-control-item-container">
<template v-for="pref in notificationPrefs">
<div v-if="canShowNotification(pref.type)" :key="pref.type" class="message-control-item">
<template v-for="pref in notificationPrefs">
<div
v-if="canShowNotification(pref.type)"
:key="pref.type"
class="message-control-item"
>
<div class="message-control-item-label">{{ formatType(pref.type) }}</div>
<BaseSwitch
:model-value="pref.enabled"
@@ -47,7 +51,7 @@
<BasePlaceholder
v-else-if="notifications.length === 0"
text="暂时没有消息 :)"
icon="fas fa-inbox"
icon="inbox"
/>
<div class="timeline-container" v-if="notifications.length > 0">
@@ -757,7 +761,12 @@ const formatType = (t) => {
const isAdmin = computed(() => authState.role === 'ADMIN')
const needAdminSet = new Set(['POST_REVIEW_REQUEST','REGISTER_REQUEST', 'POINT_REDEEM', 'ACTIVITY_REDEEM'])
const needAdminSet = new Set([
'POST_REVIEW_REQUEST',
'REGISTER_REQUEST',
'POINT_REDEEM',
'ACTIVITY_REDEEM',
])
const canShowNotification = (type) => {
return !needAdminSet.has(type) || isAdmin.value

View File

@@ -13,13 +13,13 @@
<PostTypeSelect v-model="postType" />
</div>
<div class="post-options-right">
<div class="post-clear" @click="clearPost"><i class="fa-solid fa-eraser"></i> 清空</div>
<div class="post-clear" @click="clearPost"><clear-icon /> 清空</div>
<div class="ai-generate" @click="aiGenerate">
<i class="fa-solid fa-robot"></i>
<smart-optimization />
MD 格式优化
</div>
<div class="post-draft" @click="saveDraft">
<i class="fa-solid fa-floppy-disk"></i>
<save-icon />
存草稿
</div>
<div
@@ -30,9 +30,7 @@
>
发布
</div>
<div v-else class="post-submit-loading">
<i class="fa-solid fa-spinner fa-spin"></i> 发布中...
</div>
<div v-else class="post-submit-loading"><loading-four /> 发布中...</div>
</div>
</div>
<LotteryForm v-if="postType === 'LOTTERY'" :data="lottery" />

View File

@@ -25,7 +25,7 @@
<div class="point-info">
<p v-if="authState.loggedIn && point !== null">
<span><i class="fas fa-coins coin-icon"></i></span>我的积分<span
<span><paper-money-two class="coin-icon" /></span>我的积分<span
class="point-value"
>{{ point }}</span
>
@@ -37,7 +37,7 @@
<BaseImage class="goods-item-image" :src="good.image" alt="good.name" />
<div class="goods-item-name">{{ good.name }}</div>
<div class="goods-item-cost">
<i class="fas fa-coins"></i>
<paper-money-two />
{{ good.cost }} 积分
</div>
<div
@@ -63,11 +63,7 @@
<div class="loading-points-container" v-if="historyLoading">
<l-hatch size="28" stroke="4" speed="3.5" color="var(--primary-color)"></l-hatch>
</div>
<BasePlaceholder
v-else-if="histories.length === 0"
text="暂无积分记录"
icon="fas fa-inbox"
/>
<BasePlaceholder v-else-if="histories.length === 0" text="暂无积分记录" icon="inbox" />
<div class="timeline-container" v-else>
<BaseTimeline :items="histories">
<template #item="{ item }">
@@ -189,7 +185,7 @@
参与获得 {{ item.amount }} 积分
</template>
<template v-else-if="item.type === 'SYSTEM_ONLINE'"> 积分历史系统上线 </template>
<i class="fas fa-coins"></i> 你目前的积分是 {{ item.balance }}
<paper-money-two /> 你目前的积分是 {{ item.balance }}
</div>
<div class="history-time">{{ TimeManager.format(item.createdAt) }}</div>
</template>
@@ -242,18 +238,18 @@ const loading = ref(false)
const selectedGood = ref(null)
const iconMap = {
POST: 'fas fa-file-alt',
COMMENT: 'fas fa-comment',
POST_LIKED: 'fas fa-thumbs-up',
COMMENT_LIKED: 'fas fa-thumbs-up',
INVITE: 'fas fa-user-plus',
SYSTEM_ONLINE: 'fas fa-clock',
REDEEM: 'fas fa-gift',
FEATURE: 'fas fa-star',
LOTTERY_JOIN: 'fas fa-ticket-alt',
LOTTERY_REWARD: 'fas fa-ticket-alt',
POST_LIKE_CANCELLED: 'fas fa-thumbs-down',
COMMENT_LIKE_CANCELLED: 'fas fa-thumbs-down',
POST: 'file-text',
COMMENT: 'comment-icon',
POST_LIKED: 'like',
COMMENT_LIKED: 'like',
INVITE: 'add-user',
SYSTEM_ONLINE: 'history-icon',
REDEEM: 'gift',
FEATURE: 'star',
LOTTERY_JOIN: 'medal-one',
LOTTERY_REWARD: 'fireworks',
POST_LIKE_CANCELLED: 'clear-icon',
COMMENT_LIKE_CANCELLED: 'clear-icon',
}
const loadTrend = async () => {

View File

@@ -12,9 +12,9 @@
<TagSelect v-model="selectedTags" creatable />
</div>
<div class="post-options-right">
<div class="post-clear" @click="clearPost"><i class="fa-solid fa-eraser"></i> 清空</div>
<div class="post-clear" @click="clearPost"><clear-icon /> 清空</div>
<div class="ai-generate" @click="aiGenerate">
<i class="fa-solid fa-robot"></i>
<smart-optimization />
MD 格式优化
</div>
<div class="post-cancel" @click="cancelEdit">取消</div>
@@ -26,9 +26,7 @@
>
更新
</div>
<div v-else class="post-submit-loading">
<i class="fa-solid fa-spinner fa-spin"></i> 更新中...
</div>
<div v-else class="post-submit-loading"><loading-four /> 更新中...</div>
</div>
</div>
</div>

View File

@@ -22,7 +22,7 @@
class="article-subscribe-button"
@click="subscribePost"
>
<i class="fas fa-user-plus"></i>
<people-plus />
<div class="article-subscribe-button-text">
{{ isMobile ? '订阅' : '订阅文章' }}
</div>
@@ -32,14 +32,14 @@
class="article-unsubscribe-button"
@click="unsubscribePost"
>
<i class="fas fa-user-minus"></i>
<people-minus-one />
<div class="article-unsubscribe-button-text">
{{ isMobile ? '退订' : '取消订阅' }}
</div>
</div>
<DropdownMenu v-if="articleMenuItems.length > 0" :items="articleMenuItems">
<template #trigger>
<i class="fas fa-ellipsis-vertical action-menu-icon"></i>
<more-one class="action-menu-icon" />
</template>
</DropdownMenu>
</div>
@@ -53,7 +53,7 @@
<div v-if="isMobile" class="info-content-header">
<div class="user-name">
{{ author.username }}
<i class="fas fa-medal medal-icon"></i>
<medal-one class="medal-icon" />
<NuxtLink
v-if="author.displayMedal"
class="user-medal"
@@ -69,7 +69,7 @@
<div v-if="!isMobile" class="info-content-header">
<div class="user-name">
{{ author.username }}
<i class="fas fa-medal medal-icon"></i>
<medal-one class="medal-icon" />
<NuxtLink
v-if="author.displayMedal"
class="user-medal"
@@ -88,7 +88,7 @@
<div class="article-footer-container">
<ReactionsGroup v-model="postReactions" content-type="post" :content-id="postId">
<div class="make-reaction-item copy-link" @click="copyPostLink">
<i class="fas fa-link"></i>
<link-icon />
</div>
</ReactionsGroup>
</div>
@@ -707,8 +707,8 @@ const unsubscribePost = async () => {
const fetchCommentSorts = () => {
return Promise.resolve([
{ id: 'NEWEST', name: '最新', icon: 'fas fa-clock' },
{ id: 'OLDEST', name: '最旧', icon: 'fas fa-hourglass-start' },
{ id: 'NEWEST', name: '最新', icon: 'lightning' },
{ id: 'OLDEST', name: '最旧', icon: 'history-icon' },
// { id: 'MOST_INTERACTIONS', name: '最多互动', icon: 'fas fa-fire' }
])
}

View File

@@ -7,7 +7,7 @@
@crop="onCropped"
/>
<div v-if="isLoadingPage" class="loading-page">
<l-hatch size="20" stroke="4" speed="3.5" color="var(--primary-color)"></l-hatch>
<l-hatch size="28" stroke="4" speed="3.5" color="var(--primary-color)"></l-hatch>
</div>
<div v-else>
<div class="settings-title">个人资料设置</div>
@@ -23,7 +23,7 @@
</div>
<div class="form-row username-row">
<BaseInput
icon="fas fa-user"
icon="user-icon"
v-model="username"
@input="usernameError = ''"
placeholder="用户名"
@@ -133,15 +133,15 @@ const onCropped = ({ file, url }) => {
}
const fetchPublishModes = () => {
return Promise.resolve([
{ id: 'DIRECT', name: '直接发布', icon: 'fas fa-bolt' },
{ id: 'REVIEW', name: '审核后发布', icon: 'fas fa-search' },
{ id: 'DIRECT', name: '直接发布', icon: 'send-icon' },
{ id: 'REVIEW', name: '审核后发布', icon: 'search-icon' },
])
}
const fetchPasswordStrengths = () => {
return Promise.resolve([
{ id: 'LOW', name: '低', icon: 'fas fa-lock-open' },
{ id: 'MEDIUM', name: '中', icon: 'fas fa-lock' },
{ id: 'HIGH', name: '高', icon: 'fas fa-user-shield' },
{ id: 'LOW', name: '低', icon: 'unlock' },
{ id: 'MEDIUM', name: '中', icon: 'lock-one' },
{ id: 'HIGH', name: '高', icon: 'lock' },
])
}
const fetchAiLimits = () => {
@@ -154,8 +154,8 @@ const fetchAiLimits = () => {
}
const fetchRegisterModes = () => {
return Promise.resolve([
{ id: 'DIRECT', name: '直接注册', icon: 'fas fa-user-check' },
{ id: 'WHITELIST', name: '白名单邀请制', icon: 'fas fa-envelope' },
{ id: 'DIRECT', name: '直接注册', icon: 'send-icon' },
{ id: 'WHITELIST', name: '白名单邀请制', icon: 'search-icon' },
])
}
const loadAdminConfig = async () => {

View File

@@ -6,16 +6,11 @@
</div>
<div v-if="emailStep === 0" class="email-signup-page-content">
<BaseInput
icon="fas fa-envelope"
v-model="email"
@input="emailError = ''"
placeholder="邮箱"
/>
<BaseInput icon="mail" v-model="email" @input="emailError = ''" placeholder="邮箱" />
<div v-if="emailError" class="error-message">{{ emailError }}</div>
<BaseInput
icon="fas fa-user"
icon="user-icon"
v-model="username"
@input="usernameError = ''"
placeholder="用户名"
@@ -23,7 +18,7 @@
<div v-if="usernameError" class="error-message">{{ usernameError }}</div>
<BaseInput
icon="fas fa-lock"
icon="lock"
v-model="password"
@input="passwordError = ''"
type="password"
@@ -40,7 +35,7 @@
</div>
<div v-else class="signup-page-button-primary disabled">
<div class="signup-page-button-text">
<i class="fas fa-spinner fa-spin"></i>
<loading-four />
发送中...
</div>
</div>
@@ -51,7 +46,7 @@
</div>
<div v-if="emailStep === 1" class="email-signup-page-content">
<BaseInput icon="fas fa-envelope" v-model="code" placeholder="邮箱验证码" />
<BaseInput icon="mail" v-model="code" placeholder="邮箱验证码" />
<div
v-if="!isWaitingForEmailVerified"
class="signup-page-button-primary"
@@ -61,7 +56,7 @@
</div>
<div v-else class="signup-page-button-primary disabled">
<div class="signup-page-button-text">
<i class="fas fa-spinner fa-spin"></i>
<loading-four />
验证中...
</div>
</div>

View File

@@ -18,7 +18,7 @@
class="profile-page-header-subscribe-button"
@click="subscribeUser"
>
<i class="fas fa-user-plus"></i>
<add-user />
关注
</div>
<div
@@ -26,11 +26,11 @@
class="profile-page-header-unsubscribe-button"
@click="unsubscribeUser"
>
<i class="fas fa-user-minus"></i>
<reduce-user />
取消关注
</div>
<div v-if="!isMine" class="profile-page-header-subscribe-button" @click="sendMessage">
<i class="fas fa-paper-plane"></i>
<message-one />
发私信
</div>
</div>
@@ -45,7 +45,7 @@
content="经验值可通过发帖、评论等操作获得,达到目标后即可提升等级,解锁更多功能。"
placement="bottom"
>
<i class="fas fa-info-circle profile-exp-info"></i>
<info-icon class="profile-exp-info" />
</ToolTip>
</div>
</div>
@@ -207,7 +207,7 @@
<BasePlaceholder
v-if="filteredTimelineItems.length === 0"
text="暂无时间线"
icon="fas fa-inbox"
icon="inbox"
/>
<div class="timeline-list">
<BaseTimeline :items="filteredTimelineItems">
@@ -305,7 +305,7 @@
</BaseTimeline>
</div>
<div v-else>
<BasePlaceholder text="暂无收藏文章" icon="fas fa-inbox" />
<BasePlaceholder text="暂无收藏文章" icon="inbox" />
</div>
</div>
@@ -368,11 +368,11 @@ const selectedTab = ref(
: 'summary',
)
const tabs = [
{ key: 'summary', label: '总结', icon: 'fas fa-chart-line' },
{ key: 'timeline', label: '时间线', icon: 'fas fa-clock' },
{ key: 'following', label: '关注', icon: 'fas fa-user-plus' },
{ key: 'favorites', label: '收藏', icon: 'fas fa-bookmark' },
{ key: 'achievements', label: '勋章', icon: 'fas fa-medal' },
{ key: 'summary', label: '总结', icon: 'chart-line' },
{ key: 'timeline', label: '时间线', icon: 'alarm-clock' },
{ key: 'following', label: '关注', icon: 'add-user' },
{ key: 'favorites', label: '收藏', icon: 'bookmark' },
{ key: 'achievements', label: '勋章', icon: 'medal-one' },
]
const followTab = ref('followers')
@@ -415,19 +415,19 @@ const fetchSummary = async () => {
const postsRes = await fetch(`${API_BASE_URL}/api/users/${username}/hot-posts`)
if (postsRes.ok) {
const data = await postsRes.json()
hotPosts.value = data.map((p) => ({ icon: 'fas fa-book', post: p }))
hotPosts.value = data.map((p) => ({ icon: 'file-text', post: p }))
}
const repliesRes = await fetch(`${API_BASE_URL}/api/users/${username}/hot-replies`)
if (repliesRes.ok) {
const data = await repliesRes.json()
hotReplies.value = data.map((c) => ({ icon: 'fas fa-comment', comment: c }))
hotReplies.value = data.map((c) => ({ icon: 'comment-icon', comment: c }))
}
const tagsRes = await fetch(`${API_BASE_URL}/api/users/${username}/hot-tags`)
if (tagsRes.ok) {
const data = await tagsRes.json()
hotTags.value = data.map((t) => ({ icon: 'fas fa-tag', tag: t }))
hotTags.value = data.map((t) => ({ icon: 'tag-one', tag: t }))
}
}
@@ -443,19 +443,19 @@ const fetchTimeline = async () => {
const mapped = [
...posts.map((p) => ({
type: 'post',
icon: 'fas fa-book',
icon: 'file-text',
post: p,
createdAt: p.createdAt,
})),
...replies.map((r) => ({
type: r.parentComment ? 'reply' : 'comment',
icon: 'fas fa-comment',
icon: 'comment-icon',
comment: r,
createdAt: r.createdAt,
})),
...tags.map((t) => ({
type: 'tag',
icon: 'fas fa-tag',
icon: 'tag-one',
tag: t,
createdAt: t.createdAt,
})),
@@ -477,7 +477,7 @@ const fetchFavorites = async () => {
const res = await fetch(`${API_BASE_URL}/api/users/${username}/subscribed-posts`)
if (res.ok) {
const data = await res.json()
favoritePosts.value = data.map((p) => ({ icon: 'fas fa-bookmark', post: p }))
favoritePosts.value = data.map((p) => ({ icon: 'bookmark', post: p }))
} else {
favoritePosts.value = []
}

View File

@@ -0,0 +1,152 @@
import { defineNuxtPlugin } from 'nuxt/app'
import {
Pin,
Fireworks,
Gift,
RankingList,
Star,
Edit,
HashtagKey,
Remind,
Info,
ChartLine,
Finance,
Up,
Down,
TagOne,
MedalOne,
Next,
DropDownList,
MoreOne,
SunOne,
Moon,
ComputerOne,
Comment,
Link,
SlyFaceWhitSmile,
Like,
ApplicationMenu,
Search,
Copy,
Loading,
Rss,
MessageEmoji,
AddUser,
ReduceUser,
MessageOne,
AlarmClock,
Bookmark,
Inbox,
LoadingFour,
Mail,
Lock,
User,
Send,
Unlock,
LockOne,
ImageFiles,
ExpandUp,
Close,
ArrowLeft,
CollapseTextInput,
Stopwatch,
PaperMoneyTwo,
Check,
ChartHistogram,
CheckCorrect,
PeoplePlus,
PeopleMinusOne,
SmartOptimization,
Save,
Clear,
FileText,
History,
Lightning,
PeoplesTwo,
Code,
GoodTwo,
Twitter,
Bitcoin,
Fire,
Communication,
WaterLevel,
RobotOne,
Server,
Protection,
} from '@icon-park/vue-next'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component('Pin', Pin)
nuxtApp.vueApp.component('Fireworks', Fireworks)
nuxtApp.vueApp.component('Gift', Gift)
nuxtApp.vueApp.component('RankingList', RankingList)
nuxtApp.vueApp.component('Star', Star)
nuxtApp.vueApp.component('Edit', Edit)
nuxtApp.vueApp.component('HashtagKey', HashtagKey)
nuxtApp.vueApp.component('Remind', Remind)
nuxtApp.vueApp.component('InfoIcon', Info)
nuxtApp.vueApp.component('ChartLine', ChartLine)
nuxtApp.vueApp.component('Finance', Finance)
nuxtApp.vueApp.component('Up', Up)
nuxtApp.vueApp.component('Down', Down)
nuxtApp.vueApp.component('TagOne', TagOne)
nuxtApp.vueApp.component('MedalOne', MedalOne)
nuxtApp.vueApp.component('Next', Next)
nuxtApp.vueApp.component('DropDownList', DropDownList)
nuxtApp.vueApp.component('MoreOne', MoreOne)
nuxtApp.vueApp.component('SunOne', SunOne)
nuxtApp.vueApp.component('Moon', Moon)
nuxtApp.vueApp.component('ComputerOne', ComputerOne)
nuxtApp.vueApp.component('CommentIcon', Comment)
nuxtApp.vueApp.component('LinkIcon', Link)
nuxtApp.vueApp.component('SlyFaceWhitSmile', SlyFaceWhitSmile)
nuxtApp.vueApp.component('Like', Like)
nuxtApp.vueApp.component('ApplicationMenu', ApplicationMenu)
nuxtApp.vueApp.component('SearchIcon', Search)
nuxtApp.vueApp.component('Copy', Copy)
nuxtApp.vueApp.component('Loading', Loading)
nuxtApp.vueApp.component('Rss', Rss)
nuxtApp.vueApp.component('MessageEmoji', MessageEmoji)
nuxtApp.vueApp.component('AddUser', AddUser)
nuxtApp.vueApp.component('ReduceUser', ReduceUser)
nuxtApp.vueApp.component('MessageOne', MessageOne)
nuxtApp.vueApp.component('AlarmClock', AlarmClock)
nuxtApp.vueApp.component('Bookmark', Bookmark)
nuxtApp.vueApp.component('Inbox', Inbox)
nuxtApp.vueApp.component('LoadingFour', LoadingFour)
nuxtApp.vueApp.component('UserIcon', User)
nuxtApp.vueApp.component('Mail', Mail)
nuxtApp.vueApp.component('Lock', Lock)
nuxtApp.vueApp.component('SendIcon', Send)
nuxtApp.vueApp.component('Unlock', Unlock)
nuxtApp.vueApp.component('LockOne', LockOne)
nuxtApp.vueApp.component('ImageFiles', ImageFiles)
nuxtApp.vueApp.component('ExpandUp', ExpandUp)
nuxtApp.vueApp.component('CloseIcon', Close)
nuxtApp.vueApp.component('ArrowLeft', ArrowLeft)
nuxtApp.vueApp.component('CollapseTextInput', CollapseTextInput)
nuxtApp.vueApp.component('Stopwatch', Stopwatch)
nuxtApp.vueApp.component('PaperMoneyTwo', PaperMoneyTwo)
nuxtApp.vueApp.component('Check', Check)
nuxtApp.vueApp.component('ChartHistogram', ChartHistogram)
nuxtApp.vueApp.component('CheckCorrect', CheckCorrect)
nuxtApp.vueApp.component('PeoplePlus', PeoplePlus)
nuxtApp.vueApp.component('PeopleMinusOne', PeopleMinusOne)
nuxtApp.vueApp.component('SmartOptimization', SmartOptimization)
nuxtApp.vueApp.component('SaveIcon', Save)
nuxtApp.vueApp.component('ClearIcon', Clear)
nuxtApp.vueApp.component('FileText', FileText)
nuxtApp.vueApp.component('HistoryIcon', History)
nuxtApp.vueApp.component('Lightning', Lightning)
nuxtApp.vueApp.component('PeoplesTwo', PeoplesTwo)
nuxtApp.vueApp.component('CodeIcon', Code)
nuxtApp.vueApp.component('GoodTwo', GoodTwo)
nuxtApp.vueApp.component('Twitter', Twitter)
nuxtApp.vueApp.component('Bitcoin', Bitcoin)
nuxtApp.vueApp.component('Fire', Fire)
nuxtApp.vueApp.component('Communication', Communication)
nuxtApp.vueApp.component('WaterLevel', WaterLevel)
nuxtApp.vueApp.component('RobotOne', RobotOne)
nuxtApp.vueApp.component('ServerIcon', Server)
nuxtApp.vueApp.component('Protection', Protection)
})

View File

@@ -9,28 +9,28 @@ export const notificationState = reactive({
})
const iconMap = {
POST_VIEWED: 'fas fa-eye',
COMMENT_REPLY: 'fas fa-reply',
POST_REVIEWED: 'fas fa-shield-alt',
POST_REVIEW_REQUEST: 'fas fa-gavel',
POST_UPDATED: 'fas fa-comment-dots',
USER_ACTIVITY: 'fas fa-user',
FOLLOWED_POST: 'fas fa-feather-alt',
USER_FOLLOWED: 'fas fa-user-plus',
USER_UNFOLLOWED: 'fas fa-user-minus',
POST_SUBSCRIBED: 'fas fa-bookmark',
POST_UNSUBSCRIBED: 'fas fa-bookmark',
REGISTER_REQUEST: 'fas fa-user-clock',
ACTIVITY_REDEEM: 'fas fa-coffee',
POINT_REDEEM: 'fas fa-gift',
LOTTERY_WIN: 'fas fa-trophy',
LOTTERY_DRAW: 'fas fa-bullhorn',
POLL_VOTE: 'fas fa-square-poll-vertical',
POLL_RESULT_OWNER: 'fas fa-flag-checkered',
POLL_RESULT_PARTICIPANT: 'fas fa-flag-checkered',
MENTION: 'fas fa-at',
POST_DELETED: 'fas fa-trash',
POST_FEATURED: 'fas fa-star',
POST_VIEWED: 'HistoryIcon',
COMMENT_REPLY: 'MessageOne',
POST_REVIEWED: 'CheckCorrect',
POST_REVIEW_REQUEST: 'FileText',
POST_UPDATED: 'Edit',
USER_ACTIVITY: 'UserIcon',
FOLLOWED_POST: 'Pin',
USER_FOLLOWED: 'AddUser',
USER_UNFOLLOWED: 'ReduceUser',
POST_SUBSCRIBED: 'Bookmark',
POST_UNSUBSCRIBED: 'Bookmark',
REGISTER_REQUEST: 'AlarmClock',
ACTIVITY_REDEEM: 'PaperMoneyTwo',
POINT_REDEEM: 'Gift',
LOTTERY_WIN: 'MedalOne',
LOTTERY_DRAW: 'Fireworks',
POLL_VOTE: 'ChartHistogram',
POLL_RESULT_OWNER: 'RankingList',
POLL_RESULT_PARTICIPANT: 'ChartLine',
MENTION: 'HashtagKey',
POST_DELETED: 'ClearIcon',
POST_FEATURED: 'Star',
}
export async function fetchUnreadCount() {

View File

@@ -23,7 +23,7 @@ export default (apiBaseUrl, websiteBaseUrl) => {
return (
body.map((item) => ({
value: `[🔗${item.title}](${websiteBaseUrl}/posts/${item.id})`,
html: `<div><i class="fas fa-link"></i> ${item.title}</div>`,
html: `<div><link-icon /> ${item.title}</div>`,
})) ?? []
)
} else {