feat: expand CSP connect-src directive and add async loading guard for highlight.js in popout view

- Add cdnjs.cloudflare.com, fonts.googleapis.com, and fonts.gstatic.com to connect-src CSP directive
- Add waitForHljs helper function with 50 attempt limit and 100ms polling interval
- Check if hljs is defined before highlighting code blocks in popout view
- Fall back to async waiting if hljs not immediately available to prevent undefined reference errors
This commit is contained in:
Bruno Charest 2026-04-12 17:06:35 -04:00
parent ddb73461da
commit e1fcbe9ce7
2 changed files with 21 additions and 5 deletions

View File

@ -458,7 +458,7 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware):
"script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://unpkg.com https://esm.sh; " "script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://unpkg.com https://esm.sh; "
"style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://fonts.googleapis.com; " "style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://fonts.googleapis.com; "
"img-src 'self' data: blob:; " "img-src 'self' data: blob:; "
"connect-src 'self' https://esm.sh https://unpkg.com; " "connect-src 'self' https://esm.sh https://unpkg.com https://cdnjs.cloudflare.com https://fonts.googleapis.com https://fonts.gstatic.com; "
"font-src 'self' https://fonts.gstatic.com;" "font-src 'self' https://fonts.gstatic.com;"
) )
return response return response

View File

@ -752,10 +752,18 @@ const RightSidebarManager = {
OutlineManager.init(); RightSidebarManager.init(); OutlineManager.init(); RightSidebarManager.init();
// Highlight code blocks // Highlight code blocks (wait for hljs to be available)
if (typeof hljs !== 'undefined') {
document.querySelectorAll('pre code').forEach((el) => { document.querySelectorAll('pre code').forEach((el) => {
hljs.highlightElement(el); hljs.highlightElement(el);
}); });
} else {
waitForHljs().then(() => {
document.querySelectorAll('pre code').forEach((el) => {
hljs.highlightElement(el);
});
});
}
// Hide loading // Hide loading
document.getElementById('loading').style.opacity = '0'; document.getElementById('loading').style.opacity = '0';
@ -768,6 +776,14 @@ const RightSidebarManager = {
} }
} }
async function waitForHljs() {
let attempts = 0;
while (typeof hljs === 'undefined' && attempts < 50) {
await new Promise((resolve) => setTimeout(resolve, 100));
attempts++;
}
}
async function waitForCodeMirror() { async function waitForCodeMirror() {
let attempts = 0; let attempts = 0;
while (!window.CodeMirror && attempts < 50) { while (!window.CodeMirror && attempts < 50) {