coursecode 0.1.47 → 0.1.48
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/lib/create.js +70 -8
- package/lib/import.js +2 -2
- package/package.json +1 -1
package/lib/create.js
CHANGED
|
@@ -10,6 +10,44 @@ import { spawn } from 'child_process';
|
|
|
10
10
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
11
|
const PACKAGE_ROOT = path.join(__dirname, '..');
|
|
12
12
|
|
|
13
|
+
export function toProjectDirectoryName(name) {
|
|
14
|
+
return String(name || '')
|
|
15
|
+
.trim()
|
|
16
|
+
.normalize('NFKD')
|
|
17
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
18
|
+
.toLowerCase()
|
|
19
|
+
.replace(/['’]/g, '')
|
|
20
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
21
|
+
.replace(/^_+|_+$/g, '');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function escapeSingleQuotedValue(value) {
|
|
25
|
+
return String(value).replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function stampCourseTitle(configContent, title) {
|
|
29
|
+
const titleValue = escapeSingleQuotedValue(title);
|
|
30
|
+
let nextContent = configContent.replace(
|
|
31
|
+
/^(\s*)title\s*:\s*['"`][^'"`]*['"`](\s*,?)/m,
|
|
32
|
+
`$1title: '${titleValue}'$2`
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
nextContent = nextContent.replace(
|
|
36
|
+
/^(\s*)courseTitle\s*:\s*['"`][^'"`]*['"`](\s*,?)/m,
|
|
37
|
+
`$1courseTitle: '${titleValue}'$2`
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return nextContent;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function writeCourseTitle(projectDir, title) {
|
|
44
|
+
const configPath = path.join(projectDir, 'course', 'course-config.js');
|
|
45
|
+
if (!fs.existsSync(configPath)) return;
|
|
46
|
+
|
|
47
|
+
const current = fs.readFileSync(configPath, 'utf-8');
|
|
48
|
+
fs.writeFileSync(configPath, stampCourseTitle(current, title), 'utf-8');
|
|
49
|
+
}
|
|
50
|
+
|
|
13
51
|
/**
|
|
14
52
|
* Copy directory recursively
|
|
15
53
|
*/
|
|
@@ -85,15 +123,31 @@ function gitInit(cwd) {
|
|
|
85
123
|
}
|
|
86
124
|
|
|
87
125
|
export async function create(name, options = {}) {
|
|
88
|
-
const
|
|
126
|
+
const displayName = String(name || '').trim();
|
|
127
|
+
const directoryName = toProjectDirectoryName(displayName);
|
|
128
|
+
|
|
129
|
+
if (!displayName) {
|
|
130
|
+
console.error('\n❌ Course name is required.\n');
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!directoryName) {
|
|
135
|
+
console.error('\n❌ Course name must include letters or numbers.\n');
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const targetDir = path.resolve(process.cwd(), directoryName);
|
|
89
140
|
|
|
90
141
|
// Check if directory already exists
|
|
91
142
|
if (fs.existsSync(targetDir)) {
|
|
92
|
-
console.error(`\n❌ Directory "${
|
|
143
|
+
console.error(`\n❌ Directory "${directoryName}" already exists.\n`);
|
|
93
144
|
process.exit(1);
|
|
94
145
|
}
|
|
95
146
|
|
|
96
|
-
console.log(`\n🚀 Creating CourseCode project: ${
|
|
147
|
+
console.log(`\n🚀 Creating CourseCode project: ${displayName}\n`);
|
|
148
|
+
if (directoryName !== displayName) {
|
|
149
|
+
console.log(` Project folder: ${directoryName}`);
|
|
150
|
+
}
|
|
97
151
|
|
|
98
152
|
// Create project directory
|
|
99
153
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
@@ -138,7 +192,7 @@ export async function create(name, options = {}) {
|
|
|
138
192
|
// Read and customize package.json
|
|
139
193
|
const pkgPath = path.join(targetDir, 'package.json');
|
|
140
194
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
141
|
-
pkg.name =
|
|
195
|
+
pkg.name = directoryName;
|
|
142
196
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
143
197
|
|
|
144
198
|
// Create .coursecoderc.json to track framework version
|
|
@@ -161,6 +215,8 @@ export async function create(name, options = {}) {
|
|
|
161
215
|
clean({ basePath: targetDir });
|
|
162
216
|
}
|
|
163
217
|
|
|
218
|
+
writeCourseTitle(targetDir, displayName);
|
|
219
|
+
|
|
164
220
|
// Install dependencies
|
|
165
221
|
if (options.install !== false) {
|
|
166
222
|
console.log('\n Installing dependencies...\n');
|
|
@@ -184,7 +240,7 @@ export async function create(name, options = {}) {
|
|
|
184
240
|
// Print success message
|
|
185
241
|
if (options.blank) {
|
|
186
242
|
console.log(`
|
|
187
|
-
✅ CourseCode project "${
|
|
243
|
+
✅ CourseCode project "${displayName}" created (blank starter)!
|
|
188
244
|
|
|
189
245
|
Course files:
|
|
190
246
|
- course/course-config.js - Course metadata & structure (minimal)
|
|
@@ -199,7 +255,7 @@ export async function create(name, options = {}) {
|
|
|
199
255
|
`);
|
|
200
256
|
} else {
|
|
201
257
|
console.log(`
|
|
202
|
-
✅ CourseCode project "${
|
|
258
|
+
✅ CourseCode project "${displayName}" created successfully!
|
|
203
259
|
|
|
204
260
|
Course files:
|
|
205
261
|
- course/course-config.js - Course metadata & structure
|
|
@@ -228,9 +284,15 @@ export async function create(name, options = {}) {
|
|
|
228
284
|
|
|
229
285
|
child.on('error', () => {
|
|
230
286
|
console.warn(' ⚠️ Failed to start dev server. Run manually:');
|
|
231
|
-
console.log(` cd ${
|
|
287
|
+
console.log(` cd ${directoryName} && coursecode dev\n`);
|
|
232
288
|
});
|
|
233
289
|
} else {
|
|
234
|
-
console.log(`\n To start developing:\n\n cd ${
|
|
290
|
+
console.log(`\n To start developing:\n\n cd ${directoryName}\n coursecode dev\n`);
|
|
235
291
|
}
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
displayName,
|
|
295
|
+
directoryName,
|
|
296
|
+
targetDir
|
|
297
|
+
};
|
|
236
298
|
}
|
package/lib/import.js
CHANGED
|
@@ -179,9 +179,9 @@ export async function importPresentation(source, options = {}) {
|
|
|
179
179
|
|
|
180
180
|
// Create blank project (no example slides — they'd just be deleted)
|
|
181
181
|
console.log(' ⏳ Creating course project...\n');
|
|
182
|
-
await create(name, { blank: true, install: options.install });
|
|
182
|
+
const createdProject = await create(name, { blank: true, install: options.install });
|
|
183
183
|
|
|
184
|
-
const targetDir = path.resolve(process.cwd(), name);
|
|
184
|
+
const targetDir = createdProject?.targetDir || path.resolve(process.cwd(), name);
|
|
185
185
|
const courseDir = path.join(targetDir, 'course');
|
|
186
186
|
|
|
187
187
|
// Import presentation in-place
|