// Phase 0 — подключает design system + interactives CSS + новые JS-модули // (phys8-anim.js, phys8-drag.js, phys8-helpers.js) во все 5 файлов учебника Физики 8: // physics_8_hub.html, physics_8_ch1.html, physics_8_ch2.html, physics_8_ch3.html, physics_8_lab.html. // Также добавляет body class (p8-theme-thermal/electric/spectrum) на каждой странице. 'use strict'; const fs = require('fs'); const path = require('path'); const TBOOKS = path.join(__dirname, '..', '..', 'frontend', 'textbooks'); const FILES = [ { name: 'physics_8_hub.html', theme: null }, { name: 'physics_8_ch1.html', theme: 'thermal' }, { name: 'physics_8_ch2.html', theme: 'electric' }, { name: 'physics_8_ch3.html', theme: 'spectrum' }, { name: 'physics_8_lab.html', theme: null }, ]; const CSS_LINKS = [ '', '', ]; const JS_LINKS = [ '', '', '', ]; // Anchor: после katex link мы добавляем design-system css const CSS_ANCHOR = ''; // Anchor: после phys.js / xp.js мы добавляем новые JS const JS_ANCHOR_OPTIONS = [ '', '', ]; let totalPatched = 0; for (const { name, theme } of FILES) { const fp = path.join(TBOOKS, name); if (!fs.existsSync(fp)) { console.warn('miss:', name); continue; } let h = fs.readFileSync(fp, 'utf8'); const before = h.length; let changes = []; // 1. CSS links for (const link of CSS_LINKS) { if (h.includes(link)) continue; if (h.includes(CSS_ANCHOR)) { h = h.replace(CSS_ANCHOR, CSS_ANCHOR + '\n' + link); changes.push('+css: ' + link.match(/href="([^"]+)"/)[1]); } } // 2. JS links — место подключения: после любого из якорей for (const link of JS_LINKS) { if (h.includes(link)) continue; let placed = false; for (const anchor of JS_ANCHOR_OPTIONS) { if (h.includes(anchor)) { h = h.replace(anchor, anchor + '\n' + link); placed = true; changes.push('+js: ' + link.match(/src="([^"]+)"/)[1]); break; } } if (!placed) { // Fallback: перед h = h.replace('', link + '\n'); changes.push('+js (head): ' + link.match(/src="([^"]+)"/)[1]); } } // 3. Theme class на body if (theme) { const themeClass = 'p8-theme-' + theme; if (!h.includes(themeClass)) { // Найти и добавить класс h = h.replace(/]*)>/, (match, attrs) => { if (/class="([^"]*)"/.test(attrs)) { return ' `class="${cls} ${themeClass}"`) + '>'; } return ``; }); changes.push('+body class: ' + themeClass); } } fs.writeFileSync(fp, h); if (changes.length) { console.log(`${name}: ${before} → ${h.length} bytes`); changes.forEach(c => console.log(' ' + c)); totalPatched++; } else { console.log(`${name}: no changes (already patched)`); } // Sanity parse inline scripts const scripts = [...h.matchAll(/