@learnmd/cli 0.0.1-beta.0 ā 0.0.2-beta.0
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/commands/add.d.ts +9 -2
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +136 -8
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/create.d.ts +5 -3
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +124 -24
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +19 -4
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/sync.d.ts +6 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +40 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/index.js +27 -7
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
- package/dist/commands/add.test.d.ts +0 -2
- package/dist/commands/add.test.d.ts.map +0 -1
- package/dist/commands/add.test.js +0 -35
- package/dist/commands/add.test.js.map +0 -1
package/dist/commands/add.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
1
|
+
export interface AddOptions {
|
|
2
|
+
course?: string;
|
|
3
|
+
nonInteractive?: boolean;
|
|
4
|
+
difficulty?: string;
|
|
5
|
+
time?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function addCourseCommand(initialName?: string, options?: AddOptions): Promise<void>;
|
|
8
|
+
export declare function addLessonCommand(title: string, options?: AddOptions): Promise<void>;
|
|
9
|
+
export declare function addPageCommand(title: string, options?: AddOptions): Promise<void>;
|
|
3
10
|
//# sourceMappingURL=add.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,iBAoHhF;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,iBAkEzE;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,iBAkCvE"}
|
package/dist/commands/add.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { writeFile, mkdir, readFile } from 'fs/promises';
|
|
3
3
|
import { join } from 'path';
|
|
4
|
+
import { intro, text, select, isCancel, cancel, outro } from '@clack/prompts';
|
|
4
5
|
async function checkIfInLearnMDWorkspace() {
|
|
5
6
|
try {
|
|
6
7
|
const cwd = process.cwd();
|
|
@@ -12,27 +13,123 @@ async function checkIfInLearnMDWorkspace() {
|
|
|
12
13
|
return false;
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
|
-
export async function addCourseCommand(
|
|
16
|
-
|
|
16
|
+
export async function addCourseCommand(initialName, options) {
|
|
17
|
+
const isNonInteractive = options?.nonInteractive;
|
|
18
|
+
if (!isNonInteractive) {
|
|
19
|
+
intro(chalk.bgBlue(' š Add New Course '));
|
|
20
|
+
}
|
|
17
21
|
const isLearnMD = await checkIfInLearnMDWorkspace();
|
|
18
22
|
if (!isLearnMD) {
|
|
19
23
|
console.warn(chalk.yellow('ā ļø Warning: This doesn\'t look like a LearnMD project. Ensure you are running this inside a LearnMD workspace.'));
|
|
20
24
|
}
|
|
25
|
+
let name = initialName;
|
|
26
|
+
if (!name && !isNonInteractive) {
|
|
27
|
+
const nameResult = await text({
|
|
28
|
+
message: 'What is the title of the course?',
|
|
29
|
+
placeholder: 'e.g., JavaScript Basics',
|
|
30
|
+
validate(value) {
|
|
31
|
+
if (!value || value.length === 0)
|
|
32
|
+
return 'Course title is required';
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
if (isCancel(nameResult)) {
|
|
36
|
+
cancel('Operation cancelled.');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
name = nameResult;
|
|
40
|
+
}
|
|
41
|
+
else if (!name && isNonInteractive) {
|
|
42
|
+
name = 'new-course';
|
|
43
|
+
}
|
|
44
|
+
let difficulty = options?.difficulty;
|
|
45
|
+
if (!difficulty && !isNonInteractive) {
|
|
46
|
+
const diffResult = await select({
|
|
47
|
+
message: 'What is the difficulty level?',
|
|
48
|
+
options: [
|
|
49
|
+
{ value: 'beginner', label: 'Beginner' },
|
|
50
|
+
{ value: 'intermediate', label: 'Intermediate' },
|
|
51
|
+
{ value: 'advanced', label: 'Advanced' },
|
|
52
|
+
],
|
|
53
|
+
});
|
|
54
|
+
if (isCancel(diffResult)) {
|
|
55
|
+
cancel('Operation cancelled.');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
difficulty = diffResult;
|
|
59
|
+
}
|
|
60
|
+
else if (!difficulty && isNonInteractive) {
|
|
61
|
+
difficulty = 'beginner';
|
|
62
|
+
}
|
|
63
|
+
let estimatedTime = options?.time;
|
|
64
|
+
if (!estimatedTime && !isNonInteractive) {
|
|
65
|
+
const timeResult = await text({
|
|
66
|
+
message: 'What is the estimated completion time?',
|
|
67
|
+
placeholder: 'e.g., 2 hours',
|
|
68
|
+
defaultValue: '1 hour',
|
|
69
|
+
});
|
|
70
|
+
if (isCancel(timeResult)) {
|
|
71
|
+
cancel('Operation cancelled.');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
estimatedTime = timeResult;
|
|
75
|
+
}
|
|
76
|
+
else if (!estimatedTime && isNonInteractive) {
|
|
77
|
+
estimatedTime = '1 hour';
|
|
78
|
+
}
|
|
21
79
|
const slug = name.toLowerCase().replace(/\s+/g, '-');
|
|
22
80
|
const coursePath = join(process.cwd(), 'courses', slug, 'lessons');
|
|
23
81
|
try {
|
|
24
82
|
await mkdir(coursePath, { recursive: true });
|
|
83
|
+
// Generate course configuration
|
|
84
|
+
const courseConfig = {
|
|
85
|
+
title: {
|
|
86
|
+
en: name,
|
|
87
|
+
es: `${name} (ES)`
|
|
88
|
+
},
|
|
89
|
+
description: {
|
|
90
|
+
en: `An interactive course: ${name}`,
|
|
91
|
+
es: `Un curso interactivo: ${name}`
|
|
92
|
+
},
|
|
93
|
+
version: '1.0.0',
|
|
94
|
+
difficulty: difficulty,
|
|
95
|
+
estimatedTime: estimatedTime,
|
|
96
|
+
lessons: ['introduction']
|
|
97
|
+
};
|
|
98
|
+
const courseDir = join(process.cwd(), 'courses', slug);
|
|
99
|
+
await writeFile(join(courseDir, 'learnmd.json'), JSON.stringify(courseConfig, null, 2));
|
|
100
|
+
// Add an initial overview.mdx
|
|
101
|
+
const overviewContent = `---
|
|
102
|
+
title: Overview
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
# Welcome to ${name}!
|
|
106
|
+
|
|
107
|
+
This is the overview page for your new course. You can add extended descriptions, images, and custom salutations here.
|
|
108
|
+
`;
|
|
109
|
+
await writeFile(join(courseDir, 'overview.mdx'), overviewContent);
|
|
25
110
|
// Add an initial lesson
|
|
26
|
-
await addLessonCommand('Introduction', slug);
|
|
27
|
-
|
|
111
|
+
await addLessonCommand('Introduction', { course: slug, nonInteractive: isNonInteractive });
|
|
112
|
+
if (!isNonInteractive) {
|
|
113
|
+
outro(chalk.green(`ā
Course '${name}' created successfully in courses/${slug}/`));
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
console.log(chalk.green(`ā
Course '${name}' created successfully in courses/${slug}/`));
|
|
117
|
+
}
|
|
28
118
|
}
|
|
29
119
|
catch (error) {
|
|
30
120
|
console.error(chalk.red('ā Failed to create course directory.'));
|
|
31
121
|
console.error(error);
|
|
32
122
|
}
|
|
33
123
|
}
|
|
34
|
-
export async function addLessonCommand(title,
|
|
35
|
-
|
|
124
|
+
export async function addLessonCommand(title, options) {
|
|
125
|
+
const courseSlug = options?.course || 'demo-course';
|
|
126
|
+
const isNonInteractive = options?.nonInteractive;
|
|
127
|
+
if (!isNonInteractive) {
|
|
128
|
+
console.log(chalk.blue(`\nš Adding new lesson: ${title} to ${courseSlug}\n`));
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
console.log(`Adding new lesson: ${title} to ${courseSlug}`);
|
|
132
|
+
}
|
|
36
133
|
const slug = title.toLowerCase().replace(/\s+/g, '-');
|
|
37
134
|
const filePath = join(process.cwd(), 'courses', courseSlug, 'lessons', `${slug}.mdx`);
|
|
38
135
|
const content = `---
|
|
@@ -43,7 +140,6 @@ description:
|
|
|
43
140
|
en: 'Description for ${title}'
|
|
44
141
|
es: 'Descripción para ${title}'
|
|
45
142
|
duration: '10 minutes'
|
|
46
|
-
difficulty: 'beginner'
|
|
47
143
|
---
|
|
48
144
|
|
|
49
145
|
# ${title}
|
|
@@ -83,11 +179,43 @@ difficulty: 'beginner'
|
|
|
83
179
|
try {
|
|
84
180
|
await mkdir(join(process.cwd(), 'courses', courseSlug, 'lessons'), { recursive: true });
|
|
85
181
|
await writeFile(filePath, content);
|
|
86
|
-
console.log(chalk.
|
|
182
|
+
console.log(chalk.gray(` Created lesson: courses/${courseSlug}/lessons/${slug}.mdx`));
|
|
87
183
|
}
|
|
88
184
|
catch (error) {
|
|
89
185
|
console.error(chalk.red('ā Failed to create lesson. Ensure you have permissions.'));
|
|
90
186
|
console.error(error);
|
|
91
187
|
}
|
|
92
188
|
}
|
|
189
|
+
export async function addPageCommand(title, options) {
|
|
190
|
+
const isNonInteractive = options?.nonInteractive;
|
|
191
|
+
const slug = title.toLowerCase().replace(/\s+/g, '-');
|
|
192
|
+
const pathUrl = `/${slug}`;
|
|
193
|
+
if (!isNonInteractive) {
|
|
194
|
+
console.log(chalk.blue(`\nš Adding new custom page: ${title} at ${pathUrl}\n`));
|
|
195
|
+
}
|
|
196
|
+
const filePath = join(process.cwd(), 'pages', `${slug}.mdx`);
|
|
197
|
+
const content = `---
|
|
198
|
+
title: '${title}'
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
# ${title}
|
|
202
|
+
|
|
203
|
+
This is a custom dynamic page. You can add MDX components here.
|
|
204
|
+
`;
|
|
205
|
+
try {
|
|
206
|
+
await mkdir(join(process.cwd(), 'pages'), { recursive: true });
|
|
207
|
+
await writeFile(filePath, content);
|
|
208
|
+
console.log(chalk.gray(` Created page file: pages/${slug}.mdx`));
|
|
209
|
+
console.log(chalk.yellow(` ā ļø Remember to add this page to your learnmd.config.ts:`));
|
|
210
|
+
console.log(chalk.cyan(`
|
|
211
|
+
customPages: [
|
|
212
|
+
{ path: '${pathUrl}', componentPath: 'pages/${slug}.mdx' }
|
|
213
|
+
]
|
|
214
|
+
`));
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
console.error(chalk.red('ā Failed to create page. Ensure you have permissions.'));
|
|
218
|
+
console.error(error);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
93
221
|
//# sourceMappingURL=add.js.map
|
package/dist/commands/add.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE9E,KAAK,UAAU,yBAAyB;IACtC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1B,MAAM,eAAe,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC;QAC3E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACxC,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC,eAAe,CAAC,CAAC;IACjH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAAoB,EAAE,OAAoB;IAC/E,MAAM,gBAAgB,GAAG,OAAO,EAAE,cAAc,CAAC;IAEjD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,yBAAyB,EAAE,CAAC;IACpD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,gHAAgH,CAAC,CAAC,CAAC;IAC/I,CAAC;IAED,IAAI,IAAI,GAAG,WAAW,CAAC;IACvB,IAAI,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC;YAC5B,OAAO,EAAE,kCAAkC;YAC3C,WAAW,EAAE,yBAAyB;YACtC,QAAQ,CAAC,KAAK;gBACZ,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO,0BAA0B,CAAC;YACtE,CAAC;SACF,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,sBAAsB,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,IAAI,GAAG,UAAoB,CAAC;IAC9B,CAAC;SAAM,IAAI,CAAC,IAAI,IAAI,gBAAgB,EAAE,CAAC;QACrC,IAAI,GAAG,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,UAAU,GAAG,OAAO,EAAE,UAAU,CAAC;IACrC,IAAI,CAAC,UAAU,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC;YAC9B,OAAO,EAAE,+BAA+B;YACxC,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;gBACxC,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE;gBAChD,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;aACzC;SACF,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,sBAAsB,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,UAAU,GAAG,UAAoB,CAAC;IACpC,CAAC;SAAM,IAAI,CAAC,UAAU,IAAI,gBAAgB,EAAE,CAAC;QAC3C,UAAU,GAAG,UAAU,CAAC;IAC1B,CAAC;IAED,IAAI,aAAa,GAAG,OAAO,EAAE,IAAI,CAAC;IAClC,IAAI,CAAC,aAAa,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC;YAC5B,OAAO,EAAE,wCAAwC;YACjD,WAAW,EAAE,eAAe;YAC5B,YAAY,EAAE,QAAQ;SACvB,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,sBAAsB,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,aAAa,GAAG,UAAoB,CAAC;IACvC,CAAC;SAAM,IAAI,CAAC,aAAa,IAAI,gBAAgB,EAAE,CAAC;QAC9C,aAAa,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,MAAM,IAAI,GAAI,IAAe,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAEnE,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7C,gCAAgC;QAChC,MAAM,YAAY,GAAG;YACnB,KAAK,EAAE;gBACL,EAAE,EAAE,IAAc;gBAClB,EAAE,EAAE,GAAG,IAAc,OAAO;aAC7B;YACD,WAAW,EAAE;gBACX,EAAE,EAAE,0BAA0B,IAAc,EAAE;gBAC9C,EAAE,EAAE,yBAAyB,IAAc,EAAE;aAC9C;YACD,OAAO,EAAE,OAAO;YAChB,UAAU,EAAE,UAAoB;YAChC,aAAa,EAAE,aAAuB;YACtC,OAAO,EAAE,CAAC,cAAc,CAAC;SAC1B,CAAC;QAEF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;QACvD,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAExF,8BAA8B;QAC9B,MAAM,eAAe,GAAG;;;;eAIb,IAAc;;;CAG5B,CAAC;QACE,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE,eAAe,CAAC,CAAC;QAElE,wBAAwB;QACxB,MAAM,gBAAgB,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAE3F,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,IAAI,qCAAqC,IAAI,GAAG,CAAC,CAAC,CAAC;QACpF,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,IAAI,qCAAqC,IAAI,GAAG,CAAC,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,CAAC;QACjE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAa,EAAE,OAAoB;IACxE,MAAM,UAAU,GAAG,OAAO,EAAE,MAAM,IAAI,aAAa,CAAC;IACpD,MAAM,gBAAgB,GAAG,OAAO,EAAE,cAAc,CAAC;IAEjD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,KAAK,OAAO,UAAU,IAAI,CAAC,CAAC,CAAC;IACjF,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,sBAAsB,KAAK,OAAO,UAAU,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;IAEtF,MAAM,OAAO,GAAG;;SAET,KAAK;SACL,KAAK;;yBAEW,KAAK;0BACJ,KAAK;;;;IAI3B,KAAK;;;iCAGwB,KAAK;;;;;;;;;;;;;QAa9B,IAAI;;;;;;;;;;;;;;;;;CAiBX,CAAC;IAEA,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxF,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,UAAU,YAAY,IAAI,MAAM,CAAC,CAAC,CAAC;IACzF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC,CAAC;QACpF,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAa,EAAE,OAAoB;IACtE,MAAM,gBAAgB,GAAG,OAAO,EAAE,cAAc,CAAC;IACjD,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC;IAE3B,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,KAAK,OAAO,OAAO,IAAI,CAAC,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;IAE7D,MAAM,OAAO,GAAG;UACR,KAAK;;;IAGX,KAAK;;;CAGR,CAAC;IAEA,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,8BAA8B,IAAI,MAAM,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,4DAA4D,CAAC,CAAC,CAAC;QACxF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;;mBAER,OAAO,4BAA4B,IAAI;;KAErD,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
interface CreateOptions {
|
|
2
|
-
template
|
|
3
|
-
language
|
|
2
|
+
template?: string;
|
|
3
|
+
language?: string;
|
|
4
|
+
nonInteractive?: boolean;
|
|
4
5
|
}
|
|
5
|
-
export declare function createCommand(name?: string,
|
|
6
|
+
export declare function createCommand(name?: string, options?: CreateOptions): Promise<void>;
|
|
7
|
+
export declare function getCourseConfig(courseName: string): string;
|
|
6
8
|
export {};
|
|
7
9
|
//# sourceMappingURL=create.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAUA,UAAU,aAAa;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAsB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,iBAqCzE;AAkED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAiB1D"}
|
package/dist/commands/create.js
CHANGED
|
@@ -1,17 +1,39 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { mkdir, writeFile, readFile } from 'fs/promises';
|
|
3
3
|
import { join } from 'path';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import { intro, text, isCancel, cancel, outro } from '@clack/prompts';
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const pkg = require('../../package.json');
|
|
8
|
+
const version = pkg.version;
|
|
9
|
+
export async function createCommand(name, options) {
|
|
10
|
+
const isNonInteractive = options?.nonInteractive;
|
|
11
|
+
if (!isNonInteractive) {
|
|
12
|
+
intro(chalk.bgBlue(' š Create LearnMD Project '));
|
|
13
|
+
}
|
|
14
|
+
let projectName = name;
|
|
15
|
+
if (!projectName && !isNonInteractive) {
|
|
16
|
+
projectName = await askForProjectName();
|
|
17
|
+
}
|
|
18
|
+
else if (!projectName && isNonInteractive) {
|
|
19
|
+
projectName = 'my-course';
|
|
20
|
+
}
|
|
21
|
+
if (!projectName)
|
|
22
|
+
return; // Cancelled
|
|
6
23
|
const isInWorkspace = await checkIfInLearnMDWorkspace();
|
|
7
|
-
console.log(chalk.blue(`\nš Creating LearnMD project: ${projectName}\n`));
|
|
8
24
|
try {
|
|
9
25
|
await mkdir(projectName, { recursive: true });
|
|
10
26
|
await createBasicStructure(projectName);
|
|
11
27
|
await updatePackageJson(projectName, projectName, isInWorkspace);
|
|
12
28
|
await createEssentialFiles(projectName, isInWorkspace);
|
|
13
|
-
|
|
14
|
-
|
|
29
|
+
if (!isNonInteractive) {
|
|
30
|
+
outro(chalk.green('ā
LearnMD project created successfully!'));
|
|
31
|
+
console.log(chalk.blue('Next steps:'));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.log(chalk.green('ā
LearnMD project created successfully!'));
|
|
35
|
+
console.log('Next steps:');
|
|
36
|
+
}
|
|
15
37
|
console.log(` cd ${projectName}`);
|
|
16
38
|
console.log(' pnpm install');
|
|
17
39
|
console.log(' pnpm dev\n');
|
|
@@ -33,21 +55,21 @@ async function checkIfInLearnMDWorkspace() {
|
|
|
33
55
|
}
|
|
34
56
|
}
|
|
35
57
|
async function askForProjectName() {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
default: 'my-course',
|
|
43
|
-
validate: (input) => {
|
|
44
|
-
if (/^[a-z0-9-]+$/.test(input))
|
|
45
|
-
return true;
|
|
58
|
+
const result = await text({
|
|
59
|
+
message: 'What is your project name?',
|
|
60
|
+
defaultValue: 'my-course',
|
|
61
|
+
placeholder: 'my-course',
|
|
62
|
+
validate: (value) => {
|
|
63
|
+
if (!value || !/^[a-z0-9-]+$/.test(value)) {
|
|
46
64
|
return 'Project name must contain only lowercase letters, numbers, and hyphens';
|
|
47
|
-
}
|
|
65
|
+
}
|
|
48
66
|
},
|
|
49
|
-
|
|
50
|
-
|
|
67
|
+
});
|
|
68
|
+
if (isCancel(result)) {
|
|
69
|
+
cancel('Operation cancelled.');
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
51
73
|
}
|
|
52
74
|
async function createBasicStructure(projectPath) {
|
|
53
75
|
const dirs = ['courses/demo-course/lessons', 'public', 'src'];
|
|
@@ -63,8 +85,37 @@ async function createBasicStructure(projectPath) {
|
|
|
63
85
|
await writeFile(join(projectPath, 'tsconfig.node.json'), getTsNodeConfig());
|
|
64
86
|
await writeFile(join(projectPath, 'learnmd.config.ts'), getLearnMdConfig());
|
|
65
87
|
await writeFile(join(projectPath, '.gitignore'), getGitIgnore());
|
|
88
|
+
// Course config for the demo course
|
|
89
|
+
await writeFile(join(projectPath, 'courses/demo-course/learnmd.json'), getCourseConfig('Demo Course'));
|
|
90
|
+
// Overview MDX
|
|
91
|
+
await writeFile(join(projectPath, 'courses/demo-course/overview.mdx'), `---
|
|
92
|
+
title: Demo Course Overview
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
# Welcome to Demo Course!
|
|
96
|
+
|
|
97
|
+
This is the overview page. Configure your course description and welcome message here.
|
|
98
|
+
`);
|
|
66
99
|
await writeFile(join(projectPath, 'courses/demo-course/lessons/.gitkeep'), '');
|
|
67
100
|
}
|
|
101
|
+
export function getCourseConfig(courseName) {
|
|
102
|
+
return JSON.stringify({
|
|
103
|
+
title: {
|
|
104
|
+
en: courseName,
|
|
105
|
+
es: `${courseName} (ES)`,
|
|
106
|
+
},
|
|
107
|
+
description: {
|
|
108
|
+
en: `An interactive course: ${courseName}`,
|
|
109
|
+
es: `Un curso interactivo: ${courseName}`,
|
|
110
|
+
},
|
|
111
|
+
author: '',
|
|
112
|
+
version: '1.0.0',
|
|
113
|
+
difficulty: 'beginner',
|
|
114
|
+
estimatedTime: '1 hour',
|
|
115
|
+
tags: [],
|
|
116
|
+
lessons: [],
|
|
117
|
+
}, null, 2);
|
|
118
|
+
}
|
|
68
119
|
async function createEssentialFiles(projectPath, _isInWorkspace) {
|
|
69
120
|
await writeFile(join(projectPath, '.npmrc'), 'auto-install-peers=true\n');
|
|
70
121
|
}
|
|
@@ -101,10 +152,20 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
|
101
152
|
function getAppTsx() {
|
|
102
153
|
return `/// <reference types="vite/client" />
|
|
103
154
|
import { LearnMDProvider } from '@learnmd/core';
|
|
104
|
-
import { CatalogViewer, CourseViewer, ProfileViewer } from '@learnmd/default-theme';
|
|
155
|
+
import { CatalogViewer, CourseViewer, ProfileViewer, MainLayout, Header, Callout, Quiz, VideoEmbed, Progress, LanguageSwitcher, Paragraph } from '@learnmd/default-theme';
|
|
105
156
|
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
|
157
|
+
import { MDXProvider } from '@mdx-js/react';
|
|
106
158
|
import config from '../learnmd.config';
|
|
107
159
|
|
|
160
|
+
const components = {
|
|
161
|
+
Callout,
|
|
162
|
+
Quiz,
|
|
163
|
+
VideoEmbed,
|
|
164
|
+
Progress,
|
|
165
|
+
LanguageSwitcher,
|
|
166
|
+
Paragraph,
|
|
167
|
+
};
|
|
168
|
+
|
|
108
169
|
// Glob all markdown files dynamically across all courses
|
|
109
170
|
const lessonModules = import.meta.glob('../courses/*/lessons/*.mdx', { eager: true });
|
|
110
171
|
const allLessons = Object.entries(lessonModules).map(([path, mod]) => {
|
|
@@ -119,14 +180,53 @@ const allLessons = Object.entries(lessonModules).map(([path, mod]) => {
|
|
|
119
180
|
};
|
|
120
181
|
});
|
|
121
182
|
|
|
183
|
+
// Load Course Configurations (learnmd.json)
|
|
184
|
+
const courseConfigsRaw = import.meta.glob('../courses/*/learnmd.json', { eager: true });
|
|
185
|
+
const coursesConfig = Object.entries(courseConfigsRaw).reduce((acc, [path, mod]) => {
|
|
186
|
+
const courseSlug = path.split('/')[2];
|
|
187
|
+
acc[courseSlug] = { id: courseSlug, ...(mod as any).default || mod };
|
|
188
|
+
return acc;
|
|
189
|
+
}, {} as Record<string, any>);
|
|
190
|
+
|
|
191
|
+
// Optional: Load Home Page MDX
|
|
192
|
+
const homeModule = import.meta.glob('../home.mdx', { eager: true });
|
|
193
|
+
const HomeComponent = Object.values(homeModule)[0] ? (Object.values(homeModule)[0] as any).default : undefined;
|
|
194
|
+
|
|
195
|
+
// Load Custom Pages dynamically
|
|
196
|
+
const pageModules = import.meta.glob('../pages/*.mdx', { eager: true });
|
|
197
|
+
|
|
122
198
|
function App() {
|
|
123
199
|
return (
|
|
124
200
|
<LearnMDProvider config={config}>
|
|
125
201
|
<BrowserRouter>
|
|
126
202
|
<Routes>
|
|
127
|
-
<Route path="/" element={<CatalogViewer courses={allLessons} />} />
|
|
128
|
-
<Route path="/profile" element={
|
|
129
|
-
|
|
203
|
+
<Route path="/" element={<CatalogViewer courses={allLessons} HomeComponent={HomeComponent} />} />
|
|
204
|
+
<Route path="/profile" element={
|
|
205
|
+
<MainLayout title="Profile">
|
|
206
|
+
<Header title="User Profile" />
|
|
207
|
+
<ProfileViewer />
|
|
208
|
+
</MainLayout>
|
|
209
|
+
} />
|
|
210
|
+
<Route path="/courses/:courseId/*" element={<CourseViewer allLessons={allLessons} coursesConfig={coursesConfig} />} />
|
|
211
|
+
|
|
212
|
+
{config.customPages?.map((page, idx) => {
|
|
213
|
+
// Map standard pages path to dynamic import
|
|
214
|
+
const modKey = \`../\${page.componentPath}\`;
|
|
215
|
+
const mod = pageModules[modKey];
|
|
216
|
+
const Component = mod ? (mod as any).default : () => <div>Page not found</div>;
|
|
217
|
+
return (
|
|
218
|
+
<Route key={idx} path={page.path} element={
|
|
219
|
+
<MainLayout>
|
|
220
|
+
<Header />
|
|
221
|
+
<div className="prose dark:prose-invert max-w-4xl mx-auto py-12 px-6">
|
|
222
|
+
<MDXProvider components={components}>
|
|
223
|
+
<Component />
|
|
224
|
+
</MDXProvider>
|
|
225
|
+
</div>
|
|
226
|
+
</MainLayout>
|
|
227
|
+
} />
|
|
228
|
+
);
|
|
229
|
+
})}
|
|
130
230
|
</Routes>
|
|
131
231
|
</BrowserRouter>
|
|
132
232
|
</LearnMDProvider>
|
|
@@ -260,10 +360,10 @@ async function updatePackageJson(projectPath, name, isInWorkspace) {
|
|
|
260
360
|
'remark-mdx-frontmatter': '^4.0.0',
|
|
261
361
|
typescript: '^5.4.0',
|
|
262
362
|
vite: '^5.1.0',
|
|
263
|
-
'@learnmd/core': isInWorkspace ? 'file:../packages/core' :
|
|
363
|
+
'@learnmd/core': isInWorkspace ? 'file:../packages/core' : `^${version}`,
|
|
264
364
|
'@learnmd/default-theme': isInWorkspace
|
|
265
365
|
? 'file:../packages/default-theme'
|
|
266
|
-
:
|
|
366
|
+
: `^${version}`,
|
|
267
367
|
};
|
|
268
368
|
const packageJson = {
|
|
269
369
|
name: name.toLowerCase().replace(/\s+/g, '-'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAKA,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAcD,wBAAsB,UAAU,CAAC,OAAO,CAAC,EAAE,UAAU,iBA0CpD"}
|
package/dist/commands/dev.js
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { createServer } from 'vite';
|
|
3
3
|
import { resolve } from 'path';
|
|
4
|
+
import { readFile } from 'fs/promises';
|
|
5
|
+
async function checkIfInLearnMDWorkspace() {
|
|
6
|
+
try {
|
|
7
|
+
const cwd = process.cwd();
|
|
8
|
+
const packageJsonPath = resolve(cwd, 'package.json');
|
|
9
|
+
const content = await readFile(packageJsonPath, 'utf-8');
|
|
10
|
+
const pkg = JSON.parse(content);
|
|
11
|
+
return pkg.name === 'learnmd' || pkg.workspaces !== undefined;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
4
17
|
export async function devCommand(options) {
|
|
5
18
|
const port = parseInt(options?.port || '3000', 10);
|
|
6
19
|
const host = options?.host || 'localhost';
|
|
7
20
|
console.log(chalk.blue('\nš Starting LearnMD development server...\n'));
|
|
21
|
+
const isInWorkspace = await checkIfInLearnMDWorkspace();
|
|
8
22
|
try {
|
|
9
23
|
const server = await createServer({
|
|
10
24
|
root: process.cwd(),
|
|
25
|
+
configFile: resolve(process.cwd(), 'vite.config.ts'),
|
|
11
26
|
server: {
|
|
12
27
|
port,
|
|
13
28
|
host,
|
|
@@ -25,10 +40,10 @@ export async function devCommand(options) {
|
|
|
25
40
|
},
|
|
26
41
|
],
|
|
27
42
|
resolve: {
|
|
28
|
-
alias: {
|
|
29
|
-
'@learnmd/core': resolve(process.cwd(), '../
|
|
30
|
-
'@learnmd/default-theme': resolve(process.cwd(), '../
|
|
31
|
-
},
|
|
43
|
+
alias: isInWorkspace ? {
|
|
44
|
+
'@learnmd/core': resolve(process.cwd(), '../core/src'),
|
|
45
|
+
'@learnmd/default-theme': resolve(process.cwd(), '../default-theme/src'),
|
|
46
|
+
} : {},
|
|
32
47
|
},
|
|
33
48
|
});
|
|
34
49
|
await server.listen();
|
package/dist/commands/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAOvC,KAAK,UAAU,yBAAyB;IACtC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1B,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAoB;IACnD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,WAAW,CAAC;IAE1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC,CAAC;IAEzE,MAAM,aAAa,GAAG,MAAM,yBAAyB,EAAE,CAAC;IAExD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;YAChC,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE;YACnB,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC;YACpD,MAAM,EAAE;gBACN,IAAI;gBACJ,IAAI;gBACJ,IAAI,EAAE,IAAI;aACX;YACD,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,aAAa;oBACnB,eAAe,CAAC,MAAM;wBACpB,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;4BACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC;4BACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC;wBACzD,CAAC,CAAC,CAAC;oBACL,CAAC;iBACF;aACF;YACD,OAAO,EAAE;gBACP,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC;oBACrB,eAAe,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC;oBACtD,wBAAwB,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,sBAAsB,CAAC;iBACzE,CAAC,CAAC,CAAC,EAAE;aACP;SACF,CAAC,CAAC;QAEH,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,wCAAwC,CAAC,EAAE,KAAK,CAAC,CAAC;QAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,iBAwC1E"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { readdir, readFile, writeFile } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
export async function syncCommand(courseSlug, options) {
|
|
5
|
+
const isNonInteractive = options?.nonInteractive;
|
|
6
|
+
if (!isNonInteractive) {
|
|
7
|
+
console.log(chalk.blue(`\nš Syncing lessons for course: ${courseSlug}\n`));
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
console.log(`Syncing lessons for course: ${courseSlug}`);
|
|
11
|
+
}
|
|
12
|
+
const courseDir = join(process.cwd(), 'courses', courseSlug);
|
|
13
|
+
const lessonsDir = join(courseDir, 'lessons');
|
|
14
|
+
const configPath = join(courseDir, 'learnmd.json');
|
|
15
|
+
try {
|
|
16
|
+
// Read MDX files
|
|
17
|
+
const files = await readdir(lessonsDir);
|
|
18
|
+
const mdxFiles = files.filter(f => f.endsWith('.mdx'));
|
|
19
|
+
const slugs = mdxFiles.map(f => f.replace(/\.mdx$/, ''));
|
|
20
|
+
// Update learnmd.json
|
|
21
|
+
const configContent = await readFile(configPath, 'utf-8');
|
|
22
|
+
const config = JSON.parse(configContent);
|
|
23
|
+
config.lessons = slugs;
|
|
24
|
+
await writeFile(configPath, JSON.stringify(config, null, 2));
|
|
25
|
+
if (!isNonInteractive) {
|
|
26
|
+
console.log(chalk.green(`ā
Synced ${slugs.length} lessons to ${courseSlug}/learnmd.json`));
|
|
27
|
+
console.log(chalk.gray(` Lessons: ${slugs.join(', ')}`));
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
console.log(`ā
Synced ${slugs.length} lessons to ${courseSlug}/learnmd.json`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
console.error(chalk.red(`ā Failed to sync course ${courseSlug}. Ensure the course directory exists.`));
|
|
35
|
+
if (!isNonInteractive) {
|
|
36
|
+
console.error(error);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB,EAAE,OAAqB;IACzE,MAAM,gBAAgB,GAAG,OAAO,EAAE,cAAc,CAAC;IAEjD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oCAAoC,UAAU,IAAI,CAAC,CAAC,CAAC;IAC9E,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,+BAA+B,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAEnD,IAAI,CAAC;QACH,iBAAiB;QACjB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;QAEzD,sBAAsB;QACtB,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAEzC,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;QAEvB,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAE7D,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,MAAM,eAAe,UAAU,eAAe,CAAC,CAAC,CAAC;YAC3F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,MAAM,eAAe,UAAU,eAAe,CAAC,CAAC;QAChF,CAAC;IAEH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,2BAA2B,UAAU,uCAAuC,CAAC,CAAC,CAAC;QACvG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,11 @@ import { devCommand } from './commands/dev.js';
|
|
|
5
5
|
import { buildCommand } from './commands/build.js';
|
|
6
6
|
import { initCommand } from './commands/init.js';
|
|
7
7
|
import { addCourseCommand, addLessonCommand } from './commands/add.js';
|
|
8
|
-
|
|
8
|
+
import { syncCommand } from './commands/sync.js';
|
|
9
|
+
import { createRequire } from 'module';
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
const pkg = require('../package.json');
|
|
12
|
+
const version = pkg.version;
|
|
9
13
|
program
|
|
10
14
|
.name('learnmd')
|
|
11
15
|
.description('CLI for creating and building LearnMD courses')
|
|
@@ -16,6 +20,7 @@ program
|
|
|
16
20
|
.argument('[name]', 'Project name')
|
|
17
21
|
.option('-t, --template <template>', 'Template to use', 'default')
|
|
18
22
|
.option('-l, --language <language>', 'Default language', 'en')
|
|
23
|
+
.option('-n, --non-interactive', 'Run without interactive prompts')
|
|
19
24
|
.action(createCommand);
|
|
20
25
|
program
|
|
21
26
|
.command('init')
|
|
@@ -35,20 +40,35 @@ program
|
|
|
35
40
|
.action(buildCommand);
|
|
36
41
|
program
|
|
37
42
|
.command('add')
|
|
38
|
-
.description('Add new resources (course or
|
|
39
|
-
.argument('<type>', 'Type of resource (course, lesson)')
|
|
43
|
+
.description('Add new resources (course, lesson, or page)')
|
|
44
|
+
.argument('<type>', 'Type of resource (course, lesson, page)')
|
|
40
45
|
.argument('<name>', 'Name/Title of the resource')
|
|
41
46
|
.option('-c, --course <courseName>', 'Course name to add the lesson to (defaults to demo-course)')
|
|
42
|
-
.
|
|
47
|
+
.option('-n, --non-interactive', 'Run without interactive prompts')
|
|
48
|
+
.option('-d, --difficulty <difficulty>', 'Difficulty level for course')
|
|
49
|
+
.option('-t, --time <time>', 'Estimated completion time for course')
|
|
50
|
+
.action(async (type, name, options) => {
|
|
43
51
|
if (type === 'course') {
|
|
44
|
-
addCourseCommand(name);
|
|
52
|
+
await addCourseCommand(name, options);
|
|
45
53
|
}
|
|
46
54
|
else if (type === 'lesson') {
|
|
47
|
-
addLessonCommand(name, options
|
|
55
|
+
await addLessonCommand(name, options);
|
|
56
|
+
}
|
|
57
|
+
else if (type === 'page') {
|
|
58
|
+
const { addPageCommand } = await import('./commands/add.js');
|
|
59
|
+
await addPageCommand(name, options);
|
|
48
60
|
}
|
|
49
61
|
else {
|
|
50
|
-
console.error('Invalid resource type. Use "course" or "
|
|
62
|
+
console.error('Invalid resource type. Use "course", "lesson", or "page".');
|
|
51
63
|
}
|
|
52
64
|
});
|
|
65
|
+
program
|
|
66
|
+
.command('sync')
|
|
67
|
+
.description('Sync a directory of MDX files to update the learnmd.json lessons array')
|
|
68
|
+
.argument('<course>', 'Course name to sync')
|
|
69
|
+
.option('-n, --non-interactive', 'Run without interactive prompts')
|
|
70
|
+
.action((course, options) => {
|
|
71
|
+
syncCommand(course, options);
|
|
72
|
+
});
|
|
53
73
|
program.parse();
|
|
54
74
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@learnmd/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2-beta.0",
|
|
4
4
|
"description": "CLI for creating and building LearnMD courses",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"module": "./dist/index.js",
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"dependencies": {
|
|
13
|
+
"@clack/prompts": "^1.1.0",
|
|
13
14
|
"chalk": "^5.3.0",
|
|
14
15
|
"commander": "^12.0.0",
|
|
15
16
|
"fs-extra": "^11.2.0",
|
|
@@ -19,18 +20,18 @@
|
|
|
19
20
|
"marked": "^12.0.0",
|
|
20
21
|
"minisearch": "^6.3.0",
|
|
21
22
|
"vite": "^5.1.0",
|
|
22
|
-
"@learnmd/core": "0.0.
|
|
23
|
-
"@learnmd/default-theme": "0.0.
|
|
23
|
+
"@learnmd/core": "0.0.2-beta.0",
|
|
24
|
+
"@learnmd/default-theme": "0.0.2-beta.0"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
27
|
"@types/fs-extra": "^11.0.4",
|
|
27
28
|
"@types/inquirer": "^9.0.7",
|
|
28
29
|
"@types/node": "^20.11.0",
|
|
30
|
+
"@vitest/coverage-v8": "^1.3.0",
|
|
29
31
|
"eslint-plugin-import": "^2.32.0",
|
|
30
32
|
"eslint-plugin-security": "^4.0.0",
|
|
31
33
|
"typescript": "^5.4.0",
|
|
32
|
-
"vitest": "^1.3.0"
|
|
33
|
-
"@vitest/coverage-v8": "^1.3.0"
|
|
34
|
+
"vitest": "^1.3.0"
|
|
34
35
|
},
|
|
35
36
|
"keywords": [
|
|
36
37
|
"learnmd",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"add.test.d.ts","sourceRoot":"","sources":["../../src/commands/add.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { addLessonCommand } from './add';
|
|
3
|
-
import { writeFile, mkdir } from 'fs/promises';
|
|
4
|
-
import { join } from 'path';
|
|
5
|
-
// Mock fs/promises
|
|
6
|
-
vi.mock('fs/promises', () => ({
|
|
7
|
-
writeFile: vi.fn().mockResolvedValue(undefined),
|
|
8
|
-
mkdir: vi.fn().mockResolvedValue(undefined),
|
|
9
|
-
}));
|
|
10
|
-
describe('addLessonCommand', () => {
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
vi.clearAllMocks();
|
|
13
|
-
vi.stubGlobal('console', {
|
|
14
|
-
log: vi.fn(),
|
|
15
|
-
error: vi.fn(),
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
it('should create a lesson file with correct content', async () => {
|
|
19
|
-
const title = 'Test Lesson';
|
|
20
|
-
const slug = 'test-lesson';
|
|
21
|
-
const courseSlug = 'demo-course';
|
|
22
|
-
const expectedPath = join(process.cwd(), 'courses', courseSlug, 'lessons', `${slug}.mdx`);
|
|
23
|
-
await addLessonCommand(title);
|
|
24
|
-
expect(mkdir).toHaveBeenCalledWith(expect.stringContaining(join('courses', courseSlug, 'lessons')), { recursive: true });
|
|
25
|
-
expect(writeFile).toHaveBeenCalledWith(expectedPath, expect.stringContaining('title:'));
|
|
26
|
-
expect(writeFile).toHaveBeenCalledWith(expectedPath, expect.stringContaining(title));
|
|
27
|
-
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('Lesson created'));
|
|
28
|
-
});
|
|
29
|
-
it('should handle errors during creation', async () => {
|
|
30
|
-
vi.mocked(writeFile).mockRejectedValueOnce(new Error('Write failed'));
|
|
31
|
-
await addLessonCommand('Fail Test');
|
|
32
|
-
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Failed to create lesson'));
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
//# sourceMappingURL=add.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"add.test.js","sourceRoot":"","sources":["../../src/commands/add.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,mBAAmB;AACnB,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5B,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;IAC/C,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;CAC5C,CAAC,CAAC,CAAC;AAEJ,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE;YACvB,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;YACZ,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE;SACf,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,KAAK,GAAG,aAAa,CAAC;QAC5B,MAAM,IAAI,GAAG,aAAa,CAAC;QAC3B,MAAM,UAAU,GAAG,aAAa,CAAC;QACjC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;QAE1F,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAE9B,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzH,MAAM,CAAC,SAAS,CAAC,CAAC,oBAAoB,CACpC,YAAY,EACZ,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAClC,CAAC;QACF,MAAM,CAAC,SAAS,CAAC,CAAC,oBAAoB,CACpC,YAAY,EACZ,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAC/B,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;QAEtE,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAEpC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,gBAAgB,CAAC,yBAAyB,CAAC,CAAC,CAAC;IACjG,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|