دليل أسطرلاب English GitHub

الخطوط

كتالوج خطوط يُقدَّم من خادمك أنت، وخانات الخطوط الأربع، وخطوطك التي ترفعها بنفسك، وكيف يتقاسم الحرف العربي والحرف اللاتيني فقرة واحدة.


يمكنك تغيير خطوط التطبيق بكتابة CSS (انظر طريق custom.css). أما كتالوج الخطوط فهو طريقة لفعل ذلك من غير CSS، وسبب وجوده هو العربية. افتح الإعدادات ← التخطيط والخط فتجد أربعة منتقيات، واحدًا لكل خانة:

الخانةتتحكم فيتعرض
نص القراءة--font-serif: عمود القراءة ونثر المحرر والعناوينLora وEB Garamond وCrimson Pro وLiterata وSource Serif 4 وMerriweather وInter وSource Sans 3 وIBM Plex Sans وWork Sans
الواجهة--font-ui: اللوحة الجانبية والتبويبات واللوحات وشريط الحالةالقائمة اللاتينية نفسها
الشيفرة--font-mono: كتل الشيفرة وماركداون الخام والشيفرة داخل السطرJetBrains Mono وIBM Plex Mono وFira Code وSource Code Pro
الخط العربيالحروف العربية في الخانات الثلاث أعلاه كلهاAmiri وScheherazade New وNoto Naskh Arabic وMarkazi Text وLateef وAref Ruqaa · Noto Kufi Arabic وNoto Sans Arabic وIBM Plex Sans Arabic وCairo وTajawal وReem Kufi وAlmarai

وتقبل كل خانة أيضًا system، وهو الافتراضي: الخطوط الموجودة أصلًا على جهاز القارئ، فلا يُنزَّل شيء ولا يُقدَّم شيء. وتعرض كل خانة أيضًا خطوطك المرفوعة (انظر أدناه). وإعادة تعيين الخطوط تعيد الأربع كلها إلى system.

يرسم المنتقي كل خيار بالخط الذي يسمّيه. فقائمة أسماء خطوط كُتبت كلها بخط الواجهة ليست إلا قائمة أسماء تجارية: لا أحد يستطيع أن يختار بين Literata وSource Serif بقراءة الكلمات. لذلك يُعرض كل صف بخطه هو، وتعرض الخطوط العربية نموذجًا عربيًا، والصفوف مجمَّعة (مذيَّل / غير مذيَّل / ثابت العرض / نسخ / حديث وكوفي / خطوطك) وفوقها حقل تصفية. وتُجلب الخطوط مجموعةً مجموعة، حين تظهر المجموعة للمرة الأولى، ففتح منتقي الشيفرة لا ينزّل الخطوط العربية أبدًا.

ويبقى النموذج على الشاشة وأنت تختار. كتلة نموذج حية مثبَّتة في أعلى التبويب: سطر مختلط لكل خانة، فيه اللاتيني والعربي في مقطع واحد، فترى بنظرة أيّ الحروف يأخذ أيّ خط. وتتجدّد قبل أن تحفظ، ومعها مقياس الحجم الذي تحتها. فاختيار الخط دورة من المقارنة والتعديل، والمعاينة التي يغطيها المنتقي لا تعاين شيئًا.

الاستضافة الذاتية هي التصميم كله

خط واحد يأتي مع التطبيق نفسه: Noto Naskh Arabic، عادي وعريض، برخصة SIL المفتوحة، للحروف العربية وحدها. على جهاز فيه هذا الخط أصلًا تُستعمل النسخة المثبتة ولا يُجلب شيء. وعلى جهاز ليس فيه، كتثبيت لينكس جديد أو ويندوز بلا حزمة اللغة العربية، كانت العربية تسقط إلى ما يجده النظام، وقد لا يكون مقروءًا. الآن تُقرأ العربية كما ينبغي من أول تشغيل، في كل نسخة، قبل أن تختار شيئًا. وكل ما يلي عن الخطوط التي تختارها أنت فوق ذلك.

حين تحفظ يجلب الخادم، لا المتصفح، عائلات الخطوط المختارة مرة واحدة من Google Fonts (بطلب woff2، فيحصل على ملفات woff2). يقرأ كتل @font-face في الجواب، وينزّل كل ملف خط إلى ASTROLABE_DATA/fonts/catalog/<id>/، ويسجّل نطاق unicode-range لكل ملف (أي مجموعة الأحرف التي يغطيها) في ملف meta.json بجانبها. ومن تلك اللحظة لا يكلّم المتصفح إلا خادمك: يُولَّد GET /api/site-fonts.css من تلك الذاكرة، وكل src: فيه يشير إلى /api/fonts/catalog/… على هذه النسخة. لا يتصل متصفح أي زائر بمضيف خارجي أبدًا، لا من أجل الخطوط ولا من أجل ورقة الأنماط. وفي جهة الجلب لا يمكن الوصول إلا إلى مضيفين اثنين (fonts.googleapis.com وfonts.gstatic.com)، بقائمة سماح صارمة تُفرض على الرابط بعد تحليله، مع رفض إعادة التوجيه، ومهل زمنية، وسقوف للحجم لكل ملف ولكل عائلة. والتنزيل الذي يخفق يعطي 502 واضحًا مع رسالة، ويُترك settings.json كما كان تمامًا. وهكذا يواصل الجهاز المنقطع عن الإنترنت تقديم ما خزّنه من قبل، والحفظ الذي لا يفعل إلا إعادة اختيار عائلات مخزَّنة يعمل من غير شبكة أصلًا.

الخانة العربية لكل حرف لا لكل لغة

لا تعرّف ورقة الأنماط المولَّدة ثلاث عائلات خطوط وتترك الأمر للحظ. بل تعرّف ثلاثة مركّبات: AstrolabeProse وAstrolabeUI وAstrolabeMono. وفي كل مركّب تأتي كتل @font-face الخاصة بالخط العربي أولًا، مقصورةً على كتل يونيكود العربية، ثم تأتي كتل الخط اللاتيني بعدها وقد اقتُطعت منها تلك النطاقات نفسها. فالمجموعتان لا تتداخلان، وتتولى مطابقة الخطوط حرفًا حرفًا في المتصفح ما بقي. ففي

A mixed line is where the trick shows: the word خط sits inside an English sentence.

تُكتب الكلمات اللاتينية بـLora والكلمة العربية بـAmiri، في فقرة واحدة، من غير ترميز ولا خاصية lang ولا اتجاه. ويعمل هذا على نسخة إنجليزية أيضًا، وهذا هو المقصود: فالخزانة التي فيها اقتباسات عربية داخل ملاحظات إنجليزية لم يكن لها جواب جيد من قبل.

وبالحجم الصحيح

اختيار الخط الصحيح نصف المسألة فقط. أما النصف الآخر فهو كم يبدو كبيرًا. فخطان بحجم font-size واحد ليسا خطين بحجم ظاهر واحد. حروف Amiri الأساسية يبلغ ارتفاعها نحو 0.35 em بينما تبلغ الحروف الصغيرة في Lora نحو 0.51 em، فالمقطع العربي غير المعدَّل بجانب Lora يبدو أصغر بنحو الثلث، كحاشية سقطت وسط فقرة. لذلك يحمل كل مدخل عربي في الكتالوج size-adjust مقيسًا (Amiri 138%، وScheherazade New 136%، وLateef 150%، وNoto Kufi Arabic 90%، وCairo وAlmarai بلا تعديل)، يُكتب على كتل @font-face لتلك العائلة في المركّب. ولأنه محمول على الخط فهو يُطبَّق حرفًا حرفًا، في كل خانة، على النسخة الإنجليزية كما على العربية. أما مضاعف --font-scale الذي يكبّر الواجهة كلها تحت :root[lang="ar"] فلا يستطيع ذلك أبدًا، لأنه يكبّر الحرفين معًا بالنسبة نفسها فلا يغيّر النسبة بينهما. وتعود المركّبات في النهاية إلى var(--font-*-system)، فأي حرف لا يغطيه أي من الخطين يحطّ على الطقم الذي كانت النسخة ستستخدمه، بما فيه تقديم العربية وتعويض الحجم العربي الذي يطبّقه :root[lang="ar"].

خطوطك الخاصة

كتالوج من سبع وعشرين عائلة من Google لا يمكن أن يكون الجواب الكامل عن الخطوط، وهو أبعد ما يكون عن ذلك في العربية: فالخط الذي تريده نسخة جادة عادةً خط اشترى صاحبه رخصته، وليس على شبكة توزيع أحد. لذلك يقبل الإعدادات ← التخطيط والخط← خطوطك الخاصة رفع الخطوط.

الصيغ.woff2 و.woff و.ttf و.otf
الحجم5 ميغابايت لكل ملف
يُخزَّن فيASTROLABE_DATA/fonts/custom/: خارج الخزانة، وASTROLABE_DATA متجاهَل في git، فلا يصل الخط المرفوع إلى مستودع ملاحظاتك ولا إلى دفعة نسخ احتياطي أبدًا
يُقدَّم منGET /api/fonts/custom/<file> على هذه النسخة، بشروط ذاكرة الكتالوج نفسها: مستضاف ذاتيًا، بلا مضيف خارجي، بتخزين ثابت
يُعرض فيالخانات الأربع كلها، تحت خطوطك

وتُحدَّد الصيغة من البايتات الأولى في الملف (wOF2 وwOFF و0x00010000 وtrue وOTTO)، لا من الامتداد أبدًا ولا من نوع المحتوى الذي يعلنه الرفع، لأن كليهما نصّ يتحكم فيه المهاجم. فملف PNG أُعيدت تسميته .woff2 يأخذ 400، وهذا مهم لأن الملف على وشك أن يُقدَّم للمتصفحات بنوع MIME للخطوط. ثم تُقرأ الترويسة للتحقق من البنية: عدد جداول معقول، ودليل جداول يتسع داخل الملف الذي جاء فيه. لا يكلف هذا الفحص شيئًا، ويحوّل الملف الذي لا يمكن أن يُعرض أبدًا (بايتات أولى صحيحة يتبعها خمسة ملايين صفر) إلى 400 عند الرفع بدل خط لا يُرسم أبدًا في صمت.

وكل ما يفكّ الخادم ضغطه من ملف مرفوع محدود قبل أن يُقرأ. فجدول name يقع خلف مرور brotli واحد في WOFF2 وخلف zlib لكل جدول في WOFF1، وأيّ منهما يمكن أن يكون «قنبلة فكّ ضغط» ما لم يُقيَّد الناتج: ملف من 800 بايت يحمل تياره 900 ميغابايت من الأصفار كان سيحجز الـ900 ميغابايت كلها، دفعة واحدة، من طلب واحد. وكل عملية فكّ ضغط مقيَّدة بالطول الذي يعلنه دليل الملف نفسه، وهو بدوره مقيَّد بسقف صارم قدره 32 ميغابايت. والملف الذي يتجاوز الحدّ لا يُرفض، بل يأخذ اسم عائلة مشتقًّا من اسم الملف، وهذا ما كان الخط غير المقروء يفعله دائمًا.

واسم الملف المخزَّن اسم مختصر يبنيه هذا الخادم (حروف ASCII صغيرة، مع لاحقة عند التصادم)، فلا شيء تكتبه يصل إلى مسار أو معامل مسار أو url(). وحين لا يبقى من اسم ملفك شيء بعد الاختصار، كما يحدث مع خط-عربي.otf الذي ليس فيه حرف لاتيني واحد، يُستخدم اسم عائلة الخط نفسه بدلًا منه، فيُخزَّن ذلك الملف باسم amiri.otf لا font.otf ثم font-2.otf ثم font-3.otf. أما اسم العائلة نفسه فيأتي من جدول name في الخط حيث يسمح الملف، وإلا فمن اسم الملف، فيقول منتقيك Kitab لا upload-3.

ورفع عدة خطوط في وقت واحد آمن: فتوزيع أسماء الملفات وكتابة الفهرس يجريان واحدًا بعد الآخر لا معًا، ويُكتب الفهرس عبر ملف مؤقت لكل عملية كتابة. (كان رفع أربعة خطوط مختلفة بالتوازي يترك ملفين على القرص، أحدهما موسوم باسم عائلة خط آخر، وثلاثة أخطاء 500، مع أن البايتات كانت على القرص طوال الوقت.)

وتُكتب الخطوط المرفوعة في /api/site-fonts.css كتلَ @font-face عادية مستضافة ذاتيًا، وتتبع قاعدة unicode-range نفسها لكل خانة كالكتالوج: في الخانة العربية يُقصر الخط المرفوع على الكتل العربية، والخط المرفوع في خانة لاتينية بجانب خط عربي تُقتطع منه تلك الكتل. فتبقى المجموعتان منفصلتين، وتعمل المطابقة حرفًا حرفًا مع خطوطك تمامًا كما تعمل مع خطوطنا.

والرفع للمدير وحده (POST /api/fonts/upload؛ والمدير الذي يعاين الموقع العام يُرفض كأي زائر آخر)، وإزالة خط محروسة مرتين: فالخط الذي ما زالت تستخدمه خانة يعرض اسم تلك الخانة بدل زر الحذف، ويرفض الخادم الحذف بـ409 على أي حال.

مطابقة حجم العربي

تحمل مدخلات الكتالوج العربية size-adjust مقيسًا، أما الخط المرفوع فلا يمكنه ذلك. لذلك حين يُختار خط عربي يظهر في التبويب عنصر تحكم إضافي، نسبة مئوية بوحدتها داخل الحقل، تحل محل تعويض الحجم لأي شيء في الخانة العربية، من الكتالوج كان أو مرفوعًا. وتضبطه بالعين على النموذج الذي يعلوه بصفّين، وهذه هي الطريقة الوحيدة التي يُضبط بها هذا الرقم حقًّا. ويُخزَّن باسم settings.fonts.arabicSizeAdjust (من 50 إلى 300؛ وغيابه يعني قيمة الكتالوج نفسه، أو لا تعديل).

مخرج الطوارئ، كما هو

ولكل ما لا يغطيه الكتالوج ولا الرافع (خط متغيّر تريد التحكم فيه بمحور مخصص، أو طقم خاص بنظام كتابة بعينه، أو خط تفضّل أن تربطه بيدك): ضع الملف في ASTROLABE_DATA/fonts/ وسمّه من custom.css تمامًا كما هو مبيّن في السمات. وتُحمَّل تلك الورقة بعد الورقة المولَّدة، فقاعدة custom.css على :root تغلب الكتالوج والخطوط المرفوعة والإعدادات الافتراضية جميعًا.

حرّر هذه الصفحة على GitHub

أسطرلاب برنامج حر. هذه الصفحات مبنية من ملفات Markdown في مجلد docs بالمستودع.