Update README.md
Browse files
README.md
CHANGED
|
@@ -1,382 +1,14 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
> MeNav 是一个轻量级、高度可定制的个人导航网站生成器,让您轻松创建属于自己的导航主页。无需数据库和后端服务,完全静态部署,支持一键 Fork 部署到 GitHub Pages,还可以从浏览器书签一键导入网站。配合 [MarksVault](https://github.com/rbetree/MarksVault) 浏览器扩展,更支持书签自动同步和导航站自动更新。
|
| 16 |
-
|
| 17 |
-
如果觉得项目有用,欢迎 Star/Fork 支持,谢谢!
|
| 18 |
-
|
| 19 |
-
[直接开始部署>>](#部署方式)
|
| 20 |
-
|
| 21 |
-
## 预览
|
| 22 |
-
|
| 23 |
-
[在线访问](https://rbetree.github.io/menav/)
|
| 24 |
-
|
| 25 |
-
<p align="center">
|
| 26 |
-
<img src="assets/preview_light.png" alt="明亮主题预览" width="48%">
|
| 27 |
-
<img src="assets/preview_dark.png" alt="黑暗主题预览" width="48%">
|
| 28 |
-
</p>
|
| 29 |
-
|
| 30 |
-
## 特点
|
| 31 |
-
|
| 32 |
-
- 简洁美观的响应式布局设计
|
| 33 |
-
- 集成外部搜索引擎
|
| 34 |
-
- 分类展示网站链接
|
| 35 |
-
- 模块化配置
|
| 36 |
-
- 支持从浏览器导入书签
|
| 37 |
-
- 支持2-4层级的多层级嵌套结构
|
| 38 |
-
- 与 [MarksVault](https://github.com/rbetree/MarksVault) 浏览器扩展集成,支持自动推送书签
|
| 39 |
-
- 可部署到GitHub Pages或任何类似的CI/CD服务
|
| 40 |
-
|
| 41 |
-
> 历史更新记录已迁移至 [`CHANGELOG.md`](CHANGELOG.md),README 不再维护该部分。
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
## 技术栈
|
| 45 |
-
|
| 46 |
-
- HTML5 + CSS3
|
| 47 |
-
- JavaScript (原生)
|
| 48 |
-
- Handlebars 模板引擎
|
| 49 |
-
- Google Favicon API + Font Awesome 图标
|
| 50 |
-
|
| 51 |
-
## 项目结构
|
| 52 |
-
|
| 53 |
-
```text
|
| 54 |
-
menav/
|
| 55 |
-
├── src/ # 生成器、书签处理、前端脚本(入口:src/generator.js)
|
| 56 |
-
├── templates/ # Handlebars 模板(layouts/pages/components)
|
| 57 |
-
├── config/ # 模块化配置
|
| 58 |
-
├── assets/ # 静态资源
|
| 59 |
-
├── bookmarks/ # 书签导入相关
|
| 60 |
-
└── dist/ # 构建产物
|
| 61 |
-
```
|
| 62 |
-
|
| 63 |
-
## 文档导航
|
| 64 |
-
|
| 65 |
-
- 历史更新记录(README 不再维护):[`CHANGELOG.md`](CHANGELOG.md)
|
| 66 |
-
- 更新说明2025/12/27(兼容性移除 / 迁移指南):[`config/update-instructions-20251227.md`](config/update-instructions-20251227.md)
|
| 67 |
-
- 配置系统(完全替换策略、目录结构、示例):[`config/README.md`](config/README.md)
|
| 68 |
-
- 书签导入(格式要求、流程、常见问题):[`bookmarks/README.md`](bookmarks/README.md)
|
| 69 |
-
- 模板系统(组件、回退、数据流):[`templates/README.md`](templates/README.md)
|
| 70 |
-
- 源码结构(各脚本职责):[`src/README.md`](src/README.md)
|
| 71 |
-
- Handlebars helpers(模板辅助函数):[`src/helpers/README.md`](src/helpers/README.md)
|
| 72 |
-
- 静态资源(样式/图片等):[`assets/README.md`](assets/README.md)
|
| 73 |
-
|
| 74 |
-
## 快速开始
|
| 75 |
-
|
| 76 |
-
用于本地开发预览与构建静态站点;在线部署见 [部署方式](#部署方式)。
|
| 77 |
-
|
| 78 |
-
<details>
|
| 79 |
-
<summary>点击展开</summary>
|
| 80 |
-
|
| 81 |
-
通过以下步骤快速设置您的个人导航站:
|
| 82 |
-
|
| 83 |
-
1. 克隆仓库
|
| 84 |
-
|
| 85 |
-
```bash
|
| 86 |
-
git clone https://github.com/rbetree/menav.git
|
| 87 |
-
cd menav
|
| 88 |
-
```
|
| 89 |
-
|
| 90 |
-
2. 安装依赖
|
| 91 |
-
|
| 92 |
-
```bash
|
| 93 |
-
# 安装依赖
|
| 94 |
-
npm install
|
| 95 |
-
```
|
| 96 |
-
|
| 97 |
-
(本仓库的 GitHub Actions/CI 已改为使用 `npm ci`,以获得更稳定、可复现的依赖安装(基于 `package-lock.json`);本地开发可继续使用 `npm install`,也可直接使用 `npm ci`。)
|
| 98 |
-
|
| 99 |
-
3. 完成配置(见[设置配置文件](#设置配置文件))
|
| 100 |
-
4. 导入书签(可选)
|
| 101 |
-
- 将浏览器导出的HTML格式书签文件放入`bookmarks`目录
|
| 102 |
-
- 运行书签处理命令:
|
| 103 |
-
|
| 104 |
-
```bash
|
| 105 |
-
npm run import-bookmarks
|
| 106 |
-
```
|
| 107 |
-
|
| 108 |
-
- 若希望生成结果保持确定性(便于版本管理,减少时间戳导致的无意义 diff):
|
| 109 |
-
|
| 110 |
-
```bash
|
| 111 |
-
MENAV_BOOKMARKS_DETERMINISTIC=1 npm run import-bookmarks
|
| 112 |
-
```
|
| 113 |
-
|
| 114 |
-
- 系统会自动将书签转换为配置文件保存到`config/user/pages/bookmarks.yml`
|
| 115 |
-
|
| 116 |
-
- **注意**:`npm run dev`命令不会自动处理书签文件,必须先手动运行上述命令
|
| 117 |
-
- `npm run dev` 默认会刷新 `articles/projects` 的联网缓存(若你希望离线启动,请使用 `npm run dev:offline`)
|
| 118 |
-
|
| 119 |
-
5. 构建
|
| 120 |
-
|
| 121 |
-
```bash
|
| 122 |
-
# 启动开发服务器
|
| 123 |
-
npm run dev
|
| 124 |
-
```
|
| 125 |
-
|
| 126 |
-
```bash
|
| 127 |
-
# 离线启动开发服务器(不刷新联网缓存)
|
| 128 |
-
npm run dev:offline
|
| 129 |
-
```
|
| 130 |
-
|
| 131 |
-
```bash
|
| 132 |
-
# 生成静态HTML文件
|
| 133 |
-
npm run build
|
| 134 |
-
```
|
| 135 |
-
|
| 136 |
-
构建后的文件位于`dist`目录
|
| 137 |
-
|
| 138 |
-
6. 提交前检查(推荐)
|
| 139 |
-
|
| 140 |
-
```bash
|
| 141 |
-
# 一键检查(语法检查 + 单元测试 + 构建)
|
| 142 |
-
npm run check
|
| 143 |
-
```
|
| 144 |
-
|
| 145 |
-
(可选)格式化代码:
|
| 146 |
-
|
| 147 |
-
```bash
|
| 148 |
-
npm run format
|
| 149 |
-
```
|
| 150 |
-
|
| 151 |
-
</details>
|
| 152 |
-
|
| 153 |
-
## 部署方式
|
| 154 |
-
|
| 155 |
-
用于将生成的静态站点发布到 服务器 or CI/CD;本地构建见 [快速开始](#快速开始)。
|
| 156 |
-
|
| 157 |
-
### 快速部署到GitHub Pages(推荐)
|
| 158 |
-
|
| 159 |
-
<details>
|
| 160 |
-
<summary>点击展开</summary>
|
| 161 |
-
|
| 162 |
-
#### 第一步:前置设置
|
| 163 |
-
|
| 164 |
-
1. Fork仓库:
|
| 165 |
-
- 点击右上角的 Fork 按钮复制此仓库到您的账号
|
| 166 |
-
|
| 167 |
-
2. 启用Actions:
|
| 168 |
-
- 进入fork后的仓库
|
| 169 |
-
- 点击顶部的 "Actions" 标签页
|
| 170 |
-
- 点击绿色按钮 "I understand my workflows, go ahead and enable them"
|
| 171 |
-
|
| 172 |
-
3. 配置Pages:
|
| 173 |
-
- 进入仓库的 Settings -> Pages
|
| 174 |
-
- 在 "Build and deployment" 部分
|
| 175 |
-
- Source: 选择 "GitHub Actions"
|
| 176 |
-
|
| 177 |
-
#### 第二步:自定义配置
|
| 178 |
-
|
| 179 |
-
创建个人配置文件:
|
| 180 |
-
|
| 181 |
-
- **重要:** 始终创建自己的用户配置文件,不要直接修改默认配置文件
|
| 182 |
-
- 完成配置文件(见[设置配置文件](#设置配置文件))
|
| 183 |
-
- 提交您的配置文件到仓库
|
| 184 |
-
|
| 185 |
-
#### 第三步:等待自动部署
|
| 186 |
-
|
| 187 |
-
- GitHub Actions会自动检测您的更改
|
| 188 |
-
- 构建并部署您的网站
|
| 189 |
-
- 部署完成后,您可以在 Settings -> Pages 中找到您的网站地址
|
| 190 |
-
- 站点内容的“时效性数据”(RSS 文章聚合、projects 仓库统计)会由部署工作流在构建前自动刷新
|
| 191 |
-
- 也支持定时刷新:默认每天 UTC 02:00 触发一次(GitHub Actions cron 使用 UTC;北京时间=UTC+8,可在 `.github/workflows/deploy.yml` 中调整 `schedule.cron`)
|
| 192 |
-
|
| 193 |
-
**重要: Sync fork后需要手动触发工作流**:
|
| 194 |
-
|
| 195 |
-
- 当您使用GitHub界面上的"Sync fork"按钮同步本仓库的更新后
|
| 196 |
-
- GitHub Actions工作流不会自动运行
|
| 197 |
-
- 您需要手动触发构建流程:
|
| 198 |
-
- 进入 Actions 标签页
|
| 199 |
-
- 选择左侧的 "Build and Deploy" 工作流
|
| 200 |
-
- 点击 "Run workflow" 按钮
|
| 201 |
-
|
| 202 |
-
</details>
|
| 203 |
-
|
| 204 |
-
### Docker 部署(可选)
|
| 205 |
-
|
| 206 |
-
<details>
|
| 207 |
-
<summary>点击展开</summary>
|
| 208 |
-
|
| 209 |
-
仓库已内置 `docker-compose.yml`,并提供 GHCR 预构建镜像;两种方式都建议统一使用 Docker Compose。
|
| 210 |
-
|
| 211 |
-
> 说明:容器每次启动都会在容器内执行 `npm run build` 生成 `dist/`,然后用 nginx 提供静态文件。
|
| 212 |
-
>
|
| 213 |
-
> 请在仓库根目录执行(需要 `config/_default` 等文件)。
|
| 214 |
-
|
| 215 |
-
#### 方式 A:使用预构建镜像(推荐,免本地构建)
|
| 216 |
-
|
| 217 |
-
```bash
|
| 218 |
-
docker compose pull
|
| 219 |
-
docker compose up -d --no-build
|
| 220 |
-
```
|
| 221 |
-
|
| 222 |
-
#### 方式 B:本地构建镜像(适合二次开发/改源码)
|
| 223 |
-
|
| 224 |
-
```bash
|
| 225 |
-
docker compose up -d --build
|
| 226 |
-
```
|
| 227 |
-
|
| 228 |
-
默认访问地址:`http://localhost:8080`
|
| 229 |
-
|
| 230 |
-
#### 可选参数(环境变量)
|
| 231 |
-
|
| 232 |
-
```bash
|
| 233 |
-
MENAV_PORT=80 MENAV_ENABLE_SYNC=true MENAV_IMPORT_BOOKMARKS=true docker compose up -d --no-build
|
| 234 |
-
```
|
| 235 |
-
|
| 236 |
-
- `MENAV_PORT`:宿主机端口(默认 `8080`)
|
| 237 |
-
- `MENAV_ENABLE_SYNC`:启动构建时是否联网执行 `sync-*`(默认 `false`,更稳定)
|
| 238 |
-
- `MENAV_IMPORT_BOOKMARKS`:启动构建前是否执行 `npm run import-bookmarks`(默认 `false`)
|
| 239 |
-
|
| 240 |
-
#### 配置与更新
|
| 241 |
-
|
| 242 |
-
- 配置目录挂载在 `./config`,个人配置按“完全替换策略”建议:将 `config/_default/` 完整复制到 `config/user/` 再修改(见 [设置配置文件](#设置配置文件) 与 `config/README.md`)。
|
| 243 |
-
- 如需导入书签:将浏览器导出的书签 HTML 放到 `./bookmarks/`,并设置 `MENAV_IMPORT_BOOKMARKS=true` 后重启容器。
|
| 244 |
-
- 修改配置/书签后生效方式(触发重新构建):
|
| 245 |
-
|
| 246 |
-
```bash
|
| 247 |
-
docker compose restart menav
|
| 248 |
-
```
|
| 249 |
-
|
| 250 |
-
</details>
|
| 251 |
-
|
| 252 |
-
### 部署到服务器
|
| 253 |
-
|
| 254 |
-
<details>
|
| 255 |
-
<summary>点击展开</summary>
|
| 256 |
-
|
| 257 |
-
如果您想部署到自己的Web服务器,只需要以下几个步骤:
|
| 258 |
-
|
| 259 |
-
1. 构建静态网站:
|
| 260 |
-
|
| 261 |
-
```bash
|
| 262 |
-
npm run build
|
| 263 |
-
```
|
| 264 |
-
|
| 265 |
-
2. 复制构建结果:
|
| 266 |
-
- 所有生成的静态文件都位于 `dist` 目录中
|
| 267 |
-
- 将 `dist` 目录中的所有文件复制到您的Web服务器根目录
|
| 268 |
-
|
| 269 |
-
3. 配置Web服务器:
|
| 270 |
-
- 确保服务器配置为提供静态文件
|
| 271 |
-
- 对于Apache: 在网站根目录中已有正确的 .htaccess 文件
|
| 272 |
-
- 对于Nginx: 添加以下配置到您的server块:
|
| 273 |
-
|
| 274 |
-
```nginx
|
| 275 |
-
server {
|
| 276 |
-
listen 80;
|
| 277 |
-
server_name your-domain.com;
|
| 278 |
-
root /path/to/dist;
|
| 279 |
-
index index.html;
|
| 280 |
-
|
| 281 |
-
location / {
|
| 282 |
-
try_files $uri $uri/ /404.html;
|
| 283 |
-
}
|
| 284 |
-
}
|
| 285 |
-
```
|
| 286 |
-
|
| 287 |
-
4. 更新配置:
|
| 288 |
-
- 如果您想在服务器上更新网站,只需重复上述步骤1-2
|
| 289 |
-
- 或者设置自动部署流程,例如使用GitLab CI/CD或Jenkins
|
| 290 |
-
|
| 291 |
-
</details>
|
| 292 |
-
|
| 293 |
-
### 其他CI/CD托管选项
|
| 294 |
-
|
| 295 |
-
<details>
|
| 296 |
-
<summary>点击展开</summary>
|
| 297 |
-
|
| 298 |
-
除了GitHub Pages外,您还可以使用其他各种CI/CD服务部署MeNav:
|
| 299 |
-
|
| 300 |
-
**如 Vercel / Netlify / Cloudflare Pages**:
|
| 301 |
-
|
| 302 |
-
- 连接您的GitHub仓库
|
| 303 |
-
- 设置构建命令为`npm run build`
|
| 304 |
-
- 设置输出目录为`dist`
|
| 305 |
-
|
| 306 |
-
Vercel 部署:
|
| 307 |
-
|
| 308 |
-
1. 登录 Vercel,点击 `Add New...` → `Project`
|
| 309 |
-
2. 选择 `Import Git Repository`,连接并选择你的 MeNav 仓库
|
| 310 |
-
3. 构建配置(一般选择 `Other` 或保持默认自动识别即可):
|
| 311 |
-
- `Build Command`: `npm run build`
|
| 312 |
-
- `Output Directory`: `dist`
|
| 313 |
-
- `Install Command`(可选,但更稳定):`npm ci`
|
| 314 |
-
4. 点击 `Deploy`,等待完成后用 Vercel 分配的域名/自定义域名访问
|
| 315 |
-
|
| 316 |
-
**如果您只使用第三方平台部署(不使用 GitHub Pages)**:
|
| 317 |
-
|
| 318 |
-
为避免 GitHub Actions 中的 Pages 配置错误,您可以禁用 GitHub Pages 部署步骤:
|
| 319 |
-
|
| 320 |
-
1. 进入仓库的 Settings -> Secrets and variables -> Actions
|
| 321 |
-
2. 点击 "Variables" 标签页
|
| 322 |
-
3. 点击 "New repository variable"
|
| 323 |
-
4. 名称填写:`ENABLE_GITHUB_PAGES`
|
| 324 |
-
5. 值填写:`false`
|
| 325 |
-
6. 点击 "Add variable"
|
| 326 |
-
|
| 327 |
-
设置后,GitHub Actions 仍会自动构建网站(包括书签处理、RSS 同步等),但会跳过 GitHub Pages 部署步骤,避免报错。第三方平台(如 Vercel/Cloudflare Pages)会自动检测到代码变化并部署。
|
| 328 |
-
|
| 329 |
-
> 如果你希望在构建时刷新“时效性数据”(RSS 文章聚合、projects 仓库统计),请将构建命令改为:
|
| 330 |
-
>
|
| 331 |
-
> ```bash
|
| 332 |
-
> npm ci && npm run sync-projects && npm run sync-articles && npm run build
|
| 333 |
-
> ```
|
| 334 |
-
>
|
| 335 |
-
> 说明:`sync-*` 会联网抓取并写入 `dev/` 缓存(仓库默认 gitignore);同步脚本为 best-effort,失败不会阻断后续 `build`。
|
| 336 |
-
>
|
| 337 |
-
> 备注:`dev/` 只用于构建过程的中间缓存,默认不会被提交到仓库;部署时也只会上传 `dist/`,不会包含 `dev/`。
|
| 338 |
-
|
| 339 |
-
> **书签转换依赖 GitHub Actions**
|
| 340 |
-
> 如果需要使用书签自动推送功能,必须先在 GitHub 仓库中启用 GitHub Actions
|
| 341 |
-
>
|
| 342 |
-
> **部署流程**:
|
| 343 |
-
>
|
| 344 |
-
> ```
|
| 345 |
-
> 1. 上传书签 → 2. GitHub Actions 处理 → 3. 使用处理完成的代码在 GitHub Pages 自动部署
|
| 346 |
-
> ↓
|
| 347 |
-
> 4. 其他 CI/CD 托管平台检测到变化 → 5. 使用处理完成的代码自动部署
|
| 348 |
-
> ```
|
| 349 |
-
|
| 350 |
-
无论选择哪种部署方式,请确保创建并使用您自己的配置文件,而不是直接修改默认配置。
|
| 351 |
-
|
| 352 |
-
</details>
|
| 353 |
-
|
| 354 |
-
## 设置配置文件
|
| 355 |
-
|
| 356 |
-
MeNav 使用模块化配置方式,将配置分散到多个 YAML 文件中,更易于管理和维护。
|
| 357 |
-
|
| 358 |
-
完整说明请直接看:[`config/README.md`](config/README.md)(以该文档为准)。
|
| 359 |
-
|
| 360 |
-
> **🔔 重要提示:** 请务必在`config/user/`目录下创建并使用您自己的配置文件,不要直接修改默认配置文件,以便后续更新项目时不会丢失您的个性化设置。
|
| 361 |
-
|
| 362 |
-
在加载配置时遵循以下优先级顺序:
|
| 363 |
-
|
| 364 |
-
1. `config/user/` (用户配置)(优先级最高)
|
| 365 |
-
2. `config/_default/` (默认配置)
|
| 366 |
-
|
| 367 |
-
**注意:** 采用完全替换策略,而非合并。系统会选择存在的用户配置,完全忽略默认配置。
|
| 368 |
-
|
| 369 |
-
### 最小可用配置(快速指引)
|
| 370 |
-
|
| 371 |
-
- 首次使用建议先完整复制 `config/_default/` 到 `config/user/`,再按需修改(因为配置采用“完全替换”策略,不会从默认配置补齐缺失项)。
|
| 372 |
-
- 至少需要有 `config/user/site.yml`(缺失时构建会直接报错退出,避免生成空白站点)。
|
| 373 |
-
|
| 374 |
-
## 书签导入功能
|
| 375 |
-
|
| 376 |
-
MeNav 支持从浏览器导入书签,快速批量添加网站链接;也支持与 MarksVault 扩展集成自动同步。
|
| 377 |
-
|
| 378 |
-
完整说明请直接看:[`bookmarks/README.md`](bookmarks/README.md)(以该文档为准)。
|
| 379 |
-
|
| 380 |
-
## Star-History
|
| 381 |
-
|
| 382 |
-
[](https://www.star-history.com/#rbetree/menav&Date)
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Menav Bookmark Manager
|
| 3 |
+
emoji: 📚
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: indigo
|
| 6 |
+
sdk: docker
|
| 7 |
+
sdk_version: "1.0"
|
| 8 |
+
app_file: Dockerfile
|
| 9 |
+
pinned: false
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
# Menav - 书签管理器
|
| 13 |
+
|
| 14 |
+
这是一个在 Hugging Face Space 上运行的 Menav 书签管理应用。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|