coursecode 0.1.51 → 0.1.53
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
CHANGED
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
# CourseCode
|
|
2
2
|
|
|
3
|
-
**Open-source, local-first course authoring
|
|
3
|
+
**Open-source, local-first course authoring with no vendor lock-in. Built for AI tools like Claude Code, Codex, Cursor, and [CourseCode Desktop](https://coursecodedesktop.com). No coding required to start, full code control when you need it.**
|
|
4
4
|
|
|
5
|
-
CourseCode creates real project files you can inspect, version, and edit directly
|
|
5
|
+
CourseCode creates real project files you can inspect, version, and edit directly instead of relying on restrictive graphical editing tools. Built-in MCP integration means your AI assistant connects directly to your course project and understands the framework immediately.
|
|
6
6
|
|
|
7
|
-
Bring your own PDFs, Word docs, or
|
|
7
|
+
Bring your own PDFs, Word docs, or other reference documents, use AI to accelerate authoring, and deploy to any LMS without vendor lock-in or subscriptions.
|
|
8
8
|
|
|
9
9
|
## View the demo
|
|
10
10
|
|
|
11
11
|
- [View the live CourseCode demo course](https://preview.coursecodecloud.com/preview/coursecode-demo/nTfJU2qvp23P0mguxrrGFZr4FlXfM03N)
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## CourseCode ecosystem
|
|
14
14
|
|
|
15
15
|
- [Build SCORM courses with the framework](https://coursecodeframework.com/scorm/)
|
|
16
16
|
- [Use CourseCode Desktop if you prefer a GUI](https://coursecodedesktop.com/scorm/)
|
|
17
17
|
- [Use CourseCode Cloud for hosted delivery](https://coursecodecloud.com)
|
|
18
18
|
|
|
19
|
+
> CourseCode Framework is a standalone tool. Desktop and Cloud are optional.
|
|
20
|
+
|
|
19
21
|
## Features
|
|
20
22
|
|
|
21
23
|
- **MCP integration**: Works with Claude Code, Codex, Cursor, CourseCode Desktop, and any MCP-capable AI tool — previews, screenshots, linting, and testing without manual file sharing
|
|
22
24
|
- **No coding required to start**: Describe what you want and let AI help build slides, interactions, and structure
|
|
25
|
+
- **Course modernization**: Use existing SCORM courses, PowerPoints, PDFs, Word docs, scripts, and SME notes as source material for upgraded courses
|
|
23
26
|
- **Full LMS integration**: SCORM 1.2, SCORM 2004, cmi5, and LTI with complete tracking records
|
|
24
27
|
- **AI-assisted authoring workflow**: Structured guides and MCP tools for faster course development
|
|
25
28
|
- **Rich UI components**: Images, video, accordions, tabs, and custom sandboxed HTML/JS embeds
|
|
@@ -24,9 +24,17 @@
|
|
|
24
24
|
|
|
25
25
|
============================================================================ */
|
|
26
26
|
|
|
27
|
-
/*
|
|
27
|
+
/* Hide shell chrome until course-config-derived layout attributes are applied. */
|
|
28
|
+
html[data-course-loading="true"] .course-header,
|
|
29
|
+
html[data-course-loading="true"] .sidebar,
|
|
30
|
+
html[data-course-loading="true"] .sidebar-backdrop,
|
|
31
|
+
html[data-course-loading="true"] .app-footer {
|
|
32
|
+
display: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Loading indicator - overlay that covers the full shell during startup */
|
|
28
36
|
#loading {
|
|
29
|
-
position:
|
|
37
|
+
position: fixed;
|
|
30
38
|
top: 0;
|
|
31
39
|
left: 0;
|
|
32
40
|
right: 0;
|
|
@@ -42,7 +50,7 @@
|
|
|
42
50
|
radial-gradient(circle at 20% 50%, var(--color-secondary-alpha-05) 0%, transparent 50%),
|
|
43
51
|
radial-gradient(circle at 80% 80%, var(--color-primary-alpha-10) 0%, transparent 50%);
|
|
44
52
|
color: var(--text-muted);
|
|
45
|
-
z-index:
|
|
53
|
+
z-index: var(--z-overlay);
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
/* Loading text styling */
|
package/framework/index.html
CHANGED
|
@@ -174,6 +174,7 @@ export function initAppUI() {
|
|
|
174
174
|
* Hides the loading indicator after the course has finished initializing.
|
|
175
175
|
*/
|
|
176
176
|
export function hideLoadingIndicator() {
|
|
177
|
+
document.documentElement.removeAttribute('data-course-loading');
|
|
177
178
|
if (loadingIndicator) {
|
|
178
179
|
loadingIndicator.style.display = 'none';
|
|
179
180
|
AppState.setLoadingVisible(false);
|
|
@@ -613,4 +614,4 @@ function _lockApplicationForExit() {
|
|
|
613
614
|
closeSidebar();
|
|
614
615
|
hideModal(); // Hide any active modal
|
|
615
616
|
showModal('postExit'); // Show the final "safe to close" modal
|
|
616
|
-
}
|
|
617
|
+
}
|
package/framework/js/main.js
CHANGED
|
@@ -219,6 +219,8 @@ window.addEventListener('click', (event) => {
|
|
|
219
219
|
});
|
|
220
220
|
|
|
221
221
|
function reportInitializationError(error) {
|
|
222
|
+
document.documentElement.removeAttribute('data-course-loading');
|
|
223
|
+
|
|
222
224
|
// Store error in AppState if initialized (defensive - AppState might not be initialized yet)
|
|
223
225
|
try {
|
|
224
226
|
if (AppState.isInitialized()) {
|
|
@@ -346,10 +348,8 @@ function applyThemeVariants() {
|
|
|
346
348
|
// Apply course layout from config (before theme variants)
|
|
347
349
|
// Layouts: 'article' (default), 'traditional', 'focused', 'presentation', 'canvas'
|
|
348
350
|
const layout = courseConfig.layout || 'article';
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
logger.debug(`[Layout] Applied data-layout="${layout}" from course config`);
|
|
352
|
-
}
|
|
351
|
+
html.setAttribute('data-layout', layout);
|
|
352
|
+
logger.debug(`[Layout] Applied data-layout="${layout}" from course config`);
|
|
353
353
|
|
|
354
354
|
// Apply sidebar enabled state from config
|
|
355
355
|
// For 'traditional' layout, sidebar is always enabled
|
|
@@ -429,6 +429,7 @@ async function initializeCourseApplication() {
|
|
|
429
429
|
const accessResult = validateAccess();
|
|
430
430
|
if (!accessResult.valid) {
|
|
431
431
|
logger.warn('[AccessControl] Access denied:', accessResult.error);
|
|
432
|
+
document.documentElement.removeAttribute('data-course-loading');
|
|
432
433
|
showUnauthorizedScreen(accessResult.error);
|
|
433
434
|
return; // Halt initialization
|
|
434
435
|
}
|
|
@@ -203,12 +203,29 @@ function resolveSlideId(contentWindow, slideIdOrIndex) {
|
|
|
203
203
|
// =============================================================================
|
|
204
204
|
|
|
205
205
|
function doReset() {
|
|
206
|
-
// Static/cloud export:
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
206
|
+
// Static/cloud export: unload the AU first so unload/terminate cannot recreate stale LMS state.
|
|
207
|
+
const frame = document.getElementById('stub-player-course-frame');
|
|
208
|
+
let resetStarted = false;
|
|
209
|
+
|
|
210
|
+
const finishReset = () => {
|
|
211
|
+
if (resetStarted) return;
|
|
212
|
+
resetStarted = true;
|
|
213
|
+
|
|
214
|
+
const storageKey = config.storageKey;
|
|
215
|
+
if (storageKey) {
|
|
216
|
+
try { localStorage.removeItem(storageKey); } catch { /* ignore */ }
|
|
217
|
+
}
|
|
218
|
+
window.location.reload();
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
if (frame) {
|
|
222
|
+
frame.addEventListener('load', finishReset, { once: true });
|
|
223
|
+
frame.src = 'about:blank';
|
|
224
|
+
setTimeout(finishReset, 250);
|
|
225
|
+
return;
|
|
210
226
|
}
|
|
211
|
-
|
|
227
|
+
|
|
228
|
+
finishReset();
|
|
212
229
|
}
|
|
213
230
|
|
|
214
231
|
function setupOutsideClickListener(contentPanel) {
|