Files
Learn_System/backend/scripts/extract_phys9_legacy.cjs
Maxim Dolgolyov 66bd7ac1f4 fix(textbooks): Физика 9 — STATE collision, KaTeX escape, авто-init симуляций
Три бага из жалобы пользователя:

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>() — для ЛР.
2026-05-30 09:06:20 +03:00

59 lines
3.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Извлекает <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); }