66bd7ac1f4
Три бага из жалобы пользователя: 1) phys9_legacy.js упал с 'Identifier STATE has already been declared' — const STATE в монолите конфликтовал с const STATE в chapter inline JS. Скрипт extract_phys9_legacy.cjs теперь оборачивает извлечённый код в IIFE и явно экспортит через window 70 функций (upd*/draw*/init*/start*/lab*/ check*/toggle*/render*/show*/...) + 7 const-массивов (TASKS_PN, PUZ_PN). 2) В боковой панели формулы рендерились как 'Delta vecr' вместо Δr⃗ — мой переход на JSON.stringify в gen_phys9_ch.js добавил лишний слой escape backslash. Уменьшил \\ → \ в SIDEBAR_ROWS, TIPS_HTML, PARA_SUBS, LR_SUBS (90 строк). Цепочка теперь: source \Delta → string \Delta → JSON "\\Delta" → HTML JS \Delta → runtime \Delta → KaTeX \Delta ✓. 3) 'не работают симуляции' — функции из legacy.js были доступны, но chapter goTo(id) их не вызывал. Добавлен авто-вызов upd<N>(), startAnim<N>(), init<N>(), draw<N>() при переключении на параграф, и updLab<N>(), drawLab<N>() — для ЛР.
59 lines
3.0 KiB
JavaScript
59 lines
3.0 KiB
JavaScript
// Извлекает <script> из physics_9.html в frontend/js/phys9_legacy.js.
|
||
// Оборачивает в IIFE (избегаем коллизий STATE/PARAS с chapter inline JS).
|
||
// Эспортит в window все функции с префиксами upd|draw|init|start|set|toggle|lab|check + TASKS_PN/PUZ_PN/массивы.
|
||
'use strict';
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
const SRC = path.join(__dirname, '..', '..', 'frontend', 'textbooks', 'physics_9.html');
|
||
const DST = path.join(__dirname, '..', '..', 'frontend', 'js', 'phys9_legacy.js');
|
||
|
||
const h = fs.readFileSync(SRC, 'utf8');
|
||
const scriptMatch = h.match(/<script>([\s\S]*?)<\/script>/);
|
||
if (!scriptMatch) { console.error('No <script> found'); process.exit(1); }
|
||
const raw = scriptMatch[1];
|
||
|
||
// Очистка emoji
|
||
const clean = raw.replace(/[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{27BF}]|[\u{1F000}-\u{1F2FF}]|[\u{FE0F}]/gu, '');
|
||
|
||
// Найти границу setup-кода
|
||
const setupStart = clean.search(/^upd1\d\(\);/m);
|
||
const fnsPart = setupStart > 0 ? clean.slice(0, setupStart) : clean;
|
||
const setupPart = setupStart > 0 ? clean.slice(setupStart) : '';
|
||
|
||
// Сканируем все function-declarations и const-объявления массивов
|
||
const fnNames = [...new Set([...fnsPart.matchAll(/^function\s+(\w+)\s*\(/gm)].map(m => m[1]))];
|
||
const constNames = [...new Set([...fnsPart.matchAll(/^const\s+(TASKS_\w+|PUZ_\w+|QUIZ_\w+|MATCH_\w+)\s*=/gm)].map(m => m[1]))];
|
||
|
||
// Только идентификаторы, которые могут использоваться извне (по префиксу или капсу)
|
||
const exportFns = fnNames.filter(n => /^(upd|draw|init|start|set|toggle|lab|check|reset|next|go|run|play|stop|render|update|show|hide|build|switch|select|apply|calc|recalc|animate|tick)/i.test(n));
|
||
const exportList = [...exportFns, ...constNames];
|
||
|
||
const header = `// Auto-extracted from frontend/textbooks/physics_9.html (legacy monolith).
|
||
// Wrapped in IIFE — avoids collisions with chapter inline JS (STATE, PARAS, etc.).
|
||
// All upd*/draw*/init*/start*/lab*/check*/toggle* functions + TASKS_PN arrays
|
||
// are explicitly attached to window at the end.
|
||
// eslint-disable
|
||
|
||
(function(){
|
||
"use strict";
|
||
`;
|
||
|
||
const exportTail = '\n\n// === Expose handlers + task pools to global scope ===\n' +
|
||
exportList.map(name => `try { if (typeof ${name} !== "undefined") window.${name} = ${name}; } catch(e) {}`).join('\n') +
|
||
'\n})();\n';
|
||
|
||
const wrapped = setupStart > 0
|
||
? header + fnsPart + '\ntry {\n' + setupPart + '\n} catch(e) { console.warn("phys9_legacy setup skipped:", e.message); }\n' + exportTail
|
||
: header + fnsPart + exportTail;
|
||
|
||
fs.writeFileSync(DST, wrapped);
|
||
console.log('phys9_legacy.js:', wrapped.length, 'bytes');
|
||
console.log('Exported functions:', exportFns.length);
|
||
console.log('Exported consts:', constNames.length);
|
||
console.log('Sample exports:', exports.slice(0, 12).join(', '), '...');
|
||
|
||
// Sanity parse
|
||
try { new Function(wrapped); console.log('OK parse'); }
|
||
catch(e) { console.error('PARSE FAIL:', e.message); process.exit(1); }
|