عن المشروع

Pretext هي مكتبة JavaScript/TypeScript خالصة لقياس النصوص متعددة الأسطر وحساب تخطيط الأسطر. تتجنب واجهات قياس DOM مثل `getBoundingClientRect` و`offsetHeight`، التي تفرض إعادة تدفق التخطيط، وتنفذ قياسها الخاص باستخدام `measureText` من canvas في المتصفح كمرجع أساسي. يجعلها هذا مفيدة للافتراضية (virtualization)، ومحركات التخطيط المخصصة، والعرض عبر canvas/SVG، وفحوصات التجاوز أثناء التطوير. ## التثبيت ```sh npm install @chenglou/pretext ``` ## حالات الاستخدام الرئيسية ### 1. قياس ارتفاع الفقرة دون لمس DOM ```ts import { prepare, layout } from '@chenglou/pretext' const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀', '16px Inter') const { height, lineCount } = layout(prepared, 320, 20) ``` تقوم `prepare()` بعمل لمرة واحدة: تطبيع المسافات البيضاء، وتقسيم النص، وتطبيق قواعد glue، والقياس المعتمد على canvas. ثم تكون `layout()` عملية حسابية خالصة ورخيصة على العرضات المخزنة مؤقتًا، لذا يمكن إعادة تشغيلها عند تغيير الحجم دون إعادة التحضير. تشمل خيارات `prepare()` الخيار `whiteSpace: 'pre-wrap'` لسلوك شبيه بـ textarea، و`wordBreak: 'keep-all'` لما يعادل CSS `word-break: keep-all`، و`letterSpacing` لما يعادل CSS `letter-spacing`. ### 2. تخطيط الأسطر يدويًا تعيد `prepareWithSegments()` بنية أغنى للتخطيط المخصص. تتوفر واجهات API التالية: - `layoutWithLines()` — تعيد كل الأسطر عند عرض أقصى ثابت، بما في ذلك النص والعرضات المقيسة. - `walkLineRanges()` — تستدعي دالة callback لكل سطر مع العرض ومؤشرات البداية/النهاية، دون بناء سلاسل الأسطر. - `measureLineStats()` — تعيد عدد الأسطر وعرض أوسع سطر دون تخصيصات. - `measureNaturalWidth()` — تعيد أوسع سطر مفروض عندما لا يكون العرض سبب الالتفاف. - `layoutNextLine()` / `layoutNextLineRange()` — واجهات API بنمط المكرر لتخطيط الأسطر واحدًا تلو الآخر بعرضات قد تختلف، وهي مفيدة لتدفق النص حول العناصر العائمة أو الحاويات الديناميكية. - `materializeLineRange()` — تحوّل نطاق تخطيط مرة أخرى إلى سلسلة سطر كاملة. تتيح هذه الواجهات العرض إلى Canvas وSVG وWebGL، وفي النهاية إلى بيئات الخادم. تتضمن المستودع عروضًا توضيحية، وكذلك على chenglou.me/pretext. ## مساعد rich inline يدعم مساعد منفصل في `@chenglou/pretext/rich-inline` تدفقًا مضمّنًا أساسيًا للنص المنسق بخطوط مختلطة، وعناصر ذرية (مثل chips وmentions)، وعرضًا إضافيًا مملوكًا للمستدعي لهيكل الحبوب (pill chrome). وهو ضيق عن قصد: مضمّن فقط، و`white-space: normal` فقط، وليس محرك تنسيق مضمّن CSS عامًا. ## أبرز بنود مسرد API - `PreparedText` هو المقبض السريع غير الشفاف؛ و`PreparedTextWithSegments` هو مقبض التخطيط اليدوي الأغنى. - يستخدم `LayoutCursor` مؤشرات segment/grapheme، وليس إزاحات السلسلة الخام. - تعيد `layout()` على سلسلة فارغة `{ lineCount: 0, height: 0 }`؛ تحدد المتصفحات حجم الكتل الفارغة بارتفاع سطر واحد، لذا قد يرغب المستدعون في تقييد القيمة. - تُدعم الواصلات الناعمة (soft hyphens): تعمل كنقاط فاصل اختيارية وتتجسد كـ `-` زائدة عند اختيارها. - تمسح `clearCache()` ذاكرات التخزين المؤقت الداخلية المشتركة؛ وتضبط `setLocale()` اللغة الإعدادية لاستدعاءات التحضير المستقبلية. - يتضمن المقبض الأغنى `segLevels` تقريبية للعرض المخصص المدرك لـ bidi، لكن Pretext لا تنفذ خوارزمية Unicode ثنائية الاتجاه الكاملة. ## تحذيرات Pretext ليست محرك عرض خطوط كاملًا. تستهدف إعدادات CSS النصية الشائعة: - `white-space: normal` و`pre-wrap` - `word-break: normal` و`keep-all` - `overflow-wrap: break-word` - `line-break: auto` - `letter-spacing` كقيمة بكسل رقمية - تتبع علامات الجدولة الإعداد الافتراضي `tab-size: 8` قيود ملحوظة: - `system-ui` و`-apple-system` غير آمنين على macOS لدقة `layout()`؛ يُوصى بخط مسمّى. - قد تلتف الرموز التعبيرية بجوار علامات الترقيم بشكل مختلف عن المتصفح. - قد تنتج بعض الخطوط، مثل Shantell Sans، فواصل أسطر مختلفة في الكلمات الطويلة. - يتطلب وقت التشغيل `Intl.Segmenter`، وقياس نص Canvas 2D، وUnicode property escapes. - لا تُنمذج ميزات خطوط CSS خارج اختصار `font` في canvas بشكل منفصل. بشكل عام، تُقدَّم Pretext كمكتبة مركزة لقياس النصوص متعددة الأسطر تمنح مطوري الويب بديلًا سريعًا وحتميًا لاستعلامات تخطيط المتصفح.