forked from Tadrisino/MathApp_frontend
48 lines
2.4 KiB
TypeScript
48 lines
2.4 KiB
TypeScript
import { MathText } from './MathText';
|
||
import { toFa } from './format';
|
||
|
||
/**
|
||
* متنِ درس که قدمهایش در یک پاراگراف پشتِ هم آمدهاند («۱. مجموعه را بنویسید. ۲. بررسی کنید… ۳. …»):
|
||
* ۱۰۴۱ مقدمهی درس در دیتابیس همین شکلاند (۱۴۰۵-۰۷) و روی صفحه یک تکهی درهم دیده میشدند. اینجا به
|
||
* فهرستِ شمارهدار تبدیل میشوند؛ متنِ بیفهرست همان پاراگرافِ قبلی میماند.
|
||
*
|
||
* فقط دنبالهی ۱، ۲، ۳، … با «.» یا «)» و فاصلهی بعدش شمرده میشود، پس «۳.۵» (اعشار) و «شکلِ ۲. سپس» که
|
||
* پیش از آن ۱ ندارد فهرست نمیشوند.
|
||
*/
|
||
const MARKER = /(^|\s)([0-9۰-۹]{1,2})[.)](?=\s)/g;
|
||
const num = (d: string) => Number(d.replace(/[۰-۹]/g, (c) => String(c.charCodeAt(0) - 0x06f0)));
|
||
|
||
export function parseNumbered(text: string): { lead: string; items: string[] } | null {
|
||
const marks: { start: number; end: number }[] = [];
|
||
for (const m of text.matchAll(MARKER)) {
|
||
if (num(m[2]) !== marks.length + 1) continue;
|
||
const start = (m.index ?? 0) + m[1].length;
|
||
marks.push({ start, end: start + m[2].length + 1 });
|
||
}
|
||
if (marks.length < 2) return null;
|
||
return {
|
||
lead: text.slice(0, marks[0].start).trim(),
|
||
items: marks.map((mk, i) => text.slice(mk.end, marks[i + 1]?.start ?? text.length).trim()),
|
||
};
|
||
}
|
||
|
||
export function StepText({ text, color, className = '' }: { text: string; color: string; className?: string }) {
|
||
const list = parseNumbered(text);
|
||
if (!list) return <p className={`whitespace-pre-line ${className}`}><MathText text={text} display /></p>;
|
||
return (
|
||
<div className={className}>
|
||
{list.lead && <p className="mb-2 whitespace-pre-line"><MathText text={list.lead} display /></p>}
|
||
<ol className="flex flex-col gap-2.5">
|
||
{list.items.map((item, i) => (
|
||
<li key={i} className="flex gap-2.5">
|
||
<span className="mt-0.5 flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-full text-xs font-black text-white" style={{ backgroundColor: color }}>
|
||
{toFa(i + 1)}
|
||
</span>
|
||
<span className="flex-1 whitespace-pre-line"><MathText text={item} display /></span>
|
||
</li>
|
||
))}
|
||
</ol>
|
||
</div>
|
||
);
|
||
}
|