fix docs toc fallback and remove redundant iifes

This commit is contained in:
Daniel 2026-05-08 23:08:47 +02:00
parent e84f19b5cb
commit 0503a25d0b
10 changed files with 61 additions and 35 deletions

View file

@ -1139,6 +1139,8 @@ textarea.full-input{resize:vertical;}
.docs-reader-body th{background:var(--g50);font-weight:600;}
.docs-reader-body a{color:var(--blue);text-decoration:none;}
.docs-reader-body a:hover{text-decoration:underline;}
.docs-reader-body .docs-anchor-link{color:var(--blue);cursor:pointer;text-decoration:none;}
.docs-reader-body .docs-anchor-link:hover{text-decoration:underline;}
.docs-reader-body hr{border:0;border-top:1px solid var(--g200);margin:1.6em 0;}
@media (max-width:900px){

View file

@ -132,6 +132,26 @@
});
}
function prepareDocLinks(body) {
if (!body) return;
body.querySelectorAll('a[href]').forEach(function (link) {
var href = link.getAttribute('href') || '';
if (href.charAt(0) !== '#' && link.hash) {
try {
var u = new URL(link.href, window.location.href);
if (u.origin !== window.location.origin || u.pathname !== window.location.pathname) return;
href = u.hash;
} catch (_) { return; }
}
if (!href || href.charAt(0) !== '#') return;
link.dataset.docHash = href;
link.removeAttribute('href');
link.setAttribute('role', 'button');
link.setAttribute('tabindex', '0');
link.classList.add('docs-anchor-link');
});
}
function scrollReaderToHash(hash) {
var body = $('docs-reader-body');
var reader = $('docs-reader');
@ -152,25 +172,24 @@
}
function handleDocAnchorClick(e) {
var link = e.target.closest('a[href]');
var link = e.target.closest('[data-doc-hash]');
var body = $('docs-reader-body');
if (!link || !body || !body.contains(link)) return;
var href = link.getAttribute('href') || '';
if (href.charAt(0) !== '#' && link.hash) {
try {
var u = new URL(link.href, window.location.href);
if (u.origin !== window.location.origin || u.pathname !== window.location.pathname) return;
href = u.hash;
} catch (_) { return; }
}
var href = link.dataset.docHash || '';
if (!href || href.charAt(0) !== '#') return;
e.preventDefault();
requestAnimationFrame(function () {
scrollReaderToHash(href);
try { history.replaceState(null, '', href); } catch (_) { window.location.hash = href; }
if (scrollReaderToHash(href)) {
try { history.replaceState(null, '', href); } catch (_) {}
}
});
}
function handleDocAnchorKeydown(e) {
if (e.key !== 'Enter' && e.key !== ' ') return;
handleDocAnchorClick(e);
}
function loadTree() {
if (_treeLoaded) return;
fetch('/api/admin/docs/tree', { headers: getAuthHeaders() })
@ -217,6 +236,7 @@
}
body.innerHTML = data.html || '';
prepareDocAnchors(body);
prepareDocLinks(body);
if (meta) {
meta.textContent = relPath + ' • ' + (data.bytes != null ? (data.bytes + ' bytes') : '');
}
@ -277,6 +297,7 @@
if (body && !body.dataset.anchorsWired) {
body.dataset.anchorsWired = '1';
body.addEventListener('click', handleDocAnchorClick);
body.addEventListener('keydown', handleDocAnchorKeydown);
}
var filter = $('docs-filter');

View file

@ -1,7 +1,7 @@
// E2E harness bootstrap — external file because the app's CSP blocks inline scripts.
// Runs after calc-math.js + calculators.js (all three have `defer`, so execution
// is in document order once parsing completes).
(async function bootstrap() {
async function bootstrapE2eHarness() {
try {
// Cache-bust so stale playwright browser caches never serve an outdated
// component HTML between reorg deploys.
@ -20,4 +20,5 @@
console.error('[e2e-harness] bootstrap failed:', e);
window.__harnessError = String(e);
}
})();
}
bootstrapE2eHarness();

View file

@ -2,7 +2,7 @@
// ENCOUNTERS.JS — Save/resume/pause encounter progress
// ============================================================
(function() {
function setupEncountersModule() {
// ── Pause/Resume for recording buttons ─────────────────────────────────
// Each recording module (encounter, dictation) gets a pause button wired here.
@ -94,14 +94,15 @@
}
// Restore saved encounter IDs from sessionStorage (survive page refresh, cleared on tab close)
(function() {
function restoreSavedEncounterIds() {
['encounter','dictation','ed','hospital','chart','wellvisit','sickvisit','soap'].forEach(function(t) {
try {
var id = sessionStorage.getItem('_savedEncId_' + t);
if (id) window['_savedEncId_' + t] = id;
} catch(e) {}
});
})();
}
restoreSavedEncounterIds();
// Register a load handler for a specific tab type
window.registerEncounterLoadHandler = function(type, fn) {
@ -513,4 +514,5 @@
console.log('✅ Encounters module loaded');
})();
}
setupEncountersModule();

View file

@ -1,8 +1,7 @@
(function() {
var _inited = false;
var _liveEncounterInited = false;
document.addEventListener('tabChanged', function(e) {
if (e.detail.tab !== 'encounter' || _inited) return;
_inited = true;
if (e.detail.tab !== 'encounter' || _liveEncounterInited) return;
_liveEncounterInited = true;
var recordBtn = document.getElementById('enc-record-btn');
var pauseBtn = document.getElementById('enc-pause-btn');
var indicator = document.getElementById('enc-recording-indicator');
@ -239,4 +238,3 @@
console.log('✅ Encounter module loaded');
});
})();

View file

@ -2,7 +2,7 @@
// SHADESS.JS — SSHADESS psychosocial screening form + well visit note
// ============================================================
(function() {
function setupShadessModule() {
// ── SSHADESS domain definitions ──────────────────────────────────────────
// Each domain has key questions (most important shown first) + comment field
@ -1059,4 +1059,5 @@
console.log('SHADESS module loaded');
})();
}
setupShadessModule();

View file

@ -1,8 +1,7 @@
(function() {
var _inited = false;
var _voiceDictationInited = false;
document.addEventListener('tabChanged', function(e) {
if (e.detail.tab !== 'dictation' || _inited) return;
_inited = true;
if (e.detail.tab !== 'dictation' || _voiceDictationInited) return;
_voiceDictationInited = true;
var recordBtn = document.getElementById('dict-record-btn');
var pauseBtn = document.getElementById('dict-pause-btn');
var indicator = document.getElementById('dict-recording-indicator');
@ -210,4 +209,3 @@
console.log('✅ Dictation module loaded');
});
})();

View file

@ -436,7 +436,7 @@ async function initDatabase() {
// Boot sequence: inline init (idempotent baseline) → node-pg-migrate for
// incremental changes. Migrations live in /app/migrations/.
(async function() {
async function bootstrapDatabase() {
await initDatabase();
try {
var { runMigrations } = require('./migrate');
@ -447,7 +447,8 @@ async function initDatabase() {
// broken DB separately.
console.error('[DB] Migration runner failed:', e.message);
}
})();
}
bootstrapDatabase();
// Clean up expired saved encounters and audio backups
async function cleanupExpired() {

View file

@ -568,7 +568,7 @@ router.post('/forgot-password', async (req, res) => {
// Fire-and-forget: DB lookup + token + email happen after the response
// is sent, so their latency cannot be measured by the caller.
(async function () {
async function sendResetEmailInBackground() {
try {
var user = await db.get('SELECT id FROM users WHERE email = ?', [email]);
if (!user) return;
@ -586,7 +586,8 @@ router.post('/forgot-password', async (req, res) => {
} catch (bgErr) {
console.error('[Auth] forgot-password background send failed:', bgErr.message);
}
})();
}
sendResetEmailInBackground();
} catch (err) { console.error('[Auth] Forgot password error:', err.message); res.status(500).json({ error: 'Password reset request failed' }); }
});

View file

@ -350,7 +350,7 @@ router.post('/embeddings/generate', async function(req, res) {
console.log('[Embeddings] Starting batch generation for ' + content.length + ' items...');
// Don't await — run in background
(async function() {
async function generateEmbeddingsInBackground() {
for (var i = 0; i < content.length; i++) {
var item = content[i];
try {
@ -384,7 +384,8 @@ router.post('/embeddings/generate', async function(req, res) {
console.error('[Embeddings] Index creation failed:', e.message);
}
}
})();
}
generateEmbeddingsInBackground();
res.json({
success: true,