feat(trainer): авто-KaTeX во ВСЕХ текст-условиях (формулы рендерятся везде)
renderMixed теперь авто-детектит математику в любом текст-условии (compute/verify/ choice/word), без обязательных $...$: латино-цифровые «прогоны» (дроби, уравнения, степени x²/(x+1)², проценты %, градусы °, десятичные) → KaTeX через exprToLatex; кириллица/слова остаются текстом. Одиночные числа НЕ рендерятся (только выражения с оператором/степенью/%/°), чтобы не «утяжелять» прозу. Безопасность: любой неразобравшийся фрагмент остаётся обычным экранированным текстом (худший случай = прежнее поведение). $...$ по-прежнему форсирует рендер. showStatement применяет авто-рендер ко всем текст-условиям (целые уравнения solve/ roots идут единым latex как раньше). Проверка: реплика логики прогнана по ВСЕМ генераторам (2388 дисплеев / 1609 матем. фрагментов): 0 кириллицы в формулах, все фрагменты валидны, проза сохранена — 3997/0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+38
-9
@@ -622,17 +622,47 @@
|
||||
// Смешанный текст «проза + математика»: фрагменты в $...$ рендерятся KaTeX
|
||||
// (через exprToLatex), остальное экранируется. Так формулы видны и в текст-условиях
|
||||
// (проценты/дроби/verify/choice), где нет единого latex уравнения.
|
||||
// Возврат «косметики» prettyMath к виду, понятному SimExpr-парсеру.
|
||||
function _unpretty(s) {
|
||||
return String(s).replace(/[·×]/g, '*').replace(/−/g, '-').replace(/÷/g, '/').replace(/²/g, '^2').replace(/³/g, '^3');
|
||||
}
|
||||
// Один математический фрагмент → KaTeX-html или null (если не математика / не разобрался).
|
||||
function _mathRun(run) {
|
||||
var suffix = '', core = run, t = core.match(/(%|°)$/);
|
||||
if (t) { suffix = (t[1] === '%') ? '\\%' : '^{\\circ}'; core = core.slice(0, -1); }
|
||||
// рендерим только если есть оператор/степень/дробь/проценты-градусы (одиночные числа/слова — текстом)
|
||||
var worth = /[\/^=<>+\-−·×÷√]|[0-9][A-Za-z]|²|³/.test(run) || suffix;
|
||||
if (!worth) return null;
|
||||
core = _unpretty(core);
|
||||
if (!/[0-9A-Za-z]/.test(core)) return null;
|
||||
var lx = TE.exprToLatex(core);
|
||||
if (lx == null) return null;
|
||||
return kat(lx + suffix, false);
|
||||
}
|
||||
// Авто-рендер математики в прозе: латино-цифровые «прогоны» → KaTeX, кириллица/слова — текст.
|
||||
function _autoProse(s) {
|
||||
var out = '', re = /[0-9A-Za-z(][\w ().,^*\/+\-=<>≤≥≠·×÷√²³°%]*/g, last = 0, m;
|
||||
while ((m = re.exec(s))) {
|
||||
out += esc(s.slice(last, m.index));
|
||||
var run = m[0], tail = '', tm = run.match(/[ ,.;:]+$/);
|
||||
if (tm) { tail = run.slice(run.length - tm[0].length); run = run.slice(0, run.length - tm[0].length); }
|
||||
var r = _mathRun(run);
|
||||
out += (r != null ? r : esc(run)) + esc(tail);
|
||||
last = m.index + m[0].length;
|
||||
}
|
||||
out += esc(s.slice(last));
|
||||
return out;
|
||||
}
|
||||
// Смешанный текст: $...$ — принудительная математика; вне — авто-детект формул.
|
||||
// Безопасно: любой неразобравшийся фрагмент остаётся обычным экранированным текстом.
|
||||
function renderMixed(text) {
|
||||
var parts = String(text == null ? '' : text).split('$');
|
||||
var html = '';
|
||||
var parts = String(text == null ? '' : text).split('$'), html = '';
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
if (i % 2 === 1) { // нечётные сегменты — математика
|
||||
// prettyMath уже мог заменить * → ·, − и т.п.; возвращаем к виду для SimExpr-парсера
|
||||
var src = parts[i].replace(/[·×]/g, '*').replace(/−/g, '-').replace(/÷/g, '/');
|
||||
var lx = TE.exprToLatex(src);
|
||||
if (i % 2 === 1) {
|
||||
var lx = TE.exprToLatex(_unpretty(parts[i]));
|
||||
html += lx ? (kat(lx, false) || esc(parts[i])) : esc(parts[i]);
|
||||
} else {
|
||||
html += esc(parts[i]);
|
||||
html += _autoProse(parts[i]);
|
||||
}
|
||||
}
|
||||
return html;
|
||||
@@ -645,8 +675,7 @@
|
||||
var latex = useFig ? null : problem.latex;
|
||||
eq.classList.toggle('tr-eq-text', !latex);
|
||||
if (latex) { setMath(eq, latex, text, true); return; } // целое уравнение (solve/roots/…)
|
||||
if (text && text.indexOf('$') !== -1) eq.innerHTML = renderMixed(text); // текст с инлайн-формулами
|
||||
else eq.textContent = text;
|
||||
eq.innerHTML = renderMixed(text); // текст-условие: авто-рендер формул в KaTeX
|
||||
}
|
||||
// Переключатель «Текст / На чертеже» — только для задач с чертежом и кратким условием.
|
||||
function renderFigureToggle() {
|
||||
|
||||
Reference in New Issue
Block a user