الإعداد
كل مفتاح في ملف .env، ولوحة الإعدادات داخل التطبيق، وأيّهما يغلب حين يقول كلٌّ منهما شيئًا مختلفًا.
يُضبط أسطرلاب من مكانين، ويكاد المكانان يغطّيان الأمور نفسها.
- ملف
.env. ملف نصيّ بسيط بجانب التطبيق، في كل سطر منه مفتاح وقيمته على هيئةKEY=value. يقرؤه الخادم مرةً واحدة عند تشغيله، فإذا غيّرت شيئًا فيه فلا بد أن تعيد تشغيل الخادم ليأخذ به. - لوحة الإعدادات. وهي داخل التطبيق نفسه. حين تغيّر شيئًا فيها يكتبه الخادم في ملف اسمه
settings.jsonداخل مجلد بياناته، ويسري التغيير فورًا، بلا إعادة تشغيل.
معظم الإعدادات موجودة في المكانين معًا. فإذا اختلفا غلبت لوحة الإعدادات: القيمة المحفوظة في اللوحة تتقدّم على القيمة نفسها في .env. وإذا مسحت الحقل من اللوحة عادت قيمة .env إلى العمل. وثمّة استثناء واحد: المفاتيح الحسّاسة أمنيًّا (كلمة المرور، وسرّ الجلسة، والمنفذ، ونحوها) تعيش في .env وحده، ولا تعرضها اللوحة ولا تغيّرها أبدًا.
تحديث خادم تشغّله بنفسك
يقرأ الخادم إصداره من package.json، ويحمل العميل الإصدار الذي بُني به. بعد git pull شغّل
npm run build ثم أعد التشغيل: السحب يحرّك الإصدار، والبناء يحرّك الملفات. إذا بقي تبويب مفتوحًا
بعد نشر جديد قال مرةً واحدة: أسطرلاب X صار على الخادم، أعد التحميل لتلحق به. وإذا أعادت إعادةُ
التحميل النسخةَ القديمة نفسها — لأن الملفات لم يُعَد بناؤها، أو لأن عامل الخدمة ما زال يقدّم الواجهة
القديمة — قال التطبيق ذلك بدلًا منها، مرةً لكل إصدار، وكفّ عن السؤال: يقول الخادم إنه أسطرلاب X لكنه
يقدّم نسخة Y. ولهذا السطر معنى واحد: شغّل npm run build (أو أعد تثبيت الحزمة) على الجهاز الذي
يشغّل الخادم. أما تطبيق الحاسوب وتطبيق أندرويد فيحملان بناءهما مع خادمهما، فلا يُظهرانه أبدًا.
متغيرات البيئة
متغيّر البيئة قيمة لها اسم، يقرؤها الخادم عند تشغيله. يمكنك أن تضعها في ملف .env، أو في سطر الأوامر (الطرفية) الذي تشغّل الخادم منه؛ وفي الحالين تصل إلى المكان نفسه.
سكربتات npm تحمّل ملف .env من تلقاء نفسها (عبر node --env-file-if-exists=.env)، فلست بحاجة إلى export ولا إلى source. أما ملف .env.example في جذر المستودع فيسرد كل المفاتيح مع تعليق يشرح كل واحد منها؛ والجدول التالي هو النسخة المختصرة.
| المفتاح | ما هو |
|---|---|
PORT | المنفذ الذي يستمع عليه الخادم (الافتراضي 6801) |
HOST | العنوان الذي يستمع عليه الخادم (الافتراضي 0.0.0.0، أي كل واجهات الشبكة). إذا استمع الخادم على غير الجهاز المحلي ولم تكن هناك كلمة مرور، طبع تحذيرًا صارخًا عند التشغيل: كل من يصل إلى المنفذ يصير مشرفًا |
ASTROLABE_VAULT | مجلد الخزانة، أي المجلد الذي يحوي ملاحظاتك (الافتراضي ./vault). والمعامل --vault <path> في سطر الأوامر يتقدّم عليه |
ASTROLABE_DATA | مجلد بيانات الخادم (الافتراضي ./data). فيه settings.json، وقاعدة بيانات التعليقات (SQLite)، وملفك custom.css، وdesigns.json، وملف اعتمادات git، ورمز القصّاصة (clip-token)، ومجلد fonts/ (ملفات خطوطك، مع نسخة الكتالوج المحفوظة في fonts/catalog/ والخطوط المرفوعة في fonts/custom/)، وversions/ (تاريخ الملاحظات)، وauthor-sites.json، والدفاتر الثلاثة التي هي لك لا للجهاز: layouts.json وbooks.json وannotations.json. وستة من هذه الملفات، وهي settings.json وdesigns.json وcustom.css وlayouts.json وbooks.json وannotations.json، ومعها مجلد fonts/، تُنسخ إلى <vault>/.astrolabe/، وهو مجلد نقطي لا يعرضه أوبسيديان أبدًا، فيبدأ منها خادم ثانٍ فوق الخزانة نفسها (انظر الإعدادات تسافر مع الخزانة) |
ADMIN_PASSWORD_HASH | كلمة مرور المشرف، مخزّنةً على هيئة تجزئة argon2id، أي بصمة يستطيع الخادم أن يتحقق بها من كلمة المرور ولا يمكن استرجاع كلمة المرور منها. يصنعها لك الأمر npm run hash-password. وإذا لم يُضبط هذا المفتاح عمل التطبيق في الوضع المحلي المفتوح: لا كلمة مرور، والكل مشرف |
SESSION_SECRET | نصّ طويل عشوائي يوقّع به الخادم ملفات تعريف الارتباط (الكوكيز) التي تثبت أنك سجّلت دخولك. وإذا لم يُضبط اخترع الخادم سرًّا جديدًا عند كل تشغيل، فيُخرجك كل إعادة تشغيل من حسابك |
PUBLIC | القيمة false تطلب تسجيل الدخول حتى للقراءة (الافتراضي: القراءة للجميع، والتحرير لمن سجّل دخوله). يرفض الخادم أن يبدأ إذا ضُبط PUBLIC=false من غير ADMIN_PASSWORD_HASH |
SECURE_COOKIES | true أو false لفرض علامة Secure على ملف الجلسة. وإذا لم يُضبط قرّر الخادم من الطلب نفسه: HTTPS يأخذ العلامة، وHTTP العادي لا يأخذها (ويمكن لوكيل موثوق أن يقول «هذا HTTPS» عبر الترويسة X-Forwarded-Proto) |
TRUSTED_PROXIES | عناوين IP، أو نطاقات عناوين بصيغة CIDR، مفصولة بفواصل، يُصدَّق ما تقوله ترويستاها X-Forwarded-For وX-Forwarded-Proto (مثل 127.0.0.1,::1). وإذا لم يُضبط تُتجاهل الترويستان، ويُحسب حدّ المحاولات على عنوان الاتصال نفسه |
HOME_NOTE | الملاحظة التي يهبط عليها الزائر أول مرة، مسارًا داخل الخزانة، مثل index.md |
COMMENTS | القيمة on (وكذلك true و1 وyes) تسمح للقرّاء بترك تعليقات تحت الملاحظات المنشورة (الافتراضي: معطَّل) |
NOTE_VERSIONS | القيمة off (وكذلك false و0 وno) توقف احتفاظ التطبيق بنسخة من كل ملاحظة قبل كل حفظ في ASTROLABE_DATA/versions/ (الافتراضي: مفعَّل)؛ انظر النسخ، قبل git وإلى جانبه |
PDF_SEARCH | القيمة off (وكذلك false و0 وno) تمنع بحث الشريط الجانبي من قراءة نصوص ملفات PDF على رفّك (الافتراضي: مفعَّل؛ انظر البحث داخل كل كتاب) |
SPEAK_EXTERNAL | القيمة on (وكذلك true و1 وyes) تسمح للمدير بضبط المتحدّث الخارجي في القراءة بصوت عالٍ، وهو برنامج يشغّله الخادم بمستخدمه نفسه (الافتراضي: معطَّل، فلا يُحفظ أمر، ولا يُشغَّل أمر حُفظ من قبل). في .env وحده — فهو قرار مشغّل الجهاز لا قرار من يملك كلمة مرور المدير. وتطبيق سطح المكتب مشغّلُ نفسه فيفعّله |
OLLAMA_HOST | أين يجد اسأل الخزانة برنامج Ollama، وهو المتغير نفسه الذي يقرؤه Ollama (الافتراضي http://127.0.0.1:11434) |
SITE_NAME | اسم الموقع، يظهر في الشريط الجانبي وعناوين الصفحات ونافذة تسجيل الدخول (الافتراضي Astrolabe) |
SITE_TAGLINE | سطر قصير تحت اسم الموقع، في وضع المدونة |
SITE_FOOTER | سطر التذييل في وضع المدونة. يُملأ فيه {year} و{siteName} تلقائيًّا (الافتراضي © {year} {siteName}) |
SITE_URL | العنوان العام للموقع، لروابط RSS والروابط القانونية، مثل https://notes.example.com. وإذا لم يُضبط استُنتج من كل طلب. في .env وحده؛ لا حقل له في اللوحة |
LEGACY_HOSTS | أسماء المضيفين القديمة التي كان الموقع يجيب عليها، مفصولةً بفواصل. الطلب الذي يصل على أحدها يُحوَّل تحويلًا دائمًا إلى المسار نفسه على SITE_URL، فتبقى الروابط القديمة تعمل بعد تغيير الاسم. يحتاج إلى SITE_URL؛ وفي .env وحده |
DEFAULT_THEME | السمة التي يراها الزائر قبل أن يختار واحدة: أيّ من السمات الست والأربعين المدمجة، أو custom:<name> لسمة بنيتَها أنت (انظر السمات)، أو follow. وتركه فارغًا يعني follow: يأخذ الزوار السمة التي تحرّر أنت فيها. لا فرق بين الحروف الكبيرة والصغيرة؛ والاسم المجهول يُتجاهل مع سطر واحد على stderr |
EXCLUDE_TAGS | وسوم مفصولة بفواصل تُخفى من قوائم المواضيع وحبوب الوسوم في الموقع العام، وهي عادةً وسوم سير العمل مثل draft,seedling. لا فرق بين الحروف الكبيرة والصغيرة، ولا بأس بعلامة # في أول الوسم. ولا يتأثر بها ما يراه المشرف نفسه |
PUBLIC_LAYOUT | ما يراه الزائر: blog لتخطيط مدونة تقليدي (انظر وضع المدونة)، أو designed لصفحة رئيسية تركّبها بنفسك (انظر المصمم)، وأي قيمة أخرى تعني app، أي التطبيق للقراءة فقط (وهو الافتراضي) |
SITE_LANG | لغة الموقع: en (الافتراضي) أو ar. ومع ar تصير كل نصوص الواجهة عربية وتنعكس الواجهة كلها من اليمين إلى اليسار (انظر العربية والكتابة من اليمين). أما اللغة التي تحرّر أنت بها فاختيار مستقل، لكل متصفح على حدة: الإعدادات ← اللغة ← لغتك |
BLOG_LOCALE | رمز لغة ومنطقة (بصيغة BCP47، مثل ar-EG أو en-GB) يقرّر شكل الأرقام في تواريخ التدوينات ولغة خلاصة RSS (الافتراضي: يتبع SITE_LANG). وتتبع أسماءُ الشهور لغةَ الواجهة حين يكون مبدّل لغة الزائر مفعَّلًا |
LANGUAGE_FILTER | أي الملاحظات المنشورة يعرضها الموقع العام، بحسب اللغة المكتوبة بها: off (الافتراضي: اعرض الكل) · follow (كل قارئ يرى لغته) · ar · en. والقيمتان القديمتان true وfalse ما زالتا تعملان؛ انظر مرشّح اللغة |
ATTACHMENTS_DIR | مجلد الخزانة الذي تُحفظ فيه الملفات المرفوعة من داخل التطبيق (الافتراضي Attachments، أو مرفقات في الموقع العربي؛ ومجلد attachments الموجود أصلًا يبقى على حاله). يُنشأ عند أول حاجة إليه. ويستطيع إعداد المرفقات أن يرسل المرفوعات إلى مكان آخر تمامًا؛ انظر المرفقات |
BANNER_FALLBACK | صورة الترويسة لتدوينات المدونة التي ليس لها banner: خاص بها: generated (الافتراضي: تدرّج لوني تجريدي يُصنع من عنوان الملاحظة، ويظل هو نفسه للعنوان نفسه) أو none |
ASTROLABE_GIT_SSH_COMMAND | المتغيّر الوحيد من عائلة GIT_* الذي يمرّره أسطرلاب إلى git كما هو، باسم GIT_SSH_COMMAND؛ انظر النسخ الاحتياطي والمزامنة |
إن كنت ثبّتّه حين كان اسمه Vellum. كل مفتاح أعلاه ما زال يجيب بتهجئته القديمة: يُقرأ VELLUM_VAULT وVELLUM_DATA وسائرها حين لا يكون مفتاح ASTROLABE_* مضبوطًا، فيظل ملف .env أو وحدة systemd أو اختصار الصدفة الذي كُتب قبل إعادة التسمية يعمل. وحين يُضبط الاثنان تغلب التهجئة الجديدة، ويسمّي سطر التشغيل المفاتيح القديمة التي اعتمد عليها، مرة واحدة. وما زال /vellum.sty يُقدَّم بجانب /astrolabe.sty للأوراق المكتوبة على اسم الحزمة القديم.
حدود حجم الطلبات. لكل طلب يصل إلى الخادم حدٌّ أقصى للحجم، يُفرض قبل أن يقرأه أي شيء، ولا مفتاح له: 10 ميغابايت على أي طلب إلى /api، وحدّ أضيق كثيرًا هو 64 كيلوبايت على الشيئين اللذين يستطيع الزائر المجهول إرسالهما (التعليقات ومحاولات تسجيل الدخول). وكل ما يتجاوز الحدّ يُرفض برمز الخطأ HTTP 413 (أي «الطلب أكبر من المسموح») بدل أن يشغل الذاكرة. وللملفات المرفوعة حصّتها المستقلة. وإذا كان التطبيق خلف وكيل فإن حدًّا مماثلًا عند الوكيل طبقةُ حماية إضافية معقولة؛ في nginx مثلًا: client_max_body_size 10m;، أو 256m إن كنت ستُسقط أفلامًا في ملاحظاتك، لأن لرفع الفيديو حصّته الخاصة: 256 ميغابايت.
لوحة الإعدادات
معظم مفاتيح هوية الموقع أعلاه يمكن تغييرها أيضًا أثناء التشغيل، من التطبيق: لا تحرير لـ.env ولا إعادة تشغيل. بوصفك مشرفًا افتح الإعدادات (المسنن في العنقود العلوي، أو من لوحة الأوامر). شريطها الجانبي على مستويين: أربع مجموعات — أنت وموقعك والبيانات والتطبيق — كلٌّ منها عنوانٌ فوق صفحات قصيرة، سُمّيت بما جئت لتفعله لا بمكان حفظ القيمة. تجيب الصفحة عن سؤال واحد، وتفتح باسمها وجملة واحدة تقول ما تقرّره، ولا تعرض أكثر من عشرة صفوف قبل سطر متقدّم. ومربع البحث فوق الشريط يجد أي صف باسمه، أو بسطر مساعدته، أو بالفقرة خلف ⓘ، أو بمتغير البيئة الذي وراءه، ويأخذك إليه أينما كان. وعلى الهاتف تظهر المجموعات الأربع نفسها قوائمَ معنونة، وكل صفحة شاشة مستقلة.
صف واحد، وشكل واحد. كل صف عنوانٌ، وسطر مساعدة واحد تحته، وأداة واحدة في عمود واحد على اليسار (وعلى اليمين في الإنجليزية): مفتاح، أو مجموعة أزرار، أو قائمة، أو صفّ من الشرائح المسمّاة، أو منزلق قيمته في العنوان (دفء الشاشة · 30%)، أو حقل مسار فيه اختر…، أو حقل نص، أو — للصفوف القليلة التي هي جداول — عرض الصف كله. ولا يُكتب بجانب المفتاح «مفعل» أو «معطل»: العنوان يقول ما يعنيه التشغيل. وتفتح ⓘ بجانب العنوان فقرةً تحت الصف تقول لماذا قد تغيّره، ومتغيّر البيئة حين يكون وراءه، جاهزًا للنسخ.
محفوظ، أو مُبقًى هنا. الصف المحفوظ في هذا المتصفح يحفظ نفسه لحظة تختار. والصفحة المكوّنة كلها من هذه الصفوف (المظهر، وهذا الجهاز) تقول ذلك مرة واحدة تحت جملتها؛ وفي غيرها تحمل الصفوف القليلة التي هي كذلك وسمًا صغيرًا هذا الجهاز. وكل صف آخر هو للموقع، ويرتفع شريط حفظ أسفل اللوحة حالما يتغير أحدها (ومعه تجاهل)، ويختفي حين تحفظ.
أنت
- المظهر: سمتك ومنزلقا راحة العين (انظر السمات)، وعلى أي حافة تجلس لوحة الملاحظات، وعرض عمود الكتابة. وكلها محفوظة على هذا الجهاز.
- التخطيط والخط: اتجاه نص الملاحظات ومحاذاته، وتستطيع أي ملاحظة تجاوزهما من مقدمتها (انظر اتجاه الملاحظة ومحاذاتها)، وخانات الخطوط الأربع (نص القراءة / الواجهة / الكود / الوجه العربي) من فهرس مختار مستضاف ذاتيًا أو من خطوط ترفعها بنفسك، مع عيّنة حية تبقى على الشاشة وأنت تختار (انظر الطباعة).
- اللغة: لغتك (تبعًا للموقع / English / العربية: كلمات التطبيق لك على هذا الجهاز، وليست أبدًا ما يأخذه الزوار) بجانب لغة الموقع (ما يقرأ به الزوار)؛ والتدقيق الإملائي في: صفّ واحد من الشرائح يسمّي اللغات التي تُسلَّم أسطرها إلى المدقّق الإملائي، ففي المتصفح اللغاتُ الأربع التي يعرفها المحرر، ولا شيء منها حتى تختار، وفي تطبيق سطح المكتب القواميس الموجودة فعلًا على حاسوبك (انظر المحرر)؛ وللزوار: مرشح اللغة ومفتاح الزائر الاختياري.
- التواريخ والتقويم: تقويم التاريخ (ميلادي / هجري / كلاهما، مع نموذج حي لليوم، ومع كلاهما أيهما يتقدّم والعلامة بينهما؛ انظر التواريخ الهجرية)؛ وتحت متقدّم: لغة التواريخ.
- الكتابة: افتح عند التشغيل (على ماذا يفتح التطبيق: حيث توقفت، أو صفحة السِّجِلّ، أو رفّ المدارات، أو ملاحظة اليوم، أو ملاحظة تختارها؛ فوق الجلسة المستعادة، ولا يفتح أبدًا فوق رابط ملصوق)، وشريط التنسيق، وتصحيح الفرنسية تلقائيًا، وبطاقة الخصائص (إيقافها يخفيها عمّا تراه أنت — ويبقى الزوار يرونها؛ انظر المحرر) ومعها بطاقة الملاحظة الفارغة؛ وأين تُكتب المرفقات الجديدة (انظر المرفقات)، ومجلد الوسوم، وجدول تسميات الوسوم: أسماء عرض للوسوم الأصلية، لواجهة ينبغي أن تقرأ «برمجيات» فوق خزانة تحتفظ بـ
#software(انظر تسميات الوسوم المحلية)؛ وتحت متقدّم: مجلد الرسوم. - الملاحظات الجديدة والقوالب: مجلد القوالب وقالب الملاحظات الجديدة، والملاحظات الدورية (جدول واحد: المجلد الذي تتشاركه الأنواع الأربعة، واسمٌ وقالبٌ لكلٍّ من اليوم والأسبوع والشهر والسنة)، ومجلد الملاحظة الفريدة واسمها، وصندوق الالتقاط والقصّاصة.
- القراءة: ترقيم العناوين في عرض القراءة، والبحث داخل الكتب (البحث في PDF)، والخلاصات مع الملاحظة التي تسردها؛ وتحت متقدّم: مجلد الأحاديث (الملاحظات التي تجيب تنبيهات
> [!hadith]؛ انظر تنبيهات الآية والحديث). - القراءة بصوت عالٍ والملاحظات الصوتية: القراءة بصوت عالٍ وهل يستمع قرّاء مدونتك؛ ولغة تفريغ الملاحظات الصوتية، والنموذج وأين يعمل، وهل تُحفظ التسجيلات (انظر الالتقاط)؛ وتحت متقدّم: أصواتك الخاصة.
موقعك
- هوية الموقع: الاسم، والعنوان الفرعي، وصورة شعار (تحل محل الاسم النصي في الشريط الجانبي وترويسة المدونة)، وأيقونة (تُقدَّم على
/favicon.icoبنوع محتواها الحقيقي وتُحقن في<link rel="icon">في كل صفحة)، والسمة الافتراضية التي يصل إليها الزوار، وأجواء الترويسة؛ وتحت متقدّم: سطر التذييل. - النشر: كم من الموقع عام، بالأرقام في أعلى الصفحة؛ والتخطيط العام (
app/blog/designed، وتحته باب المصمّم)؛ والصفحة الرئيسية: وضعnoteالكلاسيكي بملاحظة رئيسية تختارها، أو تخطيط المجلةdashboard، مع لافتة اختيارية (لا يقرؤها إلا تخطيطاblogوdesigned، فمعالتخطيط العام: appتبهت الصفحة هذه الصفوف وتقول ذلك)؛ وأزرار المشاركة والفيديو الخارجي؛ وتحت متقدّم: الوسوم المستبعدة ومواقعك الأخرى. - التعليقات والإشارات: التعليقات، وإشارات الويب والفيديفيرس، كلٌّ منها معطّل حتى تشغّله.
- المجموعات: هل تأتي الفئات من الوسوم أم من المجلدات، ومجموعاتك المصنوعة بيدك وأين تجلس. انظر وضع المدونة.
- المكتبة: الرفّ العام: تشغيله أو إيقافه، واسمه، وأين بابه، وأي المجلدات تملؤه والاستثناءات. انظر المكتبة.
البيانات
- النسخ الاحتياطي والمزامنة: أودع الخزانة وادفعها إلى مستودع git خاص تملكه، يدويًا أو على مؤقت (معطّل حتى تشغّله)؛ وتحت متقدّم: الفرع والسحب أولًا. انظر النسخ الاحتياطي والمزامنة.
- النسخ السابقة والتنقّل: نسخة من كل ملاحظة قبل كل حفظ؛ وما يحمله مجلد
.astrolabe/في الخزانة إلى الجهاز التالي؛ وهل تنتقل تفضيلات هذا المتصفح معها. - اسأل: أي النماذج تقرأ الملاحظات وتجيب عنها، ونموذج التضمين وعدد المقاطع لكل إجابة تحت متقدّم. انظر اسأل الخزانة.
التطبيق
- هذا الجهاز: النسخة دون اتصال مما تفتحه، ومفاتيح Vim (مع أرقام الأسطر النسبية)، وعرض «ما الجديد» بعد التحديث، وفي تطبيق سطح المكتب وحده اسمه وأيقونته ومدخل المشغّل وتحديثات البرنامج (انظر تطبيق سطح المكتب). وكلها محفوظة على هذا الجهاز.
- حول: الإصدار، وإصدار Node، وأعداد الخزانة، والمسارات المطلقة للخزانة ومجلد البيانات و
settings.jsonومجلد الخطوط المرفوعة.
وخزانة الجيب (مستودع GitHub مفتوح في تطبيق أندرويد) تعرض أربع عشرة صفحة: فالنشر والتعليقات والإشارات والمجموعات والمكتبة واسأل تحتاج خادمًا، والصفوف التي لا تستطيع حفظها تُرسم باهتة، مع سطر واحد يقول لماذا.
حقول الصور تعيد استخدام آلية اللافتات: اختر من مرفقات الخزانة أو ارفع هناك مباشرة (سحب وإسقاط؛ تُشمّ البايتات؛ وتحطّ حيث يشير إعداد المرفقات).
المرفقات
المرفق أي ملف تضعه في الخزانة وليس ملاحظة: صورة، أو ملف PDF، أو مقطع صوتي. وأين تذهب المرفقات الجديدة إعداد سُمّي كما يسمّيه أوبسيديان (الموقع الافتراضي للمرفقات الجديدة)، فتتصرّف الخزانة المنقولة من أوبسيديان كما يتوقّع صاحبها أصلًا. يعيش هذا الإعداد في الإعدادات ← الكتابة ← المرفقات الجديدة، بجانب مجلد القوالب ومجلد الوسوم.
| الوضع | يحطّ الرفع في |
|---|---|
| جذر الخزانة | أعلى الخزانة |
| المجلد نفسه للملاحظة | بجانب الملاحظة التي تُحرَّر |
| مجلد فرعي من مجلد الملاحظة | <مجلد الملاحظة>/<الاسم>، مثل assets بجانب كل ملاحظة |
| مجلد محدد (الافتراضي) | مجلد ثابت واحد نسبي إلى الخزانة: ATTACHMENTS_DIR، وإلا مرفقات (وAttachments في النسخة الإنجليزية)؛ والخزانة التي فيها مجلد attachments أصلًا تبقى عليه |
ولا يقرّر هذا الإعداد إلا في الرفع الذي لم يسمِّ مكانًا بنفسه: صورة لُصقت في ملاحظة، أو ملف أُسقط في المحرر. أما الملف الذي يُسقط على مجلد في شجرة الشريط الجانبي فقد سمّى مكانه بنفسه، ويحطّ في ذلك المجلد.
ويُفحص المجلد الذي تكتبه كما يُفحص كل مسار في الخزانة: يجب أن يبقى داخل الخزانة، ولا يجوز أن يكون مجلدَ نقطة (أي مجلدًا يبدأ اسمه بنقطة .، فالشجرة والمفهرس ومراقب الملفات تتجاهل تلك المجلدات كلها)، ويُنشأ عند أول حاجة إليه. والمرفقات الموجودة عندك لا تُنقل أبدًا. يقرّر الإعداد أين يذهب الرفع التالي، وتبقى التضمينات القديمة تعمل لأن الملاحظة تجد صورها باسم الملف، أيًّا كان المجلد الذي تعيش فيه.
وكل طرق الرفع تطيع هذا الإعداد: اللصق أو الإسقاط في المحرر، والإسقاط على شجرة الشريط الجانبي، وزر الرفع في أي منتقٍ. وتُعدّ لافتة الملاحظة وغلاف عمل في صفحة الوسائط رفعًا في تلك الملاحظة، فتحت الوضعين المجلد نفسه والمجلد الفرعي تحطّ الصورة بجانب الملاحظة (أو ملاحظة المتتبّع) التي تخصّها. أما منتقيات الموقع كله، لافتة الرئيسية والشعار وأيقونة الموقع، فلا ملاحظة لها، وتُقاس من جذر الخزانة. وللخطوط (ASTROLABE_DATA/fonts) ولملف custom.css بيتاهما الخاصان، ولا يتأثران.
أي ملف يمكن أن تحويه الخزانة، لا الصور وحدها. يقبل POST /api/upload الصور (png وjpeg وwebp وgif وsvg وavif وheic وbmp)، وملفات PDF، والصوت (mp3 وm4a وwav وogg وoga وopus وflac)، والفيديو (mp4 وm4v وmov وwebm وmkv وogv). يصل الفيلم إلى 256 ميغابايت ويُكتب على القرص وهو يصل، وسائر الملفات بحدّ 10 ميغابايت لكل ملف. ويُفحص محتوى الملف، فالبرنامج الذي أُعيدت تسميته إلى .png يُرفض مهما ادّعى امتداده. وكل ما ليس في تلك القائمة يُرفض في المتصفح، قبل أن يبدأ الرفع، برسالة تسمّي ما رُفض وما كان سيُقبل.
أسقط الملفات في أي مكان على الشجرة. اسحب ملفات من مدير الملفات إلى مجلد في الشريط الجانبي (أو إلى ملاحظة، فتحطّ بجانبها) فتُضاف إلى الخزانة. يضيء الصف ويقول كم ملفًا في الطريق. وبعدها يسمّي تنبيهٌ المجلدَ الذي حطّت فيه فعلًا ويعرض تراجعًا ينقلها إلى .trash/. وإذا كان الاسم مشغولًا أخذ الملف الجديد أول اسم حرّ على هيئة name-2.ext، وقال التنبيه ذلك.
والحذف يخبرك بما يأخذه حقًّا. تعرض شجرة الشريط الجانبي الملاحظات فقط. لذلك كان المجلد الذي بقيت فيه أربع صور بعد أن غادرته ملاحظته يصف نفسه بـ«0 ملاحظات»، وكان حذفه يكسر مقالةً منشورة في صمت. أما الآن فكل تأكيد حذف يسأل الخادم عمّا في الداخل فعلًا:
نقل "Media" إلى .trash؟ 0 ملاحظات، 60 مرفقًا، 53 منها تشير إليها 48 ملاحظة. ينتقل كل ذلك إلى مجلد .trash في الخزانة، قابلًا للاسترداد من القرص.
وحين تكون الملاحظات التي تشير إلى الملفات قليلة تُذكر بأسمائها. ولا تُحسب كسرًا إلا الملاحظات التي تنجو من الحذف؛ فالملاحظة التي تذهب في الحذف نفسه ليست رابطًا مكسورًا. ويُحسب نوعا الروابط معًا، تضمينات الويكي (![[fig.png]]) وروابط ماركداون ()، ومعهما banner: الملاحظة. ويكرّر تأكيدُ الحذف النهائي الجردَ نفسه، وحذف مرفق واحد (علامة × على صف في قائمة منتقي اللافتة) يسأل السؤال نفسه.
وكل عنصر تحكّم في اللوحة يرسمه أسطرلاب، لا نظام التشغيل. فالقائمة المنسدلة نافذة منبثقة بسمة التطبيق، معلّقة بزرّها ومحفوظة داخل اللوحة: لا يزيد ارتفاعها على المساحة المتاحة، وتنقلب إلى الأعلى حين لا مكان تحتها، وتستجيب لمفاتيح الأسهم وللكتابة (اكتب أول الاسم فتقفز إليه)، وEnter يثبّت وEsc يعيد القيمة القديمة. ومفاتيح التشغيل والإيقاف مفاتيح حقيقية تُقلب بنقرة؛ والصفوف الثلاثية (وراثة / تشغيل / إيقاف) تعرض حالاتها الثلاث معًا؛ والأرقام تحمل وحدتها داخل الحقل. والسبب أن عنصر <select> الأصلي يفتح نافذة يرسمها نظام التشغيل، لا تصل إليها سمة ولا تحتويها لوحة، وهذا بالضبط ما يجب ألا تفعله قائمة خطوط من سبعة وعشرين وجهًا.
على الهاتف (تخطيط الهاتف) اللوحة قائمة بالأقسام التسعة نفسها، بالترتيب نفسه وبالأسماء نفسها — المزيد ← الإعدادات — وفوقها البحث نفسه، وكل قسم شاشة مستقلة فيها الصفوف نفسها. وحالما يحمل القسم تغييرًا يصعد شريط من الأسفل فيه تجاهل وحفظ؛ ومغادرة القسم بأي طريق آخر وفيه تغييرات لم تُحفظ تسأل أولًا. أما الصف الموسوم هذا الجهاز فيحفظ نفسه حين تختار، ولا يرفع الشريط أبدًا.
مفاتيح الإعدادات
هذه هي المفاتيح التي يمكن أن يحملها ASTROLABE_DATA/settings.json. تكتبها اللوحة، ويكتبها كذلك PATCH /api/settings. وكل مفتاح غائب يعود إلى قيمته الافتراضية من .env في الجدول أعلاه.
| المفتاح | القيم | الافتراضي |
|---|---|---|
siteName | نص، ≤ 80 حرفًا | SITE_NAME، وإلا Astrolabe |
tagline | نص، ≤ 160 | SITE_TAGLINE، وإلا لا شيء |
footer | نص، ≤ 200 | SITE_FOOTER، وإلا © {year} {siteName} |
defaultTheme | أحد المعرّفات الست والأربعين، أو custom:<name> لسمة موجودة، أو follow (يتبع الزوار سمة محررك) | DEFAULT_THEME، وإلا follow |
adminTheme | معرّف سمة واحد، يكتبه التطبيق لا اليد: سمة محررك أنت، تُنسخ من متصفحك ليجد follow ما يقدّمه | لا شيء حتى تختار سمة |
publicLayout | app · blog · designed | PUBLIC_LAYOUT، وإلا app |
blogLocale | رمز لغة ومنطقة (BCP47)، ≤ 35 حرفًا، يُوحَّد شكله عند الحفظ | BLOG_LOCALE، وإلا ar حين تكون اللغة عربية، وإلا en |
language | en · ar | SITE_LANG، وإلا en |
languageFilter | off · follow · ar · en | LANGUAGE_FILTER، وإلا off |
languageToggle | منطقي: مبدّل EN/ع العام. لا نظير له في البيئة | false |
topics | tags · folders: من أين تأتي فئات الموقع العام (الإعدادات ← المجموعات) | tags |
excludeTags | مصفوفة نصوص، ≤ 200 مدخل، ≤ 50 حرفًا لكل منها | EXCLUDE_TAGS، وإلا فارغة |
commentsEnabled | منطقي | COMMENTS، وإلا false |
noteVersions | منطقي: الاحتفاظ بنسخة من كل ملاحظة قبل كل حفظ (الإعدادات ← النسخ الاحتياطي والمزامنة) | NOTE_VERSIONS، وإلا true |
shareButtons | منطقي: صف المشاركة تحت مقالات المدونة | true |
authorSites | مصفوفة { url } (https)، يجلب الخادم عنوان كل موقع منها وصورته مرة واحدة (من بطاقة OpenGraph الخاصة به) ويحفظهما في ASTROLABE_DATA/author-sites.json؛ تُعرض على المدونة بطاقاتٍ تحت المزيد من الكاتب. لا نظير له في البيئة | فارغة |
ambient | منطقي: حركة زخرفية بطيئة خلف ترويسة الموقع العام، مرسومة لكل سمة على حدة (انظر السمات) | false |
pdfSearch | منطقي: يقرأ بحث الشريط الجانبي صفحات كل ملف PDF على الرف (انظر البحث داخل كل كتاب) | PDF_SEARCH، وإلا true |
externalVideo | منطقي: رابط YouTube أو Vimeo أو PeerTube في سطر مستقل يعمل في مكانه، في التطبيق وعلى المدونة (الإعدادات ← النشر ← تضمين الفيديو الخارجي؛ انظر التضمين). لا نظير له في البيئة | false |
feeds | { fetch, note }: الخلاصات: هل يجوز للخادم أن يجلب الخلاصات التي تتابعها (الإعدادات ← القراءة ← الخلاصات)، والملاحظة التي تسردها | fetch: false، وnote: Feeds.md |
voice | { model, backend, language, keepAudio }: الملاحظات الصوتية: نموذج التفريغ (base-q5_1 · small-q5_1 · large-v3-turbo-q5_0 · large-v3-turbo · off)، وأين يعمل (auto · cpu أي المعالج وحده)، واللغة (auto · ar · en)، وهل يُحتفظ بالتسجيل | small-q5_1، auto، auto، true |
speak | { engine, rate, voices, public }: القراءة بصوت عالٍ: المحرّك (light · natural)، والسرعة (0.8 · 1 · 1.2)، والصوت المختار لكل لغة، وهل يستمع قرّاء المدونة. ويُقبل هنا مفتاحان فرعيان آخران، voicesDir (مجلد أصواتك الخاصة) وexternal ({ command, langs }، المتحدّث الخارجي)، لكنهما يُكتبان في ASTROLABE_DATA/speak-local.json لا في settings.json أبدًا: فهما يسمّيان مسارات هذا الجهاز وبرامجه، ولا يسافران | light، 1، أول صوت في كل محرّك، false |
webmentions | { accept, send }: إشارات الويب: استقبالها إلى المراجعة، وإخبار المواقع التي تربط إليها التدوينة حين تُنشر (الإعدادات ← التعليقات والإشارات ← إشارات الويب). لا نظير له في البيئة | كلاهما false |
fediverse | { enabled, handle }: المدونة حسابًا واحدًا في الفيديفيرس، والاسم الذي قبل @ (من 1 إلى 30 حرفًا أو رقمًا أو شرطة سفلية). لا نظير له في البيئة | enabled: false؛ والاسم هو اسم الموقع مطويًّا إلى تلك الحروف، وإلا blog |
ask | { provider, chatModel, anthropicModel, embedModel, topK }: اسأل الخزانة: من يجيب (ollama · anthropic)، وأسماء النماذج، وعدد المقاطع التي تقرؤها الإجابة (2–12). ومفتاح Anthropic ليس هنا: فهو للكتابة فقط ويعيش في ASTROLABE_DATA/ask-credentials.json الذي لا ينتقل أبدًا | ollama وqwen3.5:9b وclaude-sonnet-5 وembeddinggemma و6 |
favicon | صورة نسبية إلى الخزانة (.ico .png .svg .jpg .jpeg .gif .webp .avif) | لا شيء |
logo | رابط https أو صورة نسبية إلى الخزانة | لا شيء |
home.mode | note · dashboard | note |
home.note | ملاحظة نسبية إلى الخزانة (.md / .tex / .latex) | HOME_NOTE |
home.banner | رابط https أو صورة من الخزانة | لا شيء: تدرّج مولَّد من اسم الموقع |
publicFolders | { enabled, nav, home, folders[] }: المجموعات المصنوعة بيدك: هل هي مشغّلة، وباب في شريط التنقل، وشريط في الصفحة الرئيسية، وحتى 12 مجلدًا، لكل منها slug (≤ 60) وtitle (≤ 60) وdescription (≤ 200) وعلامة وراية hidden اختيارية | معطّل؛ home: true |
library | { enabled, nav, home, title, paths[] }: المكتبة: مشغّلة أم لا، وباب في شريط التنقل (مشغّل افتراضيًا متى شُغّلت المكتبة)، ورفّ في الصفحة الرئيسية، واسم (≤ 40)، وحتى 24 مسارًا، كلٌّ منها مجلد في الخزانة له title (≤ 80) وblurb (≤ 300) ونوع | معطّل |
attachments.mode | vault-root · same-folder · subfolder · specified | specified |
attachments.folder | مجلد نسبي إلى الخزانة، ≤ 180 حرفًا؛ يقرؤه الوضعان subfolder وspecified فقط. لا صعود خارج الخزانة، ولا مسار مطلق، ولا مجلد نقطة | ATTACHMENTS_DIR، وإلا مجلد موجود باسم attachments أو Attachments أو مرفقات، وإلا مرفقات (وAttachments في النسخة الإنجليزية) |
templatesFolder | مجلد نسبي إلى الخزانة | يُكتشف تلقائيًّا (Templates أو _templates أو قوالب)، وإلا لا شيء |
hadithFolder | مجلد نسبي إلى الخزانة تجيب ملاحظاته (التي تحمل collection: وnumber: في مقدمتها) تنبيهات > [!hadith] | يُكتشف تلقائيًا (hadith، Corpus/hadith، أحاديث)، وإلا فلا شيء |
drawingsFolder | مجلد نسبي إلى الخزانة يبدأ فيه قلم الشريط الجانبي رسمةً جديدة | لا شيء: جذر الخزانة |
defaultTemplate | ملاحظة نسبية إلى الخزانة تُطبَّق على كل ملاحظة جديدة | لا شيء |
dailyFolder | مجلد نسبي إلى الخزانة تسكنه الملاحظات الدورية؛ "" لجذر الخزانة | daily |
dailyFormat | صيغة فترة تسمّي السنة والشهر واليوم (YYYY وMM وDD و[نص حرفي] و/) | YYYY-MM-DD |
weeklyFormat | صيغة فترة تسمّي السنة وأسبوع ISO (ww)؛ "" يوقف الملاحظات الأسبوعية | YYYY-[W]ww |
monthlyFormat | صيغة فترة تسمّي السنة والشهر ولا شيء أدق؛ "" يوقف الملاحظات الشهرية | YYYY-MM |
yearlyFormat | صيغة فترة تسمّي السنة ولا شيء أدق؛ "" يوقف الملاحظات السنوية | YYYY |
dailyTemplate / weeklyTemplate / monthlyTemplate / yearlyTemplate | ملاحظة نسبية إلى الخزانة تُطبَّق عند إنشاء ملاحظة تلك الفترة | لا شيء (ويعود اليوم إلى defaultTemplate) |
launch | resume · sigils · orbits · today · ملاحظة نسبية إلى الخزانة: على ماذا تفتح واجهة المشرف فوق الجلسة المستعادة (انظر الملاحظات الدورية). لا نظير له في البيئة | resume |
uniqueFolder | مجلد نسبي إلى الخزانة يودع فيه أمر ملاحظة فريدة جديدة ملاحظاته (انظر الملاحظات الفريدة) | لا شيء — جذر الخزانة |
uniqueFormat | اسم الملاحظة الفريدة: رموز اليوميات ومعها HH وmm وss؛ يجب أن يذكر السنة وشيئًا أدق من اليوم | YYYYMMDDHHmm |
captureInbox | ملاحظة نسبية إلى الخزانة تستطيع ورقة الالتقاط السريع أن تضع فيها السطور بدل ملاحظة اليوم | لا شيء؛ ملاحظة اليوم وحدها |
dateCalendar | gregorian · hijri · both | gregorian |
dateOrder | auto · hijri-first · gregorian-first: أي التقويمين يتقدّم في both | auto (بحسب لغة الموقع) |
dateSeparator | bar · dot · parens: ما يفصل بين التاريخين في both | bar |
textDirection | auto · ltr · rtl | auto |
emptyPropsCard | true · false: بطاقة الخصائص ذات السطر الواحد في الملاحظات التي لا مقدمة لها | true |
propsCard | true · false: بطاقة الخصائص أصلًا، في محرر المالك وعرض القراءة عنده (والزوار يرونها دائمًا) | true |
textAlign | start · left · right · center · justify | start |
tagsFolder | مجلد نسبي إلى الخزانة يحمل صفحات الوسوم | يُكتشف تلقائيًّا، وإلا tags |
tagLabels | { tag: { en, ar } }، ≤ 200 وسم، يُستبدل كله ولا يُدمج | فارغ |
folderIcons | { \"folder/path\": \"mark\" }، ≤ 200 مجلد: علامات المجلدات التي ترسمها الشجرة؛ والعلامة التي ليست في الكتالوج تُهمل | فارغ |
fonts.prose / .ui / .mono / .arabic | معرّف من الكتالوج، أو custom:<file> لخط مرفوع، أو system | system |
fonts.arabicSizeAdjust | نسبة مئوية صحيحة، 50–300 | القيمة المقيسة لخط الكتالوج نفسه، أو لا شيء |
gitSync.enabled | منطقي | false |
gitSync.remote | https://… أو ssh://… أو git@host:path، بلا اعتمادات مضمّنة | لا شيء |
gitSync.branch | نص | main |
gitSync.intervalMinutes | عدد صحيح 0–1440؛ و0 تعني يدويًّا فقط | 0 |
gitSync.pullFirst | منطقي: سحب ما على المستودع البعيد قبل كل مزامنة، ولا يُقبل إلا إن كان مجرّد إضافة فوق ما عندك (التقديم السريع) | true |
gitSync.authMode | ssh · token | ssh |
وثمّة مفتاحان آخران للكتابة فقط: gitToken وgitUser. يقبلهما PATCH /api/settings ويخزّنهما في ASTROLABE_DATA/git-credentials.json، ولا يقرأ هذا الملف إلا مستخدم النظام الذي يعمل به الخادم (بالصلاحيات 0600). لا يدخلان settings.json أبدًا، ولا يمكن قراءتهما بعد ذلك: القراءة تجيب بـgitSync.tokenSet: true وباسم المستخدم، لا أكثر.
ويُكتب settings.json كتابةً ذرّية، أي أن الملف إما قديم بأكمله وإما جديد بأكمله، ولا يستطيع انهيار في المنتصف أن يتركه نصف مكتوب. والتغييرات تسري حيّة: اسم الموقع، والتخطيط، والسمة الافتراضية، والوسوم المستبعدة، ومسارات التعليقات، وأيقونة الموقع، كلها تتحدّث بلا إعادة تشغيل. وإذا فسد الملف يومًا سجّل الخادم تحذيرًا واحدًا وعمل على افتراضيات .env.
أما المفاتيح الحسّاسة أمنيًّا فهي عمدًا في .env وحده، وإلى الأبد. لا تستطيع اللوحة ولا /api/settings قراءتها ولا كتابتها: ADMIN_PASSWORD_HASH وSESSION_SECRET وTRUSTED_PROXIES وPORT وHOST وASTROLABE_VAULT وASTROLABE_DATA وPUBLIC. وSITE_URL في .env وحده أيضًا، لسبب أبسط: لم يحتج شيء قطّ إلى تغييره والخادم يعمل.
واجهة الإعدادات البرمجية
للسكربتات. وهي للمشرف وحده؛ يأخذ الزائر 404.
GET /api/settingsيعيد المفاتيح المخزّنة، ومعهاeffective(القيم المدمجة المستخدمة فعلًا)، وكتالوج الخطوط، وكتلةabout(الإصدار، وإصدار Node، والمسارات الكاملة، والأعداد).PATCH /api/settingsيأخذ كائنًا جزئيًّا. لا يتغيّر إلا المفاتيح التي تسمّيها؛ وnullتمسح مفتاحًا فيعود إلى.env. والتحقق صارم، فالمفتاح المجهول يُجاب بـ400، والجواب بالشكل نفسه الذي يعيدهGET. أما مفاتيح اعتمادات git فتشترط فوق ذلك أن تكون للنسخة كلمة مرور حقيقية.