محرّك إخراج مفتوح المصدر · v1.15.0
المنضّد القابل للبرمجة للويب
يأخذ Postext نص Markdown دلاليًا ويطبّق عليه قواعد تحريرية عمرها قرون، من ضبط الأسطر بخوارزمية Knuth-Plass إلى الأعمدة المتوازنة والعناصر العائمة التي تعرف مكانها، لينتج صفحات بجودة النشر في HTML أو على اللوحة (Canvas) أو في ملف PDF جاهز للطباعة.
كل صفحة تُحسب في متصفحك
Postext
باختصار
Postext برنامج مجاني مفتوح المصدر يُخرج صفحات الكتب والمجلات والتقارير. تكتب النص مع بعض العلامات البسيطة، فيحوّله Postext إلى صفحات مكتملة، مثل صفحات كتاب مطبوع. وهو يتبع قواعد استخدمها الطبّاعون منذ قرون، فيكون النص سهل القراءة. ويمكن أن تُعرض الصفحات في موقع ويب أو في تطبيق أو في ملف PDF جاهز للطباعة. صُنع للكتّاب والناشرين والمصممين والمطوّرين.
النص المكتوب
كل ما يقوله الراوي، مع وصف لما يظهر على الشاشة.
- 0:00
على الشاشةبطاقة داكنة كُتب عليها «ماينتس · 1455» فوق خط ذهبي رفيع. خلف العنوان «طوال خمسة قرون، تعلّمت الطباعة كيف تنضّد الصفحة.» تتصاعد السنة من 1455 إلى 2026 بأرقام مفرّغة ضخمة، وتحطّ حولها مصطلحات الطباعة: ضبط الأسطر، تقنين الأزواج، الأرامل واليتامى، الأعمدة المتوازنة، تباعد الأسطر، شبكة خطوط الأساس، hy·phen·a·tion (تقسيم الكلمات بالواصلة)، طول السطر، العناصر العائمة، الترويسات، الأنهار. تغوص الكاميرا في النقطة الأخيرة، فتغمر الشاشة باللون الذهبي.
السردطوال خمسة قرون، تعلّمت الطباعة كيف تنضّد الصفحة.
- 0:05
على الشاشةالعنوان: «تعلّم الويب تخطيط الواجهات، ولم يتعلّم قط تنضيد الصفحة.» نافذة متصفح على example.com/longform/article فيها مقال مضبوط على ثلاثة أعمدة عنوانه «لماذا لا يستطيع الويب تنضيد الصفحة»؛ وتشير وسوم حمراء إلى أنهار من البياض، وأرملة، ويتيمة، وصورة تقع فوق النص، وعمود أخير غير متوازن. بجانبها شريحة شيفرة نصها «column-count: 3;» ثم «…ولا شيء يُذكر غير ذلك.» وقائمة مشطوبة بالعيوب الخمسة نفسها. ثم تضطرب النافذة وتنهار.
السردتعلّم الويب تخطيط الواجهات، لا الصفحات. لذلك ما زال النص الطويل ينكسر: أنهار، وأرامل، ويتامى، وتصادمات.
- 0:18
على الشاشةبعد وميض أبيض ومرور خطوط زرقاء وذهبية وحمراء، يرتفع شعار Postext واسمه إلى مكانهما مع العبارة «منضّد قابل للبرمجة للويب». وتحتها: مفتوح المصدر · رخصة MIT · v1.7.0 · يعمل في متصفحك.
السردإليك Postext: منضّد قابل للبرمجة للويب.
- 0:24
على الشاشةالقسم 01 من 07، «المحتوى يدخل»: «Markdown يقول ما الأشياء.» ملف Markdown اسمه 03-why-postext.md يكتب نفسه: موجّه part، والعنوان «Why Postext» مع مقدمة، وفقرة تحيل إلى الشكل fig-flow بالموجّه :ref، وسطر ::resource، وكتلة :::callout. بجانبه ملف config.ts يستدعي buildDocument بتخطيط من عمودين ومتن مضبوط وتقسيم بالواصلة للغة en-us، تحت السطر «الإعداد يقرّر شكلها. لا شيء من الإخراج يعيش في النص.»
السردتكتب Markdown دلاليًا، يقول ما الأشياء. ويقرّر الإعداد شكلها.
- 0:32
على الشاشةالقسم 02، «Pretext يقيس»: «قياس من دون لمس DOM.» عنوان وفقرة وإطار تُمسح واحدًا بعد آخر، وتعطي خطوط الأبعاد ارتفاعاتها بالنقاط؛ ولوحة شيفرة تعرض prepare(text, '25px Lora') وlayout(prepared, width, 38) يعيدان ارتفاعًا وعدد أسطر. شريطان يتسابقان عبر 10,000 فقرة: «إعادة التدفّق في المتصفح · DOM» بالكاد يتحرك، و«Pretext · مقاييس canvas + حساب» يمتلئ في الحال، وعدّاد يصعد إلى 600× فوق «قياس للنص أسرع منه في DOM، فيُعاد تدفّق كتاب كامل وأنت تكتب» و«Powered by @chenglou/pretext».
السردتُقاس كل فقرة من دون لمس DOM، بسرعة تصل إلى ستمئة ضعف، بفضل Pretext، المكتبة التي جعلت ذلك ممكنًا.
- 0:42
على الشاشةالقسم 03، «Postext يقرّر»: «كل سطر يُوضع قبل أن يُرسم أي بكسل.» حلقة من سبعة أجزاء تضيء تباعًا، البنية والقياس والوضع والتعويم والتحسين والموازنة والإيقاع، مع وصف من سطر واحد لكل منها، بينما تتجمّع بجانبها صفحة من عمودين من دليل Postext: كتل موسومة تطير إلى أعمدتها، ويستقر شكل في مكانه تحت الملاحظة «:ref{id="fig-flow"} → column foot»، وينزل شريط الافتتاح، وتظهر الأسطر، وتتساوى الأعمدة، وتمسح شبكة خطوط الأساس الصفحة نزولًا. تدور الحلقة في التكرارات من 1 إلى 3 وتعرض «استقر في 3 تكرارات» مع علامة صح؛ ويعرض إطار مربع إحاطة سطر واحد وخط أساسه.
السردثم يقرّر Postext. سبع مراحل تضع كل سطر، وتعوّم كل شكل، وتوازن كل عمود، وتتكرر حتى لا يتحرك شيء.
- 0:54
على الشاشةالقسم 04، «المستند الافتراضي»: «غيّر كلمة، فلا يُنضَّد من جديد إلا ما تغيّر.»، مع الملاحظة «مثل DOM الافتراضي في React، لكن للصفحات: VDT، شجرة المستند الافتراضية.» سبع صفحات، من p. 7 إلى p. 13، مصفوفة في صف؛ مؤشر كتابة يعلّم تعديلًا في p. 11، فيتحوّل باقي ذلك العمود إلى الذهبي بوسم DIRTY، وينسكب جزء يسير إلى p. 12 التي تنال علامة صح ووسم SETTLED، بينما تحمل الصفحات السابقة وسم SKIPPED واللاحقة وسم UNTOUCHED. ثلاث نقاط تعرض القاعدة، ولوحة عنوانها renderToHtmlIndexed() تعلّم العقد المتغيّرة في شجرة المستند بوسم PATCHED.
السردكل ذلك يعيش في مستند افتراضي، مثل DOM الافتراضي في React. غيّر كلمة، فلا يُنضَّد من جديد إلا ما تغيّر.
- 1:03
على الشاشة«مستند طويل؟ لا يُرسم إلا ما على الشاشة.» عمود من صفحات كتاب يمرّ عبر إطار ذهبي اسمه VIEWPORT، مع هامش 200 بكسل فوقه وتحته: الصفحات داخله مرسومة كاملة، والصفحات خارجه حدود متقطعة. عدّاد كبير يعرض عدد الصفحات المرسومة في تلك اللحظة من أصل 48 (IntersectionObserver · +200 px)، بجانب «الهندسة: كل صفحة. البكسلات: ما تراه فقط.»
السردوفي الكتاب الطويل، لا تُرسم أبدًا إلا الصفحات الظاهرة على الشاشة.
- 1:10
على الشاشةالقسم 05، «ضبط الأسطر بخوارزمية Knuth–Plass»: «كل طرق تقسيم الفقرة. دفعة واحدة.» على اليسار فقرة عن تقسيم الأسطر منضّدة بطريقة أول ما يتسع، كما يفعل المتصفح، وتتحوّل أرخى أسطرها إلى الأحمر. وتحتها تصير كل كلمة نقطة على خط: أقواس حمراء تعلّم مواضع القطع الجشعة، وأقواس زرقاء باهتة تجرّب كل قطع ممكن، ومسار ذهبي يختار أفضل مجموعة. وعلى اليمين نسخة Knuth–Plass متساوية التباعد، مع رداءة كل سطر، والصيغة «(1 + badness + penalty)²»، ومجموع أدنى من نقاط العيب.
السرديقسم المتصفح الأسطر بجشع، سطرًا بعد سطر. أما Postext فيستعمل Knuth–Plass، الخوارزمية التي يقوم عليها TeX. تزن كل طرق تقسيم الفقرة كاملة، وتحتفظ بأكثرها انتظامًا.
- 1:24
على الشاشةالقسم 06، «إخراج واحد، ثلاثة مُخرِجات»: «ما تراه هو ما يذهب إلى المطبعة.» تحت سطر الشيفرة const vdt = buildDocument(content, config); تنقسم صفحة واحدة إلى ثلاث. Canvas (renderToCanvas()، صور نقطية دقيقة حتى البكسل) تمرّ فوق شبكة بكسلاتها عدسة مكبّرة؛ وHTML (renderToHtml()، نص قابل للتحديد، يتكيّف مع تغيير الحجم) تُحاط كل كتلة فيه بإطار وتُوسم <h1> و<p> و<figure> وغيرها؛ وPDF (renderToPdf()، جاهز للطباعة، PDF/UA، CMYK) تنزلق فيه أربعة ألواح ألوان حتى تتطابق، ثم تظهر علامات القص وشريط الألوان.
السردإخراج واحد وثلاثة مُخرِجات: Canvas وHTML وPDF جاهز للطباعة. ما تراه هو ما يذهب إلى المطبعة.
- 1:35
على الشاشةالقسم 07، «لماذا معيار مفتوح»: «وضع LaTeX المعيار للطباعة. والنشر اليوم يعيش أيضًا على كل شاشة.» بطاقتان: LaTeX، 1984، مع علامات خطأ أمام «مصمَّم للصفحة المطبوعة» و«بناء مقيّد بخطوط جهاز واحد وحزمه» و«ترجم، انتظر، كرّر» و«لا إخراج تحريري على الويب المتجاوب»؛ وPostext، 2026، مع علامات صح أمام «الويب وCanvas وPDF جاهز للطباعة من إخراج واحد» و«ملف .postext محمول واحد يحمل كل شيء» و«يُعاد تدفّقه مباشرةً وأنت تكتب» و«يعمل في أي متصفح · بلا خوادم · MIT». وتضيء بطاقة Postext.
السردوضع LaTeX المعيار للطباعة. لكن النشر اليوم يعيش على كل شاشة.
- 1:41
على الشاشةالعنوان التمهيدي «ملف واحد، الكتاب كله»، والعنوان «معيار مفتوح للنشر، يبلغ ما لا يبلغه LaTeX.» تنفجر أيقونة ملف .postext إلى خمسة أجزاء: preset.json (الإعدادات والتصميم)، وchapters/*.md (ملف Markdown لكل فصل)، وfonts/*.woff2 (الخطوط نفسها)، وimages/ · SVG (كل صورة، مضمّنة)، وresources (الجداول والأشكال والتعليقات). والتعليق: «ملف ZIP عادي: مفتوح، موثّق، برخصة MIT. يمكن لأي أداة قراءته وكتابته.»
السردPostext معيار مفتوح: ملف واحد محمول، موثّق وبرخصة MIT، يمكن لأي أداة قراءته وكتابته.
- 1:51
على الشاشة«المعرض · نضّده المحرّك الحقيقي»: جدار من صفحات الكتب يبتعد في منظور بينما يبلغ عدّاد 48 صفحة. النص: «12 فصلًا، و3 أجزاء، وغلاف، أُخرجت في نحو نصف ثانية. كل صفحة من دليل Postext حسبها postext v1.7.0 في المتصفح لهذا الفيلم. لا شيء وُضع باليد.» ثم وسوم: كتب مدرسية، مجلات، طبعات أدبية، كتالوجات.
السردلهذا يستطيع إخراج كتب من مئات الصفحات في أعشار من الثانية.
- 1:58
على الشاشةبطاقة الختام: شعار Postext مع العبارة «منضّد قابل للبرمجة للويب»، والعنوان postext.dev، وسطر طرفية يكتب «$ pnpm add postext»، والتذييل «مفتوح المصدر · MIT · github.com/drnachio/postext».
السردPostext. مفتوح المصدر، على postext.dev.
الفصل 1 · لماذا Postext
إخراج تحريري يُحسب للويب
قضى فن الطباعة خمسة قرون يتعلّم كيف تُنضَّد الصفحة، وتعلّمت المتصفحات كيف تُرتَّب الواجهة. ينقل Postext الأول إلى الثانية.
تمنحك CSS تخطيطًا متجاوبًا: flexbox وgrid والأعمدة. لكنها لا تستطيع موازنة الأعمدة، ولا إبقاء العنوان مع فقرته، ولا منع الأسطر الأرامل واليتيمة، ولا تعويم شكل إلى رأس العمود التالي. هذه قرارات تحريرية صُقلت عبر قرون من الطباعة.
يسدّ Postext هذه الفجوة. تعطيه نص Markdown دلاليًا وكائن إعدادات، فيقيس النص أسرع من DOM بما بين 300 و600 مرة باستخدام @chenglou/pretext (يفتح في تبويب جديد)، ثم يحسب هندسة الصفحة كاملة، كل سطر وكل عنصر عائم وكل تعليق، ويرسمها عبر واجهات إخراج HTML واللوحة (Canvas) وPDF الجاهز للطباعة.
Markdown يدخل
:::part{number="I" title="الأسس"
palette="band=#2b4acb"}
:::
# لماذا Postext {lead="أمضت الطباعة
خمسة قرون…"}
Postext **محرّك إخراج مفتوح
المصدر** ينقل صنعة الطباعة
إلى الويب، كما يبيّن
:ref{id="fig-flow"}.
:::callout{type="try"}
غيّر كلمة واحدة: تُنضَّد
الصفحة من جديد.
:::صفحات تخرج
بالأرقام
- أسرع من DOM في قياس النص، فيُعاد إخراج كتاب كامل وأنت تكتب
- 300–600×أسرع من DOM في قياس النص، فيُعاد إخراج كتاب كامل وأنت تكتب
- مُخرَجات من إخراج واحد: HTML واللوحة (Canvas) وPDF الجاهز للطباعة وEPUB 3
- 4مُخرَجات من إخراج واحد: HTML واللوحة (Canvas) وPDF الجاهز للطباعة وEPUB 3
- مُخرَج PDF موسوم وقابل للوصول، مع إشارات مرجعية وألوان CMYK
- PDF/UAمُخرَج PDF موسوم وقابل للوصول، مع إشارات مرجعية وألوان CMYK
- خوادم: يعمل المحرّك كاملًا في المتصفح، بترخيص MIT
- 0خوادم: يعمل المحرّك كاملًا في المتصفح، بترخيص MIT
الفصل 2 · القدرات
ما عرفه المنضّدون في الطباعة منذ البداية
ستة أمور تحتاج إليها الصفحة ولم تُصمَّم CSS قط لتقرّرها، يحسبها المحرّك بالطريقة نفسها في كل مرة.
- 2.1
ضبط الأسطر بخوارزمية Knuth-Plass
خوارزمية تقسيم الأسطر المثلى نفسها التي يستخدمها TeX، مع تقسيم الكلمات بالواصلة وفق أنماط TeX والتحكم في الأسطر اليتيمة: كتل نص منضّدة بانتظام، بلا أنهار من الفراغات، بما يتجاوز كل ما تستطيع CSS التعبير عنه.
اقرأ في التوثيق - 2.2
الموارد والإحالات المتبادلة
تطفو الأشكال ومخططات SVG والجداول إلى أعلى الأعمدة والصفحات أو أسفلها، كما تطفو العناصر في الطباعة، مع ترقيم حسب النوع وإحالات :ref تبقى متزامنة دائمًا.
اقرأ في التوثيق - 2.3
الجداول والتعليقات
جداول تُنضَّد بخطوط مستقلة للمتن والرأس، وتنقسم عبر الصفحات مع تكرار رؤوسها، وتعليقات تتبع إعداداتك: مرقّمة وموضوعة بجانب المورد الذي تصفه.
اقرأ في التوثيق - 2.4
مخططات بحبر واحد
أعد تلوين مخططات SVG بدرجات حبر واحد حسب الإضاءة، فتتسق كل الرسوم مع تصميمك، جاهزة للطباعة بالألوان الخاصة (spot colour).
اقرأ في التوثيق - 2.5
رياضيات LaTeX
معادلات داخل السطر ومعادلات معروضة تُكتب بـ LaTeX، يقيسها المحرّك وينضّدها لتستقر على شبكة خطوط الأساس إلى جانب النص.
اقرأ في التوثيق - 2.6
الويب وPDF الجاهز للطباعة وEPUB
محرّك إخراج واحد وأربعة مُخرَجات. تُرسم الصفحات المحسوبة نفسها في HTML أو على اللوحة (Canvas) أو في PDF جاهز للطباعة، مع إشارات مرجعية وألوان CMYK ومُخرَج PDF/UA موسوم وقابل للوصول، وتصدر كتابًا إلكترونيًا بصيغة EPUB 3، صفحة بصفحة أو قابلًا لإعادة التدفق.
اقرأ في التوثيق
كل صفحة في دليل Postext، من الغلاف والمحتويات إلى فواصل الأجزاء وغيرها، ينضّدها Postext في متصفحك وأنت تقرؤها.
معرض الأعمال
كتب حقيقية تُنضَّد في متصفحك
كتاب مدرسي، ومجلة، وملحمة شعرية مشروحة، وفهرس معرض، ورواية صينية كلاسيكية في 120 فصلًا، وألف ليلة وليلة بالعربية. افتح أيًّا منها في Sandbox، وغيّر قاعدة، وشاهد كل صفحة يُعاد إخراجها.
الفصل 3 · سير العمل
ثلاث خطوات إلى إخراج بجودة النشر
المحتوى في Markdown، والتصميم في كائن إعدادات، والصفحات من استدعاء دالة واحدة.
- 3.1
اكتب Markdown دلاليًا
اكتب محتواك بـ Markdown مُعزَّز: عناوين وقوائم وجداول ورياضيات وإطارات وإحالات :ref إلى أشكالك. لا شأن لك بالإخراج، المحتوى فقط.
- 3.2
اضبط قواعد الإخراج
حدّد مقاس الصفحة والأعمدة والخطوط وتصاميم العناوين والترويسات ومواضع العناصر العائمة في كائن PostextConfig، أو صمّمها بصريًا في Sandbox.
- 3.3
اعرض في HTML أو على اللوحة أو في PDF
استدعِ buildDocument لتتلقى هندسة الإخراج كاملة، ثم اعرضها بواجهة HTML أو اللوحة (Canvas) أو PDF الجاهز للطباعة.
API
دالة واحدة وتحكم كامل
استدعِ buildDocument بمحتواك وكائن إعدادات، فتحصل على هندسة الصفحات كاملة: ارسم أي صفحة صورةً بـ renderPage، أو نضّد الكتاب كله ملف PDF جاهزًا للطباعة بـ renderToPdf.
import { buildDocument, renderPage } from "postext";
import { renderToPdf } from "postext-pdf";
const doc = buildDocument(
{ markdown },
{
page: { sizePreset: "21x28" },
layout: { layoutType: "double" },
bodyText: {
fontSize: { value: 12, unit: "pt" },
textAlign: "justify",
hyphenation: { enabled: true, locale: "en-us" },
},
}
);
// كل صفحة صورةً…
const cover = renderPage(doc.pages[0], doc);
cover.toBlob((png) => save(png, "cover.png"));
// …أو الكتاب كله ملف PDF جاهزًا للطباعة
// fontProvider: بايتات TTF لكل عائلة خط ووزن (انظر التوثيق)
const pdf = await renderToPdf(doc, { fontProvider });الفصل 4 · صيغة مفتوحة
ملف واحد، الكتاب كله
يحمل ملف .postext كل ما يحتاج إليه المستند ليُنضَّد من جديد على أي جهاز: صيغة مفتوحة قابلة للتحرير يستطيع أي أحد اعتمادها.
معظم صيغ النشر تبعثر المشروع. فبناء LaTeX يعتمد على الخطوط والحزم المثبّتة على جهاز بعينه، والملفات الأصلية لمحرّرات الإخراج الكبرى ترتبط بصور ومحارف محفوظة خارجها. انقل المشروع فيضيع شيء ما. وقد اصطدمنا بهذه الحدود مع LaTeX بأنفسنا.
ملف .postext أرشيف ZIP عادي يستطيع أي أحد فتحه وقراءته وتحريره: بيان JSON، وملف Markdown لكل فصل، وملفات الخطوط والصور نفسها. يصدّره Sandbox، وتكتبه مهارة الوكيل postext-port، وتفتحه postext/bundle في أي برنامج لتنضيد الصفحات نفسها من جديد. الصيغة موثّقة ومرخّصة بـ MIT، وجاهزة لتقرأها أي أداة وتكتبها.
- 4.1
preset.jsonالإعدادات. الصفحة والشبكة والمحارف وأنماط العناوين والفقرات والألوان والترويسات، بصيغة JSON مقروءة.
- 4.2
chapters/<lang>/*.mdالفصول. ملف Markdown لكل فصل: 14 من الفصول بـ 2 من اللغات هنا.
- 4.3
fonts/*.woff2المحارف. ملفات الخطوط نفسها لا أسماؤها فقط: 18 من الملفات لعائلات Lora وFraunces وGeist وBricolage Grotesque.
- 4.4
preset.json › resourcesالموارد. التعليقات والترقيم والمواضع ومحتوى الجداول للأشكال والجداول التي يحيل إليها النص، وعددها 23.
- 4.5
resources/*.svgالصور. الرسوم نفسها، SVG أو نقطية، مع نسخة كل لغة: 32 من الملفات.
جرّبه
افتح الدليل واحصل على صفحاته
أول أمثلة Sandbox، دليل Postext، ملف .postext واحد. افتحه في المتصفح وحوّل كل صفحة إلى صورة: محارفه وأشكاله وجداوله تأتي من الملف نفسه.
نزّل الدليلpostext-guide.postext · 511 KBimport { openBundle, loadBundleFonts, registerBundleImages,
buildBundle, renderPageToCanvas } from "postext";
// دليل Sandbox: الإعدادات والفصول والخطوط والصور
const file = await fetch("postext-guide.postext").then((r) => r.blob());
const book = await openBundle(file, { locale: "en" });
await loadBundleFonts(book); // محارفه الخاصة
await registerBundleImages(book); // أشكاله الخاصة
// كل صفحة من كل فصل، صورةً
for (const doc of buildBundle(book))
for (const page of doc.pages) {
const canvas = document.createElement("canvas");
renderPageToCanvas(page, doc, canvas, { scale: 0.5 });
document.body.append(canvas);
}التثبيت
ابدأ في أقل من دقيقة
حزمة واحدة، بلا خادم، وبلا اعتماديات أصلية. أضف postext-pdf حين تحتاج إلى الطباعة.
// بداية سريعة
import { buildDocument, renderPage } from "postext";
import { renderToPdf } from "postext-pdf";
const doc = buildDocument({
markdown: "# Hello World\n\nYour content here.",
});
// الصفحة الأولى مرسومة على لوحة canvas
document.body.append(renderPage(doc.pages[0], doc));
// المستند كله ملف PDF
const pdf = await renderToPdf(doc, { fontProvider });