coursecode 0.1.55 → 0.1.57
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/README.md +1 -1
- package/bin/cli.js +1 -1
- package/framework/docs/COURSE_AUTHORING_GUIDE.md +1 -1
- package/framework/version.json +1 -1
- package/lib/build-packaging.js +2 -2
- package/lib/create.js +57 -3
- package/package.json +2 -2
- package/template/package.json +1 -1
package/README.md
CHANGED
|
@@ -235,7 +235,7 @@ coursecode preview --export
|
|
|
235
235
|
|
|
236
236
|
| Command | Description |
|
|
237
237
|
|---------|-------------|
|
|
238
|
-
| `coursecode create <name>` | Create a new course project;
|
|
238
|
+
| `coursecode create <name>` | Create a new course project; `create .` derives a title-cased course title and hyphenated npm name from the current folder |
|
|
239
239
|
| `coursecode init [name]` | Initialize the current directory, optionally with a course title |
|
|
240
240
|
| `coursecode preview` | Preview your course locally |
|
|
241
241
|
| `coursecode convert` | Convert PDFs, Word, PowerPoint to markdown |
|
package/bin/cli.js
CHANGED
|
@@ -97,7 +97,7 @@ program
|
|
|
97
97
|
.option('--start', 'Auto-start dev server after creation (skip prompt)')
|
|
98
98
|
.action(async (name, options) => {
|
|
99
99
|
const { create } = await import('../lib/create.js');
|
|
100
|
-
await create(name ||
|
|
100
|
+
await create(name || '.', { ...options, currentDirectory: true });
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
// Dev command
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|---------|-------------|
|
|
17
17
|
| `coursecode create <name>` | Create a new course project (includes example slides) |
|
|
18
18
|
| `coursecode create <name> --blank` | Create a blank project (no example content) |
|
|
19
|
-
| `coursecode create .` | Initialize the current directory
|
|
19
|
+
| `coursecode create .` | Initialize the current directory; `client-manager-course` becomes title `Client Manager Course` and package name `client-manager-course` |
|
|
20
20
|
| `coursecode init [name]` | Initialize the current directory, optionally with a specific course title |
|
|
21
21
|
| `coursecode clean` | Remove example files and reset config to minimal starter |
|
|
22
22
|
| `coursecode new slide <id>` | Create a new slide file in `course/slides/` |
|
package/framework/version.json
CHANGED
package/lib/build-packaging.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import fs from 'fs';
|
|
11
11
|
import path from 'path';
|
|
12
|
-
import
|
|
12
|
+
import { ZipArchive } from 'archiver';
|
|
13
13
|
import { fileURLToPath } from 'url';
|
|
14
14
|
import { generateManifest } from './manifest/manifest-factory.js';
|
|
15
15
|
|
|
@@ -35,7 +35,7 @@ function withClientCredentials(externalUrl, clientId, token) {
|
|
|
35
35
|
function zipDirectory(sourceDir, zipFilePath) {
|
|
36
36
|
return new Promise((resolve, reject) => {
|
|
37
37
|
const output = fs.createWriteStream(zipFilePath);
|
|
38
|
-
const archive =
|
|
38
|
+
const archive = new ZipArchive({ zlib: { level: 9 } });
|
|
39
39
|
|
|
40
40
|
output.on('close', () => resolve(archive.pointer()));
|
|
41
41
|
archive.on('error', reject);
|
package/lib/create.js
CHANGED
|
@@ -9,6 +9,16 @@ import { spawn } from 'child_process';
|
|
|
9
9
|
|
|
10
10
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
11
|
const PACKAGE_ROOT = path.join(__dirname, '..');
|
|
12
|
+
const REQUIRED_PROJECT_DIRECTORIES = [
|
|
13
|
+
{
|
|
14
|
+
path: path.join('course', 'references'),
|
|
15
|
+
placeholder: '# Place source documents here (docx, pptx, pdf)\n# Run `coursecode convert` to convert them to markdown\n'
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
path: path.join('course', 'references', 'converted'),
|
|
19
|
+
placeholder: '# Converted markdown files will be placed here\n# These can be used as source material for AI-assisted course creation\n'
|
|
20
|
+
}
|
|
21
|
+
];
|
|
12
22
|
|
|
13
23
|
export function toProjectDirectoryName(name) {
|
|
14
24
|
return String(name || '')
|
|
@@ -21,6 +31,32 @@ export function toProjectDirectoryName(name) {
|
|
|
21
31
|
.replace(/^_+|_+$/g, '');
|
|
22
32
|
}
|
|
23
33
|
|
|
34
|
+
function directoryNameWords(name) {
|
|
35
|
+
return String(name || '')
|
|
36
|
+
.trim()
|
|
37
|
+
.normalize('NFKD')
|
|
38
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
39
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
40
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
|
|
41
|
+
.replace(/['’]/g, '')
|
|
42
|
+
.replace(/[^a-zA-Z0-9]+/g, ' ')
|
|
43
|
+
.trim()
|
|
44
|
+
.split(/\s+/)
|
|
45
|
+
.filter(Boolean);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function toCurrentDirectoryCourseTitle(name) {
|
|
49
|
+
return directoryNameWords(name)
|
|
50
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
51
|
+
.join(' ');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function toCurrentDirectoryPackageName(name) {
|
|
55
|
+
return directoryNameWords(name)
|
|
56
|
+
.map(word => word.toLowerCase())
|
|
57
|
+
.join('-');
|
|
58
|
+
}
|
|
59
|
+
|
|
24
60
|
function escapeSingleQuotedValue(value) {
|
|
25
61
|
return String(value).replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
26
62
|
}
|
|
@@ -77,6 +113,18 @@ function copyDir(src, dest, options = {}) {
|
|
|
77
113
|
}
|
|
78
114
|
}
|
|
79
115
|
|
|
116
|
+
function ensureRequiredProjectDirectories(projectDir) {
|
|
117
|
+
for (const directory of REQUIRED_PROJECT_DIRECTORIES) {
|
|
118
|
+
const directoryPath = path.join(projectDir, directory.path);
|
|
119
|
+
const placeholderPath = path.join(directoryPath, '.gitkeep');
|
|
120
|
+
fs.mkdirSync(directoryPath, { recursive: true });
|
|
121
|
+
|
|
122
|
+
if (!fs.existsSync(placeholderPath)) {
|
|
123
|
+
fs.writeFileSync(placeholderPath, directory.placeholder, 'utf-8');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
80
128
|
function mergeProjectControlFile(sourcePath, destinationPath) {
|
|
81
129
|
const source = fs.readFileSync(sourcePath, 'utf-8').trimEnd();
|
|
82
130
|
if (!fs.existsSync(destinationPath)) {
|
|
@@ -161,9 +209,14 @@ function gitInit(cwd) {
|
|
|
161
209
|
export async function create(name, options = {}) {
|
|
162
210
|
const requestedName = String(name || '').trim();
|
|
163
211
|
const currentDirectory = options.currentDirectory === true || requestedName === '.';
|
|
164
|
-
const
|
|
165
|
-
const
|
|
166
|
-
const
|
|
212
|
+
const inferFromCurrentDirectory = currentDirectory && requestedName === '.';
|
|
213
|
+
const currentDirectoryName = path.basename(process.cwd());
|
|
214
|
+
const displayName = inferFromCurrentDirectory
|
|
215
|
+
? toCurrentDirectoryCourseTitle(currentDirectoryName)
|
|
216
|
+
: requestedName;
|
|
217
|
+
const directoryName = inferFromCurrentDirectory
|
|
218
|
+
? toCurrentDirectoryPackageName(currentDirectoryName)
|
|
219
|
+
: toProjectDirectoryName(displayName);
|
|
167
220
|
|
|
168
221
|
if (!displayName) {
|
|
169
222
|
console.error('\n❌ Course name is required.\n');
|
|
@@ -200,6 +253,7 @@ export async function create(name, options = {}) {
|
|
|
200
253
|
});
|
|
201
254
|
mergeProjectControlFile(path.join(templateDir, 'gitignore'), path.join(targetDir, '.gitignore'));
|
|
202
255
|
mergeProjectControlFile(path.join(templateDir, 'gitattributes'), path.join(targetDir, '.gitattributes'));
|
|
256
|
+
ensureRequiredProjectDirectories(targetDir);
|
|
203
257
|
|
|
204
258
|
// Copy framework
|
|
205
259
|
const frameworkSrc = path.join(PACKAGE_ROOT, 'framework');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coursecode",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.57",
|
|
4
4
|
"description": "Multi-format course authoring framework with CLI tools (SCORM 2004, SCORM 1.2, cmi5, LTI 1.3)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
"dependencies": {
|
|
105
105
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
106
106
|
"acorn": "^8.17.0",
|
|
107
|
-
"archiver": "^
|
|
107
|
+
"archiver": "^8.0.0",
|
|
108
108
|
"commander": "^14.0.3",
|
|
109
109
|
"lz-string": "^1.5.0",
|
|
110
110
|
"mammoth": "^1.12.0",
|