// Inject task panels (ptab-pN scaffold + JS auto-render) into physics_9_ch4.html // for §31..§36 — the only paragraphs with TASKS_PN arrays in the monolith. 'use strict'; const fs = require('fs'); const path = require('path'); const TBOOKS = path.join(__dirname, '..', '..', 'frontend', 'textbooks'); const SRC = path.join(TBOOKS, 'physics_9.html'); const DST = path.join(TBOOKS, 'physics_9_ch4.html'); const src = fs.readFileSync(SRC, 'utf8'); let ch4 = fs.readFileSync(DST, 'utf8'); // === Extract each ptab-pN block (N in 31..36) === function clean(s) { return s .replace(/[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{27BF}]|[\u{1F000}-\u{1F2FF}]|[\u{FE0F}]/gu, '') .replace(/]*>\s*<\/i>/g, '') .trim(); } function extractPtab(n) { const tag = `id="ptab-p${n}"`; const i = src.indexOf(tag); if (i < 0) return null; // Откатываемся к открывающему div const divStart = src.lastIndexOf(' непосредственно перед следующим ptab let closingDiv = src.lastIndexOf('', endTag); if (closingDiv < divStart) closingDiv = endTag; return src.slice(divStart, closingDiv + 6); } const PTABS = {}; for (let n = 31; n <= 36; n++) { const b = extractPtab(n); if (b) PTABS[n] = clean(b); } console.log('Extracted ptabs:', Object.keys(PTABS).map(k => `p${k}:${PTABS[k].length}b`).join(' ')); // === Inject ptab block + auto-render call into each build_pN in ch4 === // Pattern: each build_pN ends with `box.innerHTML = html; renderMath(box); wireReadBtn('pN');` // We append the ptab HTML to the same box, then call window.goToTask('pN', 0) to start. for (let n = 31; n <= 36; n++) { if (!PTABS[n]) continue; const pid = 'p' + n; // Escape for template literal const esc = PTABS[n].replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${'); // Find build_pN function end const fnRegex = new RegExp( `(function\\s+build_${pid}\\(\\)\\s*\\{[\\s\\S]*?wireReadBtn\\('${pid}'\\);)\\s*\\}`, 'm' ); const match = ch4.match(fnRegex); if (!match) { console.warn(`build_${pid}: not found`); continue; } // Build new function body: append ptab HTML + setup call const injectedBlock = ` // === Задачи §${n} — task panel (auto-injected from monolith) === const tasksBlock = document.createElement('div'); tasksBlock.className = 'wg'; tasksBlock.style.marginTop = '20px'; tasksBlock.innerHTML = '
Задачи
Тренажёр §${n}
' + \`${esc}\`; box.appendChild(tasksBlock); // Auto-render first task setTimeout(() => { try { if (typeof goToTask === 'function') goToTask('${pid}', 0); } catch(e) { console.warn('${pid} goToTask:', e.message); } }, 80);`; const newBody = match[1] + injectedBlock + '\n}'; ch4 = ch4.replace(fnRegex, () => newBody); console.log(` build_${pid}: injected ptab (${esc.length} bytes)`); } fs.writeFileSync(DST, ch4); console.log('ch4 size:', ch4.length); // Sanity parse inline scripts const scripts = [...ch4.matchAll(/