Skip to content

Commit 9289434

Browse files
authored
Merge pull request #70 from ubc/feat/h5p-review
fix problem bug
2 parents 4df05f3 + a55bea0 commit 9289434

1 file changed

Lines changed: 130 additions & 9 deletions

File tree

routes/create/controllers/h5pPreviewController.js

Lines changed: 130 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,16 @@ router.get('/libs/*', (req, res) => {
9494

9595
// Security: prevent directory traversal
9696
if (requestedPath.includes('..')) {
97+
console.log('[H5P-LIBS] BLOCKED traversal attempt:', requestedPath);
9798
return res.status(400).send('Invalid path');
9899
}
99100

100101
const filePath = path.join(H5P_LIBS_DIR, requestedPath);
102+
console.log('[H5P-LIBS] Serving:', requestedPath, '->', filePath);
103+
101104
res.sendFile(filePath, (err) => {
102105
if (err) {
106+
console.error('[H5P-LIBS] NOT FOUND:', filePath, err.message);
103107
res.status(404).send('Library file not found');
104108
}
105109
});
@@ -189,6 +193,17 @@ body { margin:0; padding:40px; font-family:-apple-system,BlinkMacSystemFont,"Seg
189193
// Read directly from h5p-libs (no temp dir or symlinks needed).
190194
const { cssFiles, jsFiles } = await resolveLibraryDependencies(syntheticH5pJson);
191195

196+
// Build server-side diagnostic info to embed in HTML (user has no backend access)
197+
const serverDiag = {
198+
quizId,
199+
questionTypes: [...questionTypes],
200+
dependencies: preloadedDependencies.map(d => `${d.machineName}-${d.majorVersion}.${d.minorVersion}`),
201+
resolvedJsFiles: jsFiles,
202+
resolvedCssFiles: cssFiles,
203+
h5pLibsDir: H5P_LIBS_DIR,
204+
timestamp: new Date().toISOString()
205+
};
206+
192207
// Serve library files through the existing /api route — works on all environments
193208
// without needing extra nginx/proxy configuration.
194209
const libBasePath = '/api/create/h5p-preview/libs';
@@ -280,12 +295,12 @@ ${questionBlocks.join('\n')}
280295
</div>
281296
282297
<script>
283-
// Track JS errors during library loading (must be before library scripts)
298+
// ===== DIAGNOSTICS: Track all errors during library loading =====
284299
window.__h5pErrors = [];
285300
window.__h5pLoadErrors = [];
286301
window.onerror = function(msg, src, line, col, err) {
287-
window.__h5pErrors.push({msg: msg, src: src, line: line});
288-
console.error('H5P Script Error:', msg, 'in', src, 'line', line);
302+
window.__h5pErrors.push({msg: String(msg), src: String(src), line: line});
303+
console.error('[H5P-DIAG] Script Error:', msg, 'in', src, 'line', line);
289304
};
290305
</script>
291306
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
@@ -297,16 +312,122 @@ ${jsTags}
297312
H5P.$body = jQuery('body');
298313
H5P.$window = jQuery(window);
299314
300-
jQuery(document).ready(function() {
301-
// Log load failures and available constructors for debugging
302-
if (window.__h5pLoadErrors.length > 0) {
303-
console.error('H5P: Failed to load scripts:', window.__h5pLoadErrors);
315+
// ===== SERVER-SIDE INFO (embedded at render time) =====
316+
var __serverDiag = ${JSON.stringify(serverDiag)};
317+
var __libScripts = __serverDiag.resolvedJsFiles;
318+
var __libBasePath = '${libBasePath}';
319+
320+
async function runDiagnostics() {
321+
console.log('%c===== H5P LOADING DIAGNOSTICS =====', 'color: yellow; font-size: 16px; font-weight: bold;');
322+
console.log('Time:', new Date().toISOString());
323+
console.log('Page URL:', window.location.href);
324+
325+
// 1. Server-side info (dependency resolution results from backend)
326+
console.log('%c--- SERVER-SIDE INFO (from backend) ---', 'color: cyan; font-weight: bold;');
327+
console.log('Quiz ID:', __serverDiag.quizId);
328+
console.log('Question types:', __serverDiag.questionTypes);
329+
console.log('h5p-libs dir:', __serverDiag.h5pLibsDir);
330+
console.log('Dependencies resolved:', __serverDiag.dependencies);
331+
console.log('JS files resolved (' + __serverDiag.resolvedJsFiles.length + '):', __serverDiag.resolvedJsFiles);
332+
console.log('CSS files resolved (' + __serverDiag.resolvedCssFiles.length + '):', __serverDiag.resolvedCssFiles);
333+
334+
// 2. Check which H5P constructors are registered after script loading
335+
console.log('%c--- H5P CONSTRUCTOR CHECK ---', 'color: cyan; font-weight: bold;');
336+
var h5pKeys = Object.keys(window.H5P || {}).filter(function(k) {
337+
return typeof H5P[k] === 'function';
338+
});
339+
console.log('Registered constructors (' + h5pKeys.length + '):', h5pKeys);
340+
var criticalLibs = ['DragText', 'Dialogcards', 'MultiChoice', 'TrueFalse', 'Question', 'Column', 'JoubelUI', 'TextUtilities'];
341+
criticalLibs.forEach(function(name) {
342+
var val = H5P[name];
343+
var status = val ? '✅ ' + typeof val : '❌ MISSING';
344+
console.log(' H5P.' + name + ':', status);
345+
});
346+
347+
// 3. Fetch each script URL to check HTTP status and content-type
348+
console.log('%c--- SCRIPT URL FETCH CHECKS ---', 'color: cyan; font-weight: bold;');
349+
350+
// Check h5p-core.js first
351+
try {
352+
var coreResp = await fetch('/api/create/h5p-preview/core/h5p-core.js', { method: 'HEAD' });
353+
console.log('h5p-core.js → Status:', coreResp.status, 'Content-Type:', coreResp.headers.get('content-type'));
354+
} catch(e) {
355+
console.error('h5p-core.js → FETCH ERROR:', e.message);
356+
}
357+
358+
// Check each library script
359+
var problems = [];
360+
for (var i = 0; i < __libScripts.length; i++) {
361+
var scriptUrl = __libBasePath + '/' + __libScripts[i];
362+
try {
363+
var resp = await fetch(scriptUrl);
364+
var ct = resp.headers.get('content-type') || 'unknown';
365+
var status = resp.status;
366+
var bodyText = await resp.text();
367+
var isJS = ct.includes('javascript') || ct.includes('ecmascript');
368+
var isHTML = ct.includes('html') || bodyText.trimStart().startsWith('<!') || bodyText.trimStart().startsWith('<html');
369+
var bodyPreview = bodyText.substring(0, 150).replace(/\\n/g, ' ');
370+
371+
if (status === 200 && isJS && !isHTML) {
372+
console.log('✅', __libScripts[i], '→ Status:', status, 'Type:', ct, 'Size:', bodyText.length, 'bytes');
373+
} else {
374+
console.error('❌', __libScripts[i], '→ Status:', status, 'Type:', ct, 'Size:', bodyText.length, 'IsHTML:', isHTML);
375+
console.error(' Body preview:', bodyPreview);
376+
problems.push({ file: __libScripts[i], status: status, contentType: ct, isHTML: isHTML, preview: bodyPreview });
377+
}
378+
} catch(fetchErr) {
379+
console.error('❌', __libScripts[i], '→ FETCH ERROR:', fetchErr.message);
380+
problems.push({ file: __libScripts[i], error: fetchErr.message });
381+
}
304382
}
305-
if (window.__h5pErrors.length > 0) {
306-
console.error('H5P: JS errors during loading:', window.__h5pErrors);
383+
384+
// 4. Errors collected during loading
385+
console.log('%c--- ERRORS DURING SCRIPT LOADING ---', 'color: cyan; font-weight: bold;');
386+
console.log('window.onerror events:', window.__h5pErrors.length);
387+
window.__h5pErrors.forEach(function(e, i) {
388+
console.error(' Error ' + i + ':', e.msg, '| src:', e.src, '| line:', e.line);
389+
});
390+
console.log('Script onerror events:', window.__h5pLoadErrors.length);
391+
window.__h5pLoadErrors.forEach(function(f, i) {
392+
console.error(' Failed to load:', f);
393+
});
394+
395+
// 5. List all script tags actually in the DOM
396+
console.log('%c--- ALL SCRIPT TAGS IN DOM ---', 'color: cyan; font-weight: bold;');
397+
var allScripts = document.querySelectorAll('script[src]');
398+
console.log('Total script tags:', allScripts.length);
399+
allScripts.forEach(function(s, i) {
400+
console.log(' [' + i + ']', s.src);
401+
});
402+
403+
// 6. Summary
404+
console.log('%c--- SUMMARY ---', 'color: yellow; font-weight: bold; font-size: 14px;');
405+
if (problems.length > 0) {
406+
console.error('🔴 ' + problems.length + ' scripts have problems:');
407+
problems.forEach(function(p) {
408+
if (p.isHTML) {
409+
console.error(' ' + p.file + ' → Server returned HTML instead of JS! This means nginx is NOT routing to Express.');
410+
} else if (p.error) {
411+
console.error(' ' + p.file + ' → Network error: ' + p.error);
412+
} else {
413+
console.error(' ' + p.file + ' → Status: ' + p.status + ', Type: ' + p.contentType);
414+
}
415+
});
416+
} else if (h5pKeys.length === 0) {
417+
console.error('🔴 No H5P constructors registered even though all scripts loaded OK. Possible execution error.');
418+
} else {
419+
console.log('🟢 All ' + __libScripts.length + ' scripts loaded, ' + h5pKeys.length + ' constructors registered.');
307420
}
421+
console.log('%c===== END DIAGNOSTICS =====', 'color: yellow; font-size: 16px; font-weight: bold;');
422+
423+
return problems;
424+
}
308425
426+
jQuery(document).ready(function() {
427+
// Run diagnostics first, then render
428+
runDiagnostics().then(function(problems) {
309429
${runnableCalls.join('\n')}
430+
});
310431
});
311432
</script>
312433
</body>

0 commit comments

Comments
 (0)