edb4c211a0
- Add js/sidebar.js: generates full sidebar HTML into #app-sidebar, handles role-based visibility, active link (with prefix matching), toggle wiring, collapsed state, board/features/notif init - Replace <aside class="sidebar">...</aside> with <aside id="app-sidebar"> across all 35 standard-layout pages via scripts/apply-sidebar.js - Add notifications.js to 5 pages that were missing it - Fix api.js initPage(): skip toggle re-wiring if data-sb-wired set, fix active link selector .sb-item → .sb-link - Remove stale sbl-*/nav-admin/btn-upload-nav getElementById calls that crashed after sidebar replacement (lab, classes, collection, crossword, hangman, knowledge-map, library, pet, profile) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
75 lines
2.5 KiB
JavaScript
75 lines
2.5 KiB
JavaScript
#!/usr/bin/env node
|
|
// Replace sidebar HTML with <aside class="sidebar" id="app-sidebar"></aside>
|
|
// and add <script src="/js/sidebar.js"></script> after api.js on each page.
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const FRONTEND = path.join(__dirname, '..', 'frontend');
|
|
|
|
// Pages that get the universal sidebar (excludes test-run.html, login.html, 403/404/500, parent.html, guest-board.html)
|
|
const PAGES = [
|
|
'admin', 'analytics',
|
|
'biochem', 'biochem-library', 'biochem-pathways', 'biochem-properties', 'biochem-reactions',
|
|
'board', 'classes', 'classroom', 'collection', 'collection-rb', 'course', 'crossword',
|
|
'dashboard', 'flashcards', 'gradebook', 'hangman', 'homework',
|
|
'knowledge-map', 'lab', 'lesson', 'lesson-editor', 'lesson-history', 'library', 'live-quiz',
|
|
'my-lessons', 'pet', 'profile', 'question-bank',
|
|
'red-book', 'red-book-biomes', 'red-book-ecosystem', 'red-book-games',
|
|
'theory',
|
|
];
|
|
|
|
// Regex: match <aside class="sidebar" ...> ... </aside>
|
|
// Handles optional extra attributes and multi-line content
|
|
const ASIDE_RE = /<aside\b[^>]*\bclass="sidebar"[^>]*>[\s\S]*?<\/aside>/;
|
|
|
|
// Match existing sidebar.js script tag
|
|
const SIDEBAR_SCRIPT_RE = /<script\s+src="\/js\/sidebar\.js"><\/script>/;
|
|
|
|
// Match api.js script tag
|
|
const API_SCRIPT_RE = /(<script\s+src="\/js\/api\.js"><\/script>)/;
|
|
|
|
let changed = 0;
|
|
let skipped = 0;
|
|
let errors = 0;
|
|
|
|
for (const name of PAGES) {
|
|
const file = path.join(FRONTEND, `${name}.html`);
|
|
if (!fs.existsSync(file)) {
|
|
console.log(` SKIP ${name}.html (not found)`);
|
|
skipped++;
|
|
continue;
|
|
}
|
|
|
|
let src = fs.readFileSync(file, 'utf8');
|
|
let modified = false;
|
|
|
|
// 1. Replace sidebar <aside>
|
|
if (ASIDE_RE.test(src)) {
|
|
src = src.replace(ASIDE_RE, '<aside class="sidebar" id="app-sidebar"></aside>');
|
|
modified = true;
|
|
} else if (!src.includes('id="app-sidebar"')) {
|
|
console.log(` WARN ${name}.html — no <aside class="sidebar"> found`);
|
|
}
|
|
|
|
// 2. Add sidebar.js script after api.js (if not already present)
|
|
if (!SIDEBAR_SCRIPT_RE.test(src)) {
|
|
if (API_SCRIPT_RE.test(src)) {
|
|
src = src.replace(API_SCRIPT_RE, '$1\n <script src="/js/sidebar.js"></script>');
|
|
modified = true;
|
|
} else {
|
|
console.log(` WARN ${name}.html — no api.js script tag found`);
|
|
}
|
|
}
|
|
|
|
if (modified) {
|
|
fs.writeFileSync(file, src, 'utf8');
|
|
console.log(` OK ${name}.html`);
|
|
changed++;
|
|
} else {
|
|
console.log(` - ${name}.html (no changes)`);
|
|
}
|
|
}
|
|
|
|
console.log(`\nDone: ${changed} updated, ${skipped} skipped, ${errors} errors.`);
|