feat(docs): Implement custom item ordering in documentation navigation
- Added ITEM_ORDER constant to define custom sorting for specific items within categories. - Updated the sorting logic in generateDocsNavigation to prioritize custom order before alphabetical sorting. - Enhanced comments for clarity in both English and Vietnamese regarding the sorting process.
This commit is contained in:
178
apps/web-docs/SIDEBAR_ORDERING.md
Normal file
178
apps/web-docs/SIDEBAR_ORDERING.md
Normal file
@@ -0,0 +1,178 @@
|
||||
# Hướng dẫn sắp xếp Documentation Sidebar
|
||||
|
||||
## 📋 Tổng quan
|
||||
|
||||
Sidebar navigation có 2 cấp độ sắp xếp:
|
||||
1. **Categories** (Guides, Architecture, Skills, v.v.)
|
||||
2. **Items** trong mỗi category (các file docs)
|
||||
|
||||
## 🎯 Cách sắp xếp
|
||||
|
||||
### 1. Sắp xếp Categories
|
||||
|
||||
Chỉnh sửa trong file: `apps/web-docs/src/lib/docs-generator.ts`
|
||||
|
||||
```typescript
|
||||
const CATEGORY_CONFIG = {
|
||||
'guides': { order: 1, label: { en: 'Guides', vi: 'Hướng dẫn' } },
|
||||
'architecture': { order: 2, label: { en: 'Architecture', vi: 'Kiến trúc' } },
|
||||
'skills': { order: 3, label: { en: 'Skills', vi: 'Kỹ năng' } },
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
**Cách thay đổi:**
|
||||
- Thay đổi `order` để điều chỉnh vị trí (số nhỏ hơn = cao hơn)
|
||||
- Thêm category mới với order tương ứng
|
||||
- Categories không có trong config sẽ có `order: 999` (xuất hiện cuối)
|
||||
|
||||
### 2. Sắp xếp Items trong Category
|
||||
|
||||
Có 2 loại sắp xếp:
|
||||
|
||||
#### A. Custom Order (Ưu tiên)
|
||||
|
||||
Định nghĩa thứ tự cố định cho items quan trọng:
|
||||
|
||||
```typescript
|
||||
const ITEM_ORDER = {
|
||||
'guides': [
|
||||
'getting-started', // Xuất hiện đầu tiên
|
||||
'local-development', // Thứ hai
|
||||
'deployment', // Thứ ba
|
||||
// Các file khác sẽ được sắp xếp alphabetically
|
||||
],
|
||||
'architecture': [
|
||||
'system-design',
|
||||
'service-communication',
|
||||
],
|
||||
'skills': [
|
||||
'project-rules',
|
||||
'comment-code',
|
||||
'api-design',
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
**Lưu ý:**
|
||||
- Dùng **filename** (không có extension `.md`)
|
||||
- Chỉ liệt kê các file quan trọng cần ưu tiên
|
||||
- Các file không có trong danh sách sẽ tự động sắp xếp alphabetically ở cuối
|
||||
|
||||
#### B. Alphabetical (Mặc định)
|
||||
|
||||
Items không được liệt kê trong `ITEM_ORDER` sẽ tự động sắp xếp theo alphabet (A-Z).
|
||||
|
||||
## 📝 Ví dụ thực tế
|
||||
|
||||
### Ví dụ 1: Thêm doc mới "Quick Start"
|
||||
|
||||
1. Tạo file: `docs/en/guides/quick-start.md`
|
||||
2. Muốn nó xuất hiện đầu tiên? Thêm vào `ITEM_ORDER`:
|
||||
|
||||
```typescript
|
||||
const ITEM_ORDER = {
|
||||
'guides': [
|
||||
'quick-start', // ← Thêm dòng này
|
||||
'getting-started',
|
||||
'local-development',
|
||||
'deployment',
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
### Ví dụ 2: Thay đổi thứ tự categories
|
||||
|
||||
Muốn Skills xuất hiện trước Architecture:
|
||||
|
||||
```typescript
|
||||
const CATEGORY_CONFIG = {
|
||||
'guides': { order: 1, ... },
|
||||
'skills': { order: 2, ... }, // ← Từ 3 → 2
|
||||
'architecture': { order: 3, ... }, // ← Từ 2 → 3
|
||||
};
|
||||
```
|
||||
|
||||
### Ví dụ 3: Category mới "Tutorials"
|
||||
|
||||
```typescript
|
||||
const CATEGORY_CONFIG = {
|
||||
// ... existing categories
|
||||
'tutorials': {
|
||||
order: 8,
|
||||
label: { en: 'Tutorials', vi: 'Hướng dẫn chi tiết' }
|
||||
},
|
||||
};
|
||||
|
||||
const ITEM_ORDER = {
|
||||
// ... existing orders
|
||||
'tutorials': [
|
||||
'beginner-tutorial',
|
||||
'intermediate-tutorial',
|
||||
'advanced-tutorial',
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
## 🔄 Kết quả
|
||||
|
||||
```
|
||||
Sidebar sẽ hiển thị:
|
||||
|
||||
📁 Guides (order: 1)
|
||||
└─ Getting Started (custom order 0)
|
||||
└─ Local Development (custom order 1)
|
||||
└─ Deployment (custom order 2)
|
||||
└─ Advanced Features (alphabetical)
|
||||
└─ Best Practices (alphabetical)
|
||||
|
||||
📁 Architecture (order: 2)
|
||||
└─ System Design (custom order 0)
|
||||
└─ Service Communication (custom order 1)
|
||||
└─ Database Design (alphabetical)
|
||||
|
||||
📁 Skills (order: 3)
|
||||
└─ Project Rules (custom order 0)
|
||||
└─ Comment Code (custom order 1)
|
||||
└─ API Design (custom order 2)
|
||||
└─ Testing Patterns (alphabetical)
|
||||
```
|
||||
|
||||
## ⚡ Reload để xem thay đổi
|
||||
|
||||
Sau khi chỉnh sửa `docs-generator.ts`:
|
||||
1. Lưu file
|
||||
2. Refresh trang web (Ctrl/Cmd + R)
|
||||
3. Navigation cache sẽ tự động rebuild
|
||||
|
||||
## 🎨 Tips
|
||||
|
||||
1. **Giữ custom order ngắn gọn**: Chỉ liệt kê 3-5 items quan trọng nhất
|
||||
2. **Đặt tên file có ý nghĩa**: Alphabetical sorting sẽ hợp lý hơn
|
||||
3. **Consistency**: Dùng cùng naming convention cho tất cả files
|
||||
4. **Documentation**: Thêm comment giải thích tại sao sắp xếp như vậy
|
||||
|
||||
## 📌 Checklist
|
||||
|
||||
Khi thêm doc mới:
|
||||
- [ ] Tạo file `.md` trong thư mục category phù hợp
|
||||
- [ ] Kiểm tra xem có cần custom order không
|
||||
- [ ] Nếu cần, thêm vào `ITEM_ORDER`
|
||||
- [ ] Test bằng cách refresh trang
|
||||
- [ ] Kiểm tra cả EN và VI locale
|
||||
|
||||
## ❓ Troubleshooting
|
||||
|
||||
### Doc không xuất hiện trong sidebar
|
||||
- Kiểm tra file có extension `.md` không
|
||||
- File không được đặt tên là `README.md` (bị exclude)
|
||||
- Thư mục category có trong `CATEGORY_CONFIG` không
|
||||
|
||||
### Thứ tự không đúng
|
||||
- Kiểm tra typo trong filename ở `ITEM_ORDER`
|
||||
- Đảm bảo dùng filename (không có `.md`)
|
||||
- Clear browser cache và hard refresh
|
||||
|
||||
### Category mới không xuất hiện
|
||||
- Thêm vào `CATEGORY_CONFIG` với order phù hợp
|
||||
- Đảm bảo có ít nhất 1 file `.md` trong thư mục
|
||||
@@ -29,6 +29,28 @@ const CATEGORY_CONFIG: Record<string, { order: number; label: { en: string; vi:
|
||||
'onboarding': { order: 7, label: { en: 'Onboarding', vi: 'Hướng dẫn mới' } },
|
||||
};
|
||||
|
||||
// EN: Custom ordering for specific items within categories
|
||||
// VI: Thứ tự tùy chỉnh cho các items cụ thể trong mỗi category
|
||||
// Items not listed here will be sorted alphabetically after the ordered ones
|
||||
const ITEM_ORDER: Record<string, string[]> = {
|
||||
'guides': [
|
||||
'getting-started', // EN: Always show getting started first / VI: Luôn hiển thị getting started đầu tiên
|
||||
'local-development', // EN: Then local setup / VI: Sau đó là local setup
|
||||
'deployment', // EN: Then deployment / VI: Sau đó là deployment
|
||||
// EN: Other items will be alphabetically sorted / VI: Các items khác sẽ được sắp xếp theo alphabet
|
||||
],
|
||||
'architecture': [
|
||||
'system-design', // EN: Overview first / VI: Overview trước
|
||||
'service-communication', // EN: Then communication / VI: Sau đó là communication
|
||||
],
|
||||
'skills': [
|
||||
'project-rules', // EN: Project rules first / VI: Project rules trước
|
||||
'comment-code', // EN: Then coding standards / VI: Sau đó là coding standards
|
||||
'api-design', // EN: Then API design / VI: Sau đó là API design
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* EN: Extract title from markdown file
|
||||
* VI: Trích xuất tiêu đề từ file markdown
|
||||
@@ -170,9 +192,30 @@ export function generateDocsNavigation(): NavGroup[] {
|
||||
label: { en: category.charAt(0).toUpperCase() + category.slice(1), vi: category.charAt(0).toUpperCase() + category.slice(1) }
|
||||
};
|
||||
|
||||
// EN: Sort items alphabetically
|
||||
// VI: Sắp xếp items theo thứ tự bảng chữ cái
|
||||
items.sort((a, b) => a.label.en.localeCompare(b.label.en));
|
||||
// EN: Sort items by custom order first, then alphabetically
|
||||
// VI: Sắp xếp items theo thứ tự tùy chỉnh trước, sau đó theo alphabet
|
||||
const customOrder = ITEM_ORDER[category] || [];
|
||||
|
||||
items.sort((a, b) => {
|
||||
const aSlugName = a.slug.split('/')[1]; // EN: Get filename from slug / VI: Lấy filename từ slug
|
||||
const bSlugName = b.slug.split('/')[1];
|
||||
|
||||
const aIndex = customOrder.indexOf(aSlugName);
|
||||
const bIndex = customOrder.indexOf(bSlugName);
|
||||
|
||||
// EN: If both have custom order, use that / VI: Nếu cả hai có thứ tự tùy chỉnh, dùng nó
|
||||
if (aIndex !== -1 && bIndex !== -1) {
|
||||
return aIndex - bIndex;
|
||||
}
|
||||
|
||||
// EN: Items with custom order come first / VI: Items có thứ tự tùy chỉnh xuất hiện trước
|
||||
if (aIndex !== -1) return -1;
|
||||
if (bIndex !== -1) return 1;
|
||||
|
||||
// EN: Otherwise sort alphabetically / VI: Ngược lại sắp xếp theo alphabet
|
||||
return a.label.en.localeCompare(b.label.en);
|
||||
});
|
||||
|
||||
|
||||
navGroups.push({
|
||||
id: category,
|
||||
|
||||
Reference in New Issue
Block a user