Skip to content

Commit 2965ae9

Browse files
committed
Preview bug fix
1 parent c21308a commit 2965ae9

8 files changed

Lines changed: 68 additions & 16 deletions

File tree

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
# CourseCode
22

3-
**Open-source, local-first course authoring 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.**
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.**
44

5-
CourseCode creates real project files you can inspect, version, and edit directly — with a predictable, file-based workflow instead of a black-box GUI. Built-in MCP integration means your AI assistant connects directly to your course project.
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.
66

7-
Bring your own PDFs, Word docs, or PowerPoints, use AI to accelerate authoring, and deploy to any LMS format without vendor lock-in or subscriptions.
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.
88

99
## View the demo
1010

1111
- [View the live CourseCode demo course](https://preview.coursecodecloud.com/preview/coursecode-demo/nTfJU2qvp23P0mguxrrGFZr4FlXfM03N)
1212

13-
## Explore the ecosystem
13+
## CourseCode ecosystem
1414

1515
- [Build SCORM courses with the framework](https://coursecodeframework.com/scorm/)
1616
- [Use CourseCode Desktop if you prefer a GUI](https://coursecodedesktop.com/scorm/)
1717
- [Use CourseCode Cloud for hosted delivery](https://coursecodecloud.com)
1818

19+
> CourseCode Framework is a standalone tool. Desktop and Cloud are optional.
20+
1921
## Features
2022

2123
- **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

framework/css/components/loading.css

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,17 @@
2424
2525
============================================================================ */
2626

27-
/* Loading indicator - overlay that covers the content area */
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 */
2836
#loading {
29-
position: absolute;
37+
position: fixed;
3038
top: 0;
3139
left: 0;
3240
right: 0;
@@ -42,7 +50,7 @@
4250
radial-gradient(circle at 20% 50%, var(--color-secondary-alpha-05) 0%, transparent 50%),
4351
radial-gradient(circle at 80% 80%, var(--color-primary-alpha-10) 0%, transparent 50%);
4452
color: var(--text-muted);
45-
z-index: 100;
53+
z-index: var(--z-overlay);
4654
}
4755

4856
/* Loading text styling */

framework/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!DOCTYPE html>
2-
<html lang="en">
2+
<html lang="en" data-course-loading="true">
33

44
<head>
55
<meta charset="UTF-8" />

framework/js/app/AppUI.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ export function initAppUI() {
174174
* Hides the loading indicator after the course has finished initializing.
175175
*/
176176
export function hideLoadingIndicator() {
177+
document.documentElement.removeAttribute('data-course-loading');
177178
if (loadingIndicator) {
178179
loadingIndicator.style.display = 'none';
179180
AppState.setLoadingVisible(false);
@@ -613,4 +614,4 @@ function _lockApplicationForExit() {
613614
closeSidebar();
614615
hideModal(); // Hide any active modal
615616
showModal('postExit'); // Show the final "safe to close" modal
616-
}
617+
}

framework/js/main.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ window.addEventListener('click', (event) => {
219219
});
220220

221221
function reportInitializationError(error) {
222+
document.documentElement.removeAttribute('data-course-loading');
223+
222224
// Store error in AppState if initialized (defensive - AppState might not be initialized yet)
223225
try {
224226
if (AppState.isInitialized()) {
@@ -346,10 +348,8 @@ function applyThemeVariants() {
346348
// Apply course layout from config (before theme variants)
347349
// Layouts: 'article' (default), 'traditional', 'focused', 'presentation', 'canvas'
348350
const layout = courseConfig.layout || 'article';
349-
if (!html.hasAttribute('data-layout')) {
350-
html.setAttribute('data-layout', layout);
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`);
353353

354354
// Apply sidebar enabled state from config
355355
// For 'traditional' layout, sidebar is always enabled
@@ -429,6 +429,7 @@ async function initializeCourseApplication() {
429429
const accessResult = validateAccess();
430430
if (!accessResult.valid) {
431431
logger.warn('[AccessControl] Access denied:', accessResult.error);
432+
document.documentElement.removeAttribute('data-course-loading');
432433
showUnauthorizedScreen(accessResult.error);
433434
return; // Halt initialization
434435
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "coursecode",
3-
"version": "0.1.52",
3+
"version": "0.1.53",
44
"description": "Multi-format course authoring framework with CLI tools (SCORM 2004, SCORM 1.2, cmi5, LTI 1.3)",
55
"type": "module",
66
"bin": {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import fs from 'node:fs';
2+
import path from 'node:path';
3+
import { describe, expect, it } from 'vitest';
4+
5+
const repoRoot = path.resolve(import.meta.dirname, '../..');
6+
7+
describe('loading startup shell', () => {
8+
it('starts behind the loading gate instead of preselecting a visual layout', () => {
9+
const html = fs.readFileSync(path.join(repoRoot, 'framework/index.html'), 'utf8');
10+
11+
expect(html).toContain('<html lang="en" data-course-loading="true">');
12+
expect(html).not.toContain('data-layout="article"');
13+
expect(html).not.toContain('data-sidebar-enabled="false"');
14+
});
15+
16+
it('hides shell chrome and makes loading cover the full shell during startup', () => {
17+
const css = fs.readFileSync(path.join(repoRoot, 'framework/css/components/loading.css'), 'utf8');
18+
19+
expect(css).toContain('html[data-course-loading="true"] .course-header');
20+
expect(css).toContain('html[data-course-loading="true"] .app-footer');
21+
expect(css).toContain('position: fixed;');
22+
expect(css).toContain('z-index: var(--z-overlay);');
23+
});
24+
25+
it('removes the loading gate on every terminal startup path', () => {
26+
const appUi = fs.readFileSync(path.join(repoRoot, 'framework/js/app/AppUI.js'), 'utf8');
27+
const mainJs = fs.readFileSync(path.join(repoRoot, 'framework/js/main.js'), 'utf8');
28+
const removalCount = (mainJs.match(/removeAttribute\('data-course-loading'\)/g) || []).length;
29+
30+
expect(appUi).toContain("document.documentElement.removeAttribute('data-course-loading');");
31+
expect(removalCount).toBeGreaterThanOrEqual(2);
32+
});
33+
34+
it('still applies the course-config layout at runtime', () => {
35+
const mainJs = fs.readFileSync(path.join(repoRoot, 'framework/js/main.js'), 'utf8');
36+
37+
expect(mainJs).toContain("const layout = courseConfig.layout || 'article';");
38+
expect(mainJs).toContain("html.setAttribute('data-layout', layout);");
39+
});
40+
});

0 commit comments

Comments
 (0)