منصة توثيق عربية — صفحات شجرية ومحرر غني (RTL/LTR)
  • TypeScript 90%
  • CSS 5.9%
  • Shell 1.9%
  • JavaScript 1.2%
  • Dockerfile 0.6%
  • Other 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-30 13:19:39 +03:00
.gitea/workflows test: إضافة اختبارات E2E للواجهة (Playwright — نقر أزرار حقيقي في Chromium) 2026-08-30 12:54:29 +03:00
client chore: release v1.7.0 2026-08-30 13:14:03 +03:00
desktop chore: release v1.7.0 2026-08-30 13:14:03 +03:00
e2e test: إضافة اختبارات E2E للواجهة (Playwright — نقر أزرار حقيقي في Chromium) 2026-08-30 12:54:29 +03:00
scripts chore: إدراج README في سكربت الإصدار [skip ci] 2026-08-30 13:19:39 +03:00
server chore: release v1.7.0 2026-08-30 13:14:03 +03:00
.dockerignore chore: initial commit — منصة دوكو للتوثيق العربي v1.5.0 2026-08-30 07:39:59 +03:00
.gitignore feat: إضافة نسخة سطح مكتب AppImage (Electron) + غلاف وتوثيق 2026-08-30 13:13:58 +03:00
CHANGELOG.md chore: release v1.7.0 2026-08-30 13:14:03 +03:00
docker-compose.yml chore: initial commit — منصة دوكو للتوثيق العربي v1.5.0 2026-08-30 07:39:59 +03:00
Dockerfile chore: initial commit — منصة دوكو للتوثيق العربي v1.5.0 2026-08-30 07:39:59 +03:00
package.json chore: release v1.7.0 2026-08-30 13:14:03 +03:00
playwright.config.ts test: إضافة اختبارات E2E للواجهة (Playwright — نقر أزرار حقيقي في Chromium) 2026-08-30 12:54:29 +03:00
pnpm-lock.yaml test: إضافة اختبارات E2E للواجهة (Playwright — نقر أزرار حقيقي في Chromium) 2026-08-30 12:54:29 +03:00
pnpm-workspace.yaml chore: initial commit — منصة دوكو للتوثيق العربي v1.5.0 2026-08-30 07:39:59 +03:00
README.md chore: إدراج README في سكربت الإصدار [skip ci] 2026-08-30 13:19:39 +03:00

دوكو (Docu)

منصة توثيق عربية بسيطة — صفحات شجرية + محرر كتل، مع الميزة الجوهرية: اتجاه كل فقرة (RTL / LTR) يُحدَّد تلقائيًا حسب أول حرف، مع إمكانية التوجيه اليدوي.

مشروع تعليمي مبني على فكرة Docmost لكن بنسخة مبسطة ومستقلة.

الميزات

  • 🌳 صفحات شجرية غير محدودة العمق — الإنشاء عبر نافذة داخلية، مع نقل (زر أو سحب وإفلات)، وحذف ناعم متسلسل.
  • 🔀 نقل الصفحات: من زر «نقل» في الشريط الجانبي تنقل أي صفحة تحت أي صفحة أخرى أو للجذر.
  • ✍️ محرر كتل غني (TipTap) — عناوين، غامق/مائل/شطب، فوقي/سفلي، ألوان النص والتظليل، روابط، قوائم مهام (Checkboxes)، اقتباس، كود، خط أفقي، ومحاذاة النص (يمين/وسط/يسار/ضبط).
  • 🔍 بحث في نصوص الصفحات، و🖼️ صور (رفع وإدراج)، و⚡ أوامر "/" السريعة، و🧭 فهرس المحتوى.
  • 🗑️ سلة المحذوفات: الحذف ناعم (soft delete) مع استرجاع أو حذف نهائي.
  • 🌙 وضع داكن/فاتح + 🔤 تلوين صيغة الكود (syntax highlighting) + 🏷️ أيقونة للصفحة (إيموجي).
  • 📊 جداول متقدمة: إدراج جدول، إضافة/حذف صفوف وأعمدة، صف رأس وعمود رأس، دمج الخلايا وفصلها، تغيير حجم الأعمدة بالسحب، محاذاة الخلايا، حذف الجدول، مع تحكم باتجاه الجدول كاملًا (RTL/LTR/تلقائي) دفعة واحدة.
  • 📈 رسومات Mermaid التوضيحية: إدراج مخططات (flowchart وغيرها) تتحول لرسوم SVG، مع تعديل الكود بضغطة على الرسم.
  • 🖥️ عرض الصفحة قابل للتبديل: زر في رأس المحرر يوسّع منطقة الكتابة للعرض الكامل (مفيد للجداول العريضة) أو يعيدها للعرض الضيّق، ويُحفظ اختيارك.
  • 🧭 اتجاه الفقرة تلقائي: إذا بدأت الفقرة بحرف عربي → RTL، وبحرف لاتيني → LTR.
  • 🎛️ توجيه يدوي: من شريط الأدوات اختر تلقائي / RTL / LTR لأي فقرة على حدة.
  • 💾 حفظ تلقائي أثناء الكتابة (مع تأخير debounce).
  • 📜 سجل النسخ (History): لقطة تلقائية كل 60 ثانية، وزر «حفظ» يدوي لالتقاط نسخة فورية، مع معاينة لأي نسخة قديمة واسترجاعها.
  • 🔔 إشعار الحفظ: إشعار عند كل حفظ تلقائي/يدوي، مع عرض «آخر حفظ: منذ …» في رأس المحرر.
  • 📤 تصدير الصفحة: Markdown / HTML (مستقل بصور مضمّنة ورسومات Mermaid) / نص عادي / PDF (زر تصدير في رأس المحرر).
  • 🗄️ نسخ احتياطي واسترجاع: تنزيل نسخة كاملة (JSON) واسترجاعها من أسفل الشريط الجانبي.
  • 🌐 واجهتان (عربي / إنجليزي): مفتاح لغة أسفل الشريط الجانبي، وعند التبديل ينقلب اتجاه الصفحة تلقائيًا (RTL ↔ LTR) وتُحفظ اللغة في المتصفح.
  • 🔤 خط Tajawal مدمج محليًا (عبر @fontsource/tajawal) — بدون أي روابط إنترنت.

كيف يعمل اتجاه الفقرة؟

كل فقرة/عنوان يحمل سمة textDirection بإحدى القيم:

القيمة السلوك
auto يُترك للمتصفح (عبر dir="auto") لتحديد الاتجاه حسب أول حرف قوي — عربي → RTL، لاتيني → LTR
rtl / ltr توجيه يدوي صريح يتجاوز التلقائي

الملفات المسؤولة:

  • client/src/editor/extensions/paragraphDirection.ts — امتداد TipTap.
  • client/src/editor/utils/detectDirection.ts — كشف الحرف العربي/اللاتيني.

التقنيات

  • الواجهة: React + Vite + Mantine + TipTap + خط Tajawal (مدمج محليًا)
  • الخادم: Fastify + Drizzle ORM + SQLite (أسهل تشغيل بدون Docker)
  • إدارة الحزم: pnpm workspaces

البنية

docu/
├── server/            # Fastify + Drizzle + SQLite
│   └── src/
│       ├── index.ts           # نقطة الدخول (استماع + تقديم الواجهة المبنية)
│       ├── app.ts             # buildApp(): بناء التطبيق (قابل للاختبار)
│       ├── db/                # الاتصال + schema + seed ترحيبي
│       └── routes/pages.ts    # مسارات الصفحات (شجرة + CRUD)
└── client/            # React + Vite + Mantine + TipTap
    └── src/
        ├── App.tsx            # التنسيق العام
        ├── components/        # Sidebar + EditorPage + DirectionControl
        └── editor/            # امتداد اتجاه الفقرة + كشف الاتجاه

التشغيل

يتطلب Node.js 18+ و pnpm.

pnpm install
pnpm dev          # يشغّل الخادم (4000) والواجهة (5175) معًا

ثم افتح http://localhost:5175

أوضاع أخرى

pnpm dev:server   # الخادم فقط
pnpm dev:client   # الواجهة فقط
pnpm build        # بناء الإنتاج
pnpm start        # تشغيل الخادم + تقديم الواجهة المبنية على http://localhost:4000

واجهة الـ API

الطريقة المسار الوصف
GET /api/pages/tree الشجرة الكاملة متداخلة
GET /api/pages/:id صفحة مع المحتوى
POST /api/pages إنشاء صفحة { title, parentId? }
PATCH /api/pages/:id تحديث { title?, icon?, content?, parentId? }
DELETE /api/pages/:id حذف (متسلسل للأبناء)

الاختبارات

pnpm --filter client test   # اختبارات الوحدة (محوّل Markdown + كشف الاتجاه)
pnpm --filter server test   # اختبارات تكامل الخادم (Fastify inject: صحة + إنشاء/قراءة/حذف/سلة)
pnpm --filter server build  # فحص أنواع الخادم (tsc --noEmit)
pnpm --filter client build  # بناء الواجهة + فحص الأنواع
pnpm e2e                    # اختبارات E2E للواجهة (Playwright — نقر أزرار حقيقي في Chromium)

Docker و DevOps

المشروع جاهز للنشر عبر Docker على Gitea:

  • Dockerfile — بناء متعدد المراحل (بناء الواجهة ثم صورة تشغيل بخادم Node 22).
  • docker-compose.yml — يسحب الصورة من الريجستري git.majlis7.net/debe/docu:latest ويشغّلها على المنفذ 4000 مع مجلد بيانات دائم docu-data.
  • .gitea/workflows/ci.yml — خط أنابيب CI يعمل على رانر Gitea:
    1. test: تثبيت الاعتماديات + اختبارات الوحدة والتكامل + فحص الأنواع + بناء الواجهة.
    2. e2e (بعد نجاح test): تثبيت Chromium + اختبارات Playwright للواجهة.
    3. docker (بعد نجاح test، على master): بناء الصورة ورفعها للريجستري بوسمَي latest ورقم الإصدار.

النشر

# بعد أن يرفع CI الصورة للريجستري:
docker login git.majlis7.net -u debe
docker compose up -d     # يسحب الصورة ويشغّلها على http://localhost:4000

إصدار جديد (رفع الإصدار تلقائيًا)

بعد أي تعديل بادئ برسالة Conventional Commit، شغّل:

./scripts/release.sh

يقرأ السكربت آخر رسالة commit ويحدّد حجم الترقيم تلقائيًا:

الرسالة الترقيم
feat: ... MINOR
fix: ... PATCH
feat!: ... أو BREAKING CHANGE MAJOR

ثم يحدّث version.ts وملفات package.json وCHANGELOG.md، وينشئ commit + tag ويرفعهما. يبني CI بعدها صورة بالوسم الجديد تلقائيًا.

تطبيق سطح المكتب (AppImage)

يمكن تشغيل دوكو كتطبيق سطح مكتب Linux مستقل (نافذة أصلية عبر Electron، بدون متصفح):

./scripts/build-appimage.sh

ينتج الملف desktop/build/release/Docu-<الإصدار>-x86_64.AppImage (قابل للتنفيذ مباشرة). يعمل السكربت على:

  1. بناء الخادم (JS) والواجهة.
  2. تجميعها مع غلاف Electron (desktop/main.js + desktop/package.json).
  3. إعادة بناء better-sqlite3 لإصدار Electron، ثم تغليف الكل بـ electron-builder.
  • البيانات (قاعدة SQLite والصور) تُحفظ في مجلد المستخدم (~/.config/Docu/) وليس داخل الـ AppImage (لأنه للقراءة فقط).
  • الأيقونة في desktop/icon.png، وتفاصيل التغليف في حقل build داخل desktop/package.json.

إصدارات البرنامج (Semantic Versioning)

نعتمد الترقيم MAJOR.MINOR.PATCH، ويظهر رقم الإصدار أسفل الشريط الجانبي:

الجزء متى يزيد
MAJOR تعديلات كبيرة وأحيانًا جذرية (تغييرات تكسر التوافق)
MINOR إضافة أو إزالة ميزة، أو تعديل بسيط
PATCH إصلاح مشاكل/أخطاء
  • الإصدار الحالي: 1.7.0 (المعرّف في client/src/version.ts وملفات package.json).

استكشاف الأخطاء

  • خطأ Cannot find matching keyid (مشكلة corepack): عطّل التحقق من التوقيع ثم أعد التشغيل:
    COREPACK_INTEGRITY_KEYS=0 pnpm dev
    
  • المنفذ مشغول: غيّر منفذ الخادم عبر متغير PORT، أو منفذ الواجهة في client/vite.config.ts.

خطوات قادمة مقترحة

  • التعاون اللحظي (Yjs) — نفس نهج Docmost.
  • تسجيل دخول وصلاحيات (CASL).
  • السحب والإفلات لترتيب الشجرة (fractional indexing).
  • الانتقال من SQLite إلى PostgreSQL.
  • تصدير جماعي لكل الصفحات دفعة واحدة.