از canvas تا textarea: ساخت یه ادیتور کد تو مرورگر
خلاصهٔ کاملتر
نویسنده میگه بعد از نوشتن یه پست دربارهٔ اینکه دیگه نرمافزارهایی مثل Sublime Text ساخته نمیشه، با خودش گفته چرا خودم یه ادیتور متن نسازم. نقطهٔ شروعش هم این بوده که VS Code روی Monaco Editor سوار شده، یعنی یه انبوه تو دل هم، و اگه استاندارد کار این باشه پس جا برای اشتباه زیاده.
اولین آزمایشش این بود که کل متن رو روی یه المنت رندر کنه. چندتا قابلیت حداقلی مثل جابهجایی نشانگر با کلیدهای جهتدار، هایلایت خط فعلی و تایپ کردن رو پیاده کرد، ولی canvas هیچی رو مجانی نمیده: انتخاب متن، تاریخچهٔ undo/redo، پیست چندخطی و اسکرول هیچکدوم نبودن. برای اسکرول تقلب کرد و یه مخفی هماندازهٔ متن گذاشت و از موقعیت اسکرول اون برای حساب کردن آفست رندر استفاده کرد.
مشکل بزرگتر این بود که canvas کاملاً غیرقابلدسترسه، یعنی screen reader و ابزارهای کمکی هیچی ازش نمیفهمن. برای همین رفت سراغ یه ایدهٔ بهتر: همون رو با اتریبیوت contenteditable قابل ویرایش کرد. مقدار plaintext-only این اتریبیوت دقیقاً به درد کد میخوره، چون کل محتوا تو یه text node میمونه و مرورگر انتخاب متن و undo رو مجانی بهت میده.
<div
contenteditable="plaintext-only"
autocorrect="off"
spellcheck="false">
</div>یه نکتهٔ ریز ولی گرون: اتریبیوت spellcheck باید خاموش باشه وگرنه تأخیر تایپ میپره بالا، و به گفتهٔ نویسنده چند روز طول کشیده تا اینو پیدا کنه. با Selection API هم اندازهها رو میگیره تا نشانگر سفارشی خودشو بکشه. ولی contenteditable از یه تعداد کاراکتر به بعد رفتار عجیب و کندی نشون میده، مخصوصاً تو مرورگرهای Chromium.
آخرش امتحان کرد ببینه یه سادهٔ قدیمی جواب میده یا نه، و جواب مثبت بود: برای متن طولانی خیلی سریعتره. چون textarea از CSS highlight پشتیبانی نمیکنه، یه لایهٔ سوم روش گذاشت و با MicroLighter هایلایت سینتکس رو اضافه کرد. نویسنده میگه راه محکمتر اینه که با Tree-sitter درخت سینتکس بسازه و فقط خطهای دیدهشده رو هایلایت کنه. فعلاً هم پروژه رو برای یه روز بارونی کنار گذاشته.
نکات کلیدی:
- canvas سریع رندر میکنه ولی انتخاب متن، undo و دسترسپذیری رو باید از صفر بنویسی
- مقدار plaintext-only تو contenteditable کل محتوا رو تو یه text node نگه میداره و مناسب کده
- خاموش نکردن spellcheck روی ناحیهٔ ویرایشپذیر باعث پرش تأخیر ورودی میشه
- برای متن طولانی از contenteditable سریعتره ولی CSS highlight نداره
- طبق آپدیت خود پست، OpaqueRange API هایلایت سفارشی رو برای textarea باز میکنه و EditContext API ورودی canvas رو بهتر میکنه




