@coffic/cosy-ui 0.6.2 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/collection.ts +104 -0
- package/dist/components/errors/404.astro +15 -0
- package/dist/components/layouts/Header.astro +16 -49
- package/dist/components/layouts/NavItems.astro +45 -0
- package/dist/components/layouts/Sidebar.astro +1 -0
- package/dist/components/layouts/SidebarNav.astro +11 -2
- package/dist/database/BaseDB.ts +173 -142
- package/dist/database/BlogDB.ts +4 -4
- package/dist/database/CourseDB.ts +7 -8
- package/dist/database/ExperimentDB.ts +4 -4
- package/dist/database/LessonDB.ts +4 -4
- package/dist/database/MetaDB.ts +4 -4
- package/dist/entities/BaseDoc.ts +78 -80
- package/dist/entities/BlogDoc.ts +13 -2
- package/dist/entities/CourseDoc.ts +47 -7
- package/dist/entities/ExperimentDoc.ts +6 -9
- package/dist/entities/LessonDoc.ts +6 -6
- package/dist/entities/MetaDoc.ts +2 -2
- package/dist/index.ts +5 -9
- package/dist/utils/link.ts +1 -1
- package/dist/utils/logger.ts +1 -1
- package/dist/utils/path.ts +48 -33
- package/package.json +3 -2
- package/dist/collections/ArticleCollection.ts +0 -19
- package/dist/collections/BlogCollection.ts +0 -28
- package/dist/collections/CourseCollection.ts +0 -11
- package/dist/collections/ExperimentCollection.ts +0 -18
- package/dist/collections/LessonCollection.ts +0 -25
- package/dist/collections/MetaCollection.ts +0 -17
- package/dist/entities/Heading.ts +0 -13
package/dist/database/BlogDB.ts
CHANGED
@@ -4,8 +4,8 @@ import { logger } from '../utils/logger';
|
|
4
4
|
import { type CollectionEntry } from 'astro:content';
|
5
5
|
import { BaseDB } from './BaseDB';
|
6
6
|
|
7
|
-
export const
|
8
|
-
export type BlogEntry = CollectionEntry<typeof
|
7
|
+
export const COLLECTION_BLOG = 'blogs' as const;
|
8
|
+
export type BlogEntry = CollectionEntry<typeof COLLECTION_BLOG>;
|
9
9
|
|
10
10
|
/**
|
11
11
|
* 博客数据库类,用于管理博客内容集合。
|
@@ -23,8 +23,8 @@ export type BlogEntry = CollectionEntry<typeof COLLECTION_NAME>;
|
|
23
23
|
* └── web-performance.md
|
24
24
|
* ```
|
25
25
|
*/
|
26
|
-
class BlogDB extends BaseDB<typeof
|
27
|
-
protected collectionName =
|
26
|
+
class BlogDB extends BaseDB<typeof COLLECTION_BLOG, BlogEntry, BlogDoc> {
|
27
|
+
protected collectionName = COLLECTION_BLOG;
|
28
28
|
|
29
29
|
protected createDoc(entry: BlogEntry): BlogDoc {
|
30
30
|
return BlogDoc.fromEntry(entry);
|
@@ -2,8 +2,8 @@ import CourseDoc from '../entities/CourseDoc';
|
|
2
2
|
import { getCollection, type CollectionEntry } from 'astro:content';
|
3
3
|
import { BaseDB } from './BaseDB';
|
4
4
|
|
5
|
-
export const
|
6
|
-
export type CourseEntry = CollectionEntry<typeof
|
5
|
+
export const COLLECTION_COURSE = 'courses' as const;
|
6
|
+
export type CourseEntry = CollectionEntry<typeof COLLECTION_COURSE>;
|
7
7
|
|
8
8
|
/**
|
9
9
|
* 课程数据库类,用于管理课程内容集合。
|
@@ -29,8 +29,8 @@ export type CourseEntry = CollectionEntry<typeof COLLECTION_NAME>;
|
|
29
29
|
* └── ...
|
30
30
|
* ```
|
31
31
|
*/
|
32
|
-
class CourseDB extends BaseDB<typeof
|
33
|
-
protected collectionName =
|
32
|
+
class CourseDB extends BaseDB<typeof COLLECTION_COURSE, CourseEntry, CourseDoc> {
|
33
|
+
protected collectionName = COLLECTION_COURSE;
|
34
34
|
|
35
35
|
protected createDoc(entry: CourseEntry): CourseDoc {
|
36
36
|
return new CourseDoc(entry);
|
@@ -43,7 +43,7 @@ class CourseDB extends BaseDB<typeof COLLECTION_NAME, CourseEntry, CourseDoc> {
|
|
43
43
|
* @returns 返回指定语言的顶级课程数组
|
44
44
|
*/
|
45
45
|
async allCoursesByLang(lang: string): Promise<CourseDoc[]> {
|
46
|
-
const entries = await getCollection(
|
46
|
+
const entries = await getCollection(COLLECTION_COURSE, ({ id }) => {
|
47
47
|
return id.startsWith(lang) && id.split('/').length === 2;
|
48
48
|
});
|
49
49
|
return entries.map((entry) => new CourseDoc(entry));
|
@@ -55,7 +55,7 @@ class CourseDB extends BaseDB<typeof COLLECTION_NAME, CourseEntry, CourseDoc> {
|
|
55
55
|
* @returns 返回路径参数数组
|
56
56
|
*/
|
57
57
|
async getStaticPaths(): Promise<{ params: { lang: string; slug: string } }[]> {
|
58
|
-
const entries = await getCollection(
|
58
|
+
const entries = await getCollection(COLLECTION_COURSE);
|
59
59
|
return entries.map((entry) => {
|
60
60
|
const doc = new CourseDoc(entry);
|
61
61
|
return {
|
@@ -81,5 +81,4 @@ class CourseDB extends BaseDB<typeof COLLECTION_NAME, CourseEntry, CourseDoc> {
|
|
81
81
|
}
|
82
82
|
|
83
83
|
// 创建并导出单例实例
|
84
|
-
const courseDB = new CourseDB();
|
85
|
-
export default courseDB;
|
84
|
+
export const courseDB = new CourseDB();
|
@@ -3,8 +3,8 @@ import { BaseDB } from './BaseDB';
|
|
3
3
|
import ExperimentDoc from '../entities/ExperimentDoc';
|
4
4
|
import { logger } from '../utils/logger';
|
5
5
|
|
6
|
-
export const
|
7
|
-
export type ExperimentEntry = CollectionEntry<typeof
|
6
|
+
export const COLLECTION_EXPERIMENT = 'experiments' as const;
|
7
|
+
export type ExperimentEntry = CollectionEntry<typeof COLLECTION_EXPERIMENT>;
|
8
8
|
|
9
9
|
/**
|
10
10
|
* 实验数据库类,用于管理实验内容集合
|
@@ -40,8 +40,8 @@ export type ExperimentEntry = CollectionEntry<typeof COLLECTION_NAME>;
|
|
40
40
|
* - 每个语言版本包含完整的课程内容
|
41
41
|
* - 课程目录可以作为 git 子模块独立管理
|
42
42
|
*/
|
43
|
-
class ExperimentDB extends BaseDB<typeof
|
44
|
-
protected collectionName =
|
43
|
+
class ExperimentDB extends BaseDB<typeof COLLECTION_EXPERIMENT, ExperimentEntry, ExperimentDoc> {
|
44
|
+
protected collectionName = COLLECTION_EXPERIMENT;
|
45
45
|
|
46
46
|
protected createDoc(entry: ExperimentEntry): ExperimentDoc {
|
47
47
|
return new ExperimentDoc(entry);
|
@@ -3,8 +3,8 @@ import { BaseDB } from './BaseDB';
|
|
3
3
|
import LessonDoc from '../entities/LessonDoc';
|
4
4
|
import { logger } from '../utils/logger';
|
5
5
|
|
6
|
-
export const
|
7
|
-
export type LessonEntry = CollectionEntry<typeof
|
6
|
+
export const COLLECTION_LESSON = 'lessons' as const;
|
7
|
+
export type LessonEntry = CollectionEntry<typeof COLLECTION_LESSON>;
|
8
8
|
|
9
9
|
/**
|
10
10
|
* 课程数据库类,用于管理课程内容集合
|
@@ -40,8 +40,8 @@ export type LessonEntry = CollectionEntry<typeof COLLECTION_NAME>;
|
|
40
40
|
* - 每个语言版本包含完整的课程内容
|
41
41
|
* - 课程目录可以作为 git 子模块独立管理
|
42
42
|
*/
|
43
|
-
class LessonDB extends BaseDB<typeof
|
44
|
-
protected collectionName =
|
43
|
+
class LessonDB extends BaseDB<typeof COLLECTION_LESSON, LessonEntry, LessonDoc> {
|
44
|
+
protected collectionName = COLLECTION_LESSON;
|
45
45
|
|
46
46
|
protected createDoc(entry: LessonEntry): LessonDoc {
|
47
47
|
return new LessonDoc(entry);
|
package/dist/database/MetaDB.ts
CHANGED
@@ -3,8 +3,8 @@ import { logger } from '../utils/logger';
|
|
3
3
|
import { type CollectionEntry } from 'astro:content';
|
4
4
|
import { BaseDB } from './BaseDB';
|
5
5
|
|
6
|
-
export const
|
7
|
-
export type MetaEntry = CollectionEntry<typeof
|
6
|
+
export const COLLECTION_META = 'meta' as const;
|
7
|
+
export type MetaEntry = CollectionEntry<typeof COLLECTION_META>;
|
8
8
|
|
9
9
|
/**
|
10
10
|
* 元数据数据库类,用于管理网站的元数据内容集合(如"关于我们"等页面)
|
@@ -21,8 +21,8 @@ export type MetaEntry = CollectionEntry<typeof COLLECTION_NAME>;
|
|
21
21
|
* └── terms.md
|
22
22
|
* ```
|
23
23
|
*/
|
24
|
-
class MetaDB extends BaseDB<typeof
|
25
|
-
protected collectionName =
|
24
|
+
class MetaDB extends BaseDB<typeof COLLECTION_META, MetaEntry, MetaDoc> {
|
25
|
+
protected collectionName = COLLECTION_META;
|
26
26
|
|
27
27
|
protected createDoc(entry: MetaEntry): MetaDoc {
|
28
28
|
return new MetaDoc(entry);
|
package/dist/entities/BaseDoc.ts
CHANGED
@@ -17,81 +17,64 @@ export abstract class BaseDoc<
|
|
17
17
|
}
|
18
18
|
|
19
19
|
/**
|
20
|
-
*
|
21
|
-
|
22
|
-
getId(): string {
|
23
|
-
return this.entry.id;
|
24
|
-
}
|
25
|
-
|
26
|
-
/**
|
27
|
-
* 获取文档标题
|
20
|
+
* 获取顶级文档
|
21
|
+
* 子类应该实现此方法以提供正确的顶级文档
|
28
22
|
*/
|
29
|
-
|
30
|
-
return this.entry.data.title as string;
|
31
|
-
}
|
23
|
+
abstract getTopDoc(): Promise<BaseDoc<Collection, T> | null>;
|
32
24
|
|
33
25
|
/**
|
34
|
-
*
|
26
|
+
* 获取子文档
|
27
|
+
* 子类应该实现此方法以提供正确的子文档列表
|
35
28
|
*/
|
36
|
-
|
37
|
-
return this.entry.id.split('/')[0];
|
38
|
-
}
|
29
|
+
abstract getChildren(): Promise<BaseDoc<Collection, T>[]>;
|
39
30
|
|
40
31
|
/**
|
41
|
-
*
|
32
|
+
* 获取文档的层级深度
|
33
|
+
* 例如:对于 ID 为 "zh-cn/blog/typescript" 的文档,深度为3
|
42
34
|
*/
|
43
|
-
|
44
|
-
return this.
|
35
|
+
getLevel(): number {
|
36
|
+
return this.entry.id.split('/').length;
|
45
37
|
}
|
46
38
|
|
47
39
|
/**
|
48
|
-
*
|
40
|
+
* 获取所有祖先文档的ID
|
41
|
+
* 例如:对于 ID 为 "zh-cn/blog/typescript" 的文档,祖先ID为 ["zh-cn/blog", "zh-cn"]
|
42
|
+
* @returns 祖先文档的ID列表
|
49
43
|
*/
|
50
|
-
|
51
|
-
|
44
|
+
getAncestorIds(): string[] {
|
45
|
+
const parts = this.entry.id.split('/');
|
46
|
+
return parts.slice(0, -1).map((part, index) => parts.slice(0, index + 1).join('/'));
|
52
47
|
}
|
53
48
|
|
54
49
|
/**
|
55
|
-
*
|
56
|
-
*
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
/**
|
61
|
-
* 渲染文档内容
|
50
|
+
* 获取指定层级的祖先文档ID
|
51
|
+
* 例如:对于 ID 为 "zh-cn/blog/typescript" 的文档,level=2 的祖先ID为 "zh-cn/blog"
|
52
|
+
* @param level 层级深度,从1开始
|
53
|
+
* @returns 祖先文档的ID
|
62
54
|
*/
|
63
|
-
|
64
|
-
|
55
|
+
getAncestorId(level: number): string {
|
56
|
+
const ancestorIds = this.getAncestorIds();
|
57
|
+
return ancestorIds[level - 1];
|
65
58
|
}
|
66
59
|
|
67
60
|
/**
|
68
|
-
*
|
69
|
-
*
|
61
|
+
* 获取顶级侧边栏项目
|
62
|
+
* 如果有顶级文档,返回顶级文档的侧边栏项目
|
63
|
+
* 否则返回当前文档的侧边栏项目
|
70
64
|
*/
|
71
|
-
|
72
|
-
|
73
|
-
|
65
|
+
async getTopSidebarItem(): Promise<SidebarItemEntity> {
|
66
|
+
const topDoc = await this.getTopDoc();
|
67
|
+
if (topDoc) {
|
68
|
+
return await topDoc.toSidebarItem();
|
69
|
+
}
|
74
70
|
|
75
|
-
/**
|
76
|
-
* 转换为侧边栏项目
|
77
|
-
* 基本实现,只包含当前文档
|
78
|
-
*/
|
79
|
-
async toSidebarItem(): Promise<SidebarItemEntity> {
|
80
71
|
return new SidebarItemEntity({
|
81
72
|
text: this.getTitle(),
|
73
|
+
items: [],
|
82
74
|
link: this.getLink(),
|
83
75
|
});
|
84
76
|
}
|
85
|
-
}
|
86
77
|
|
87
|
-
/**
|
88
|
-
* 层级文档基类,为有层级结构的文档类型提供额外功能
|
89
|
-
* 例如课程等有父子关系的文档
|
90
|
-
*/
|
91
|
-
export abstract class HierarchicalDoc<
|
92
|
-
Collection extends keyof DataEntryMap,
|
93
|
-
T extends CollectionEntry<Collection>,
|
94
|
-
> extends BaseDoc<Collection, T> {
|
95
78
|
/**
|
96
79
|
* 获取父文档ID
|
97
80
|
* 例如:对于 ID 为 "zh-cn/blog/typescript" 的文档,父ID为 "zh-cn/blog"
|
@@ -99,8 +82,7 @@ export abstract class HierarchicalDoc<
|
|
99
82
|
* @returns 父文档ID,如果没有父文档则返回null
|
100
83
|
*/
|
101
84
|
getParentId(): string | null {
|
102
|
-
|
103
|
-
return parts.length > 1 ? parts.slice(0, -1).join('/') : null;
|
85
|
+
return this.getAncestorId(this.getLevel() - 1);
|
104
86
|
}
|
105
87
|
|
106
88
|
/**
|
@@ -110,29 +92,63 @@ export abstract class HierarchicalDoc<
|
|
110
92
|
* 默认实现假设顶级ID是前两部分
|
111
93
|
* 子类可以根据需要覆盖此方法
|
112
94
|
*/
|
113
|
-
|
114
|
-
|
115
|
-
const parts = id.split('/');
|
116
|
-
return parts[0] + '/' + parts[1];
|
95
|
+
getTopDocId(): string {
|
96
|
+
return this.getAncestorId(2);
|
117
97
|
}
|
118
98
|
|
119
99
|
/**
|
120
|
-
*
|
121
|
-
* 子类应该实现此方法以提供正确的顶级文档
|
100
|
+
* 获取文档ID
|
122
101
|
*/
|
123
|
-
|
102
|
+
getId(): string {
|
103
|
+
return this.entry.id;
|
104
|
+
}
|
124
105
|
|
125
106
|
/**
|
126
|
-
*
|
127
|
-
|
107
|
+
* 获取文档标题
|
108
|
+
*/
|
109
|
+
getTitle(): string {
|
110
|
+
return this.entry.data.title as string;
|
111
|
+
}
|
112
|
+
|
113
|
+
/**
|
114
|
+
* 获取文档语言
|
115
|
+
*/
|
116
|
+
getLang(): string {
|
117
|
+
return this.entry.id.split('/')[0];
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* 获取文档slug
|
122
|
+
*/
|
123
|
+
getSlug(): string {
|
124
|
+
return this.getId().split('/').slice(1).join('/');
|
125
|
+
}
|
126
|
+
|
127
|
+
/**
|
128
|
+
* 获取文档描述
|
129
|
+
*/
|
130
|
+
getDescription(): string {
|
131
|
+
return this.entry.data.description as string;
|
132
|
+
}
|
133
|
+
|
134
|
+
/**
|
135
|
+
* 获取文档链接
|
136
|
+
* 每个子类必须实现此方法以提供正确的链接
|
137
|
+
*/
|
138
|
+
abstract getLink(): string;
|
139
|
+
|
140
|
+
/**
|
141
|
+
* 渲染文档内容
|
128
142
|
*/
|
129
|
-
|
143
|
+
async render(): Promise<RenderResult> {
|
144
|
+
return await render(this.entry);
|
145
|
+
}
|
130
146
|
|
131
147
|
/**
|
132
148
|
* 转换为侧边栏项目
|
133
149
|
* 如果文档有子文档,会包含子文档的侧边栏项目
|
134
150
|
*/
|
135
|
-
|
151
|
+
async toSidebarItem(): Promise<SidebarItemEntity> {
|
136
152
|
const debug = false;
|
137
153
|
|
138
154
|
const children = await this.getChildren();
|
@@ -149,22 +165,4 @@ export abstract class HierarchicalDoc<
|
|
149
165
|
link: this.getLink(),
|
150
166
|
});
|
151
167
|
}
|
152
|
-
|
153
|
-
/**
|
154
|
-
* 获取顶级侧边栏项目
|
155
|
-
* 如果有顶级文档,返回顶级文档的侧边栏项目
|
156
|
-
* 否则返回当前文档的侧边栏项目
|
157
|
-
*/
|
158
|
-
async getTopSidebarItem(): Promise<SidebarItemEntity> {
|
159
|
-
const topDoc = await this.getTopDoc();
|
160
|
-
if (topDoc) {
|
161
|
-
return await topDoc.toSidebarItem();
|
162
|
-
}
|
163
|
-
|
164
|
-
return new SidebarItemEntity({
|
165
|
-
text: this.getTitle(),
|
166
|
-
items: [],
|
167
|
-
link: this.getLink(),
|
168
|
-
});
|
169
|
-
}
|
170
168
|
}
|
package/dist/entities/BlogDoc.ts
CHANGED
@@ -2,9 +2,10 @@ import type { BlogEntry } from '../database/BlogDB';
|
|
2
2
|
import { LinkUtil } from '../utils/link';
|
3
3
|
import Tag from './Tag';
|
4
4
|
import { BaseDoc } from './BaseDoc';
|
5
|
-
import {
|
5
|
+
import { COLLECTION_BLOG } from '../database/BlogDB';
|
6
|
+
import blogDB from '../database/BlogDB';
|
6
7
|
|
7
|
-
export default class BlogDoc extends BaseDoc<typeof
|
8
|
+
export default class BlogDoc extends BaseDoc<typeof COLLECTION_BLOG, BlogEntry> {
|
8
9
|
private constructor(entry: BlogEntry) {
|
9
10
|
super(entry);
|
10
11
|
}
|
@@ -13,6 +14,16 @@ export default class BlogDoc extends BaseDoc<typeof COLLECTION_NAME, BlogEntry>
|
|
13
14
|
return new BlogDoc(entry);
|
14
15
|
}
|
15
16
|
|
17
|
+
async getTopDoc(): Promise<BlogDoc | null> {
|
18
|
+
const id = this.getTopDocId();
|
19
|
+
const doc = await blogDB.find(id);
|
20
|
+
return doc;
|
21
|
+
}
|
22
|
+
|
23
|
+
async getChildren(): Promise<BlogDoc[]> {
|
24
|
+
return await blogDB.getChildren(this.entry.id);
|
25
|
+
}
|
26
|
+
|
16
27
|
getLink(): string {
|
17
28
|
return LinkUtil.getBlogLink(this.entry.id, this.getLang());
|
18
29
|
}
|
@@ -1,12 +1,12 @@
|
|
1
|
-
import { logger } from '
|
1
|
+
import { logger } from '../utils/logger';
|
2
2
|
import { SidebarItemEntity } from './SidebarItem';
|
3
3
|
import type { CourseEntry } from '../database/CourseDB';
|
4
|
-
import courseDB from '../database/CourseDB';
|
4
|
+
import { courseDB } from '../database/CourseDB';
|
5
5
|
import { LinkUtil } from '../utils/link';
|
6
|
-
import {
|
7
|
-
import {
|
6
|
+
import { COLLECTION_COURSE } from '../database/CourseDB';
|
7
|
+
import { BaseDoc } from './BaseDoc';
|
8
8
|
|
9
|
-
export default class CourseDoc extends
|
9
|
+
export default class CourseDoc extends BaseDoc<typeof COLLECTION_COURSE, CourseEntry> {
|
10
10
|
constructor(entry: CourseEntry) {
|
11
11
|
super(entry);
|
12
12
|
}
|
@@ -19,14 +19,54 @@ export default class CourseDoc extends HierarchicalDoc<typeof COLLECTION_NAME, C
|
|
19
19
|
return LinkUtil.getCourseLink(this.entry.id);
|
20
20
|
}
|
21
21
|
|
22
|
+
getOrder(): number {
|
23
|
+
return this.entry.data.order;
|
24
|
+
}
|
25
|
+
|
26
|
+
isFolder(): boolean {
|
27
|
+
return this.entry.data.folder;
|
28
|
+
}
|
29
|
+
|
22
30
|
async getTopDoc(): Promise<CourseDoc | null> {
|
23
|
-
const id =
|
31
|
+
const id = this.getTopDocId();
|
32
|
+
const doc = await courseDB.find(id);
|
33
|
+
return doc;
|
34
|
+
}
|
35
|
+
|
36
|
+
async getAncestor(level: number): Promise<CourseDoc | null> {
|
37
|
+
const debug = false;
|
38
|
+
if (debug) {
|
39
|
+
logger.info(`获取 ${this.entry.id} 的祖先文档,level: ${level}`);
|
40
|
+
}
|
41
|
+
|
42
|
+
if (level >= this.getLevel()) {
|
43
|
+
if (debug) {
|
44
|
+
logger.info(`祖先文档为自身`);
|
45
|
+
}
|
46
|
+
return this;
|
47
|
+
}
|
48
|
+
|
49
|
+
const id = this.getAncestorId(level);
|
24
50
|
const doc = await courseDB.find(id);
|
25
51
|
return doc;
|
26
52
|
}
|
27
53
|
|
54
|
+
/**
|
55
|
+
* 获取子文档
|
56
|
+
* @returns 子文档列表
|
57
|
+
*/
|
28
58
|
async getChildren(): Promise<CourseDoc[]> {
|
29
|
-
|
59
|
+
const debug = false;
|
60
|
+
const children = (await courseDB.getChildren(this.entry.id)).sort(
|
61
|
+
(a, b) => a.getOrder() - b.getOrder()
|
62
|
+
);
|
63
|
+
if (debug && children.length > 0) {
|
64
|
+
logger.array(
|
65
|
+
`${this.entry.id} 的子文档(${children.length})`,
|
66
|
+
children.map((child) => `#${child.getOrder()} ${child.entry.id}`)
|
67
|
+
);
|
68
|
+
}
|
69
|
+
return children;
|
30
70
|
}
|
31
71
|
|
32
72
|
override async toSidebarItem(): Promise<SidebarItemEntity> {
|
@@ -2,15 +2,12 @@ import type { ExperimentEntry } from '../database/ExperimentDB';
|
|
2
2
|
import experimentDB from '../database/ExperimentDB';
|
3
3
|
import { logger } from '../utils/logger';
|
4
4
|
import { SidebarItemEntity } from './SidebarItem';
|
5
|
-
import type { Heading } from './Heading';
|
6
5
|
import { LinkUtil } from '../utils/link';
|
7
|
-
import {
|
8
|
-
import {
|
6
|
+
import { COLLECTION_EXPERIMENT } from '../database/ExperimentDB';
|
7
|
+
import { BaseDoc } from './BaseDoc';
|
8
|
+
import type { IHeadingType } from '../types/heading';
|
9
9
|
|
10
|
-
export default class ExperimentDoc extends
|
11
|
-
typeof COLLECTION_NAME,
|
12
|
-
ExperimentEntry
|
13
|
-
> {
|
10
|
+
export default class ExperimentDoc extends BaseDoc<typeof COLLECTION_EXPERIMENT, ExperimentEntry> {
|
14
11
|
constructor(entry: ExperimentEntry) {
|
15
12
|
super(entry);
|
16
13
|
}
|
@@ -70,14 +67,14 @@ export default class ExperimentDoc extends HierarchicalDoc<
|
|
70
67
|
return this.entry.rendered?.html || '';
|
71
68
|
}
|
72
69
|
|
73
|
-
getHeadings():
|
70
|
+
getHeadings(): IHeadingType[] {
|
74
71
|
const debug = false;
|
75
72
|
|
76
73
|
if (debug) {
|
77
74
|
logger.info(`获取 ${this.entry.id} 的 headings`);
|
78
75
|
}
|
79
76
|
|
80
|
-
return (this.entry.rendered?.metadata?.headings as
|
77
|
+
return (this.entry.rendered?.metadata?.headings as IHeadingType[]) || [];
|
81
78
|
}
|
82
79
|
|
83
80
|
async getTopDoc(): Promise<ExperimentDoc | null> {
|
@@ -2,12 +2,12 @@ import type { LessonEntry } from '../database/LessonDB';
|
|
2
2
|
import lessonDB from '../database/LessonDB';
|
3
3
|
import { logger } from '../utils/logger';
|
4
4
|
import { SidebarItemEntity } from './SidebarItem';
|
5
|
-
import type { Heading } from './Heading';
|
6
5
|
import { LinkUtil } from '../utils/link';
|
7
|
-
import {
|
8
|
-
import {
|
6
|
+
import { COLLECTION_LESSON } from '../database/LessonDB';
|
7
|
+
import { BaseDoc } from './BaseDoc';
|
8
|
+
import type { IHeadingType } from '../types/heading';
|
9
9
|
|
10
|
-
export default class LessonDoc extends
|
10
|
+
export default class LessonDoc extends BaseDoc<typeof COLLECTION_LESSON, LessonEntry> {
|
11
11
|
constructor(entry: LessonEntry) {
|
12
12
|
super(entry);
|
13
13
|
}
|
@@ -67,14 +67,14 @@ export default class LessonDoc extends HierarchicalDoc<typeof COLLECTION_NAME, L
|
|
67
67
|
return this.entry.rendered?.html || '';
|
68
68
|
}
|
69
69
|
|
70
|
-
getHeadings():
|
70
|
+
getHeadings(): IHeadingType[] {
|
71
71
|
const debug = false;
|
72
72
|
|
73
73
|
if (debug) {
|
74
74
|
logger.info(`获取 ${this.entry.id} 的 headings`);
|
75
75
|
}
|
76
76
|
|
77
|
-
return (this.entry.rendered?.metadata?.headings as
|
77
|
+
return (this.entry.rendered?.metadata?.headings as IHeadingType[]) || [];
|
78
78
|
}
|
79
79
|
|
80
80
|
async getTopDoc(): Promise<LessonDoc | null> {
|
package/dist/entities/MetaDoc.ts
CHANGED
@@ -3,9 +3,9 @@ import type { MetaEntry } from '../database/MetaDB';
|
|
3
3
|
import { LinkUtil } from '../utils/link';
|
4
4
|
import { BaseDoc } from './BaseDoc';
|
5
5
|
import metaDB from '../database/MetaDB';
|
6
|
-
import {
|
6
|
+
import { COLLECTION_META } from '../database/MetaDB';
|
7
7
|
|
8
|
-
export default class MetaDoc extends BaseDoc<typeof
|
8
|
+
export default class MetaDoc extends BaseDoc<typeof COLLECTION_META, MetaEntry> {
|
9
9
|
constructor(entry: MetaEntry) {
|
10
10
|
super(entry);
|
11
11
|
}
|
package/dist/index.ts
CHANGED
@@ -7,14 +7,6 @@ export { default as Alert } from './components/base/Alert.astro';
|
|
7
7
|
export { default as Speak } from './components/base/Speak.astro';
|
8
8
|
export { default as Module } from './components/base/Module.astro';
|
9
9
|
|
10
|
-
// Collections
|
11
|
-
export * from './collections/ArticleCollection';
|
12
|
-
export * from './collections/BlogCollection';
|
13
|
-
export * from './collections/CourseCollection';
|
14
|
-
export * from './collections/ExperimentCollection';
|
15
|
-
export * from './collections/LessonCollection';
|
16
|
-
export * from './collections/MetaCollection';
|
17
|
-
|
18
10
|
// Navigation
|
19
11
|
export { default as ThemeSwitcher } from './components/navigation/ThemeSwitcher.astro';
|
20
12
|
export { default as TableOfContents } from './components/navigation/TableOfContents.astro';
|
@@ -110,7 +102,6 @@ export * from './entities/BaseDoc';
|
|
110
102
|
export * from './entities/BlogDoc';
|
111
103
|
export * from './entities/CourseDoc';
|
112
104
|
export * from './entities/ExperimentDoc';
|
113
|
-
export * from './entities/Heading';
|
114
105
|
export * from './entities/LessonDoc';
|
115
106
|
export * from './entities/MetaDoc';
|
116
107
|
export * from './entities/SidebarItem';
|
@@ -118,3 +109,8 @@ export * from './entities/Tag';
|
|
118
109
|
|
119
110
|
// Database
|
120
111
|
export * from './database/BaseDB';
|
112
|
+
export * from './database/BlogDB';
|
113
|
+
export * from './database/CourseDB';
|
114
|
+
export * from './database/ExperimentDB';
|
115
|
+
export * from './database/LessonDB';
|
116
|
+
export * from './database/MetaDB';
|
package/dist/utils/link.ts
CHANGED
@@ -93,7 +93,7 @@ export class LinkUtil {
|
|
93
93
|
logger.info(`获取课程文档链接,课程文档ID: ${courseId}`);
|
94
94
|
}
|
95
95
|
|
96
|
-
return `/${lang}/courses/${courseIdWithoutLang}
|
96
|
+
return LinkUtil.createUrl(`/${lang}/courses/${courseIdWithoutLang}`);
|
97
97
|
}
|
98
98
|
|
99
99
|
static getMetaLink(lang: string, slug: string): string {
|