# الصفحات المركّبة

> ترميز Markdown للصفحات المركّبة: سور الصفحة ذو النقاط الرأسية الأربع الذي يسمّي قالب الصفحة، والإطارات والسمة slot التي ترسل المحتوى إلى إطارات القالب، والأشكال ذات التسميات عند مراسي الصورة، والتحذيرات التي تطابق المحتوى بالقالب

- نسخة HTML: https://postext.dev/ar/docs/composed-pages
- آخر تحديث: 2026-10-16
- مدة القراءة: 9 دقائق
- لغات أخرى: [en](https://postext.dev/en/docs/composed-pages.md), [es](https://postext.dev/es/docs/composed-pages.md), [ca](https://postext.dev/ca/docs/composed-pages.md), [de](https://postext.dev/de/docs/composed-pages.md), [fr](https://postext.dev/fr/docs/composed-pages.md), [it](https://postext.dev/it/docs/composed-pages.md), [pt](https://postext.dev/pt/docs/composed-pages.md), [zh](https://postext.dev/zh/docs/composed-pages.md), [ja](https://postext.dev/ja/docs/composed-pages.md)

## باختصار

بعض الصفحات ليست عمودًا واحدًا من النص الجاري، بل مجموعة من الإطارات، مثل صفحة في كتاب مدرسي فيها شريط للعنوان ونص وثلاثة صناديق ملوّنة مع صورها. يسمّي Postext هذه الصفحات الصفحات المركّبة. يحدّد شكلَ الصفحة قالبٌ في الإعدادات، ولا يقول ملف Markdown إلا أيّ قطعة من النص تذهب إلى أيّ إطار. تشرح هذه الصفحة كيف يُكتب هذا الترميز: سور الصفحة، والإطارات، وأسماء الخانات، والصور ذات التسميات مثل أسماء الأماكن على الخريطة. وتسرد أيضًا التحذيرات التي يعطيها Postext حين لا يتوافق النص مع القالب.

**القالب يحمل شكل الصفحة، وملف Markdown يحمل محتواها ويقول إلى أيّ إطار تذهب كل قطعة منه.**

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

تتناول هذه الصفحة ترميز Markdown وكيف تُنضَّد الصفحة منه. أما القالب نفسه (إطاراته وأحجامه وأنماطه وزخرفته) فموصوف في [الإعدادات › الصفحات المركّبة](https://postext.dev/ar/docs/configuration-composed-pages.md). والمستند الذي لا صفحات مركّبة فيه يُخرَج كما كان يُخرَج من قبل تمامًا.

## سور الصفحة

```md
::::page{template="tema-cajas" fondo="banda-retos"}
# La actividad económica y el dinero

Las personas utilizan :chip[recursos]{style="clave"} que se obtienen de la naturaleza…
::::
```

تُفتتح الصفحة المركّبة بسطر من **أربع نقاط رأسية** يليها `page` وسماتها، وتُغلق بسطر مجرّد فيه **العدد نفسه من النقاط الرأسية**. وفي داخلها تُفتح الحاويات ذات النقاط الرأسية الثلاث (`:::frame` و`:::callout` و`:::figure` و`:::columns` و`:::paper`) وتُغلق كعادتها، فيُغلق `:::` المجرّد أعمقها ولا يُغلق الصفحة أبدًا. والصفحة المكتوبة بخمس نقاط رأسية (`:::::page`) تُغلق بخمس، ويصير سطر النقاط الرأسية الأربع داخلها نصًا عاديًا.

| السمة | أثرها |
| --- | --- |
| `template="…"` | إلزامية. معرّف مدخل من `pageTemplates`. |
| `spread` | الصفحة مزدوجة تمتد على صفحتين متقابلتين؛ ويجب أن يكون القالب قالبًا مزدوجًا أيضًا. |
| `id="…"`، `#id` | مرساة: الإحالة `:ref` إليها تطبع رقم الصفحة التي تقع فيها الصفحة المركّبة. |
| أي سمة أخرى | قيمة يقرؤها القالب بوصفها `{attr.name}`، مثل صورة خلفية تُختار صفحةً صفحة: `fondo="banda-retos"` في الصفحة مع `resourceId: "{attr.fondo}"` في الزخرفة. |

تبدأ الصفحة المركّبة دائمًا صفحةً جديدة (أو صفحتين مزدوجتين)، ويبدأ النص الذي يلي سور إغلاقها في الصفحة التالية.

أما `:::page{split=…}` ذات النقاط الرأسية الثلاث فهي صفحة قصة مصوّرة (انظر [القصص المصورة](https://postext.dev/ar/docs/comics.md))، وتبقى على معناها. و`:::page` ذات النقاط الثلاث التي تحمل `template=` تُقرأ هي أيضًا صفحة قصة مصوّرة، وينبّه التحذير `pageFenceLength` إلى أن الصفحة المركّبة تحتاج إلى أربع نقاط رأسية.

وإذا نقص سور، تعافى المحلّل دون أن يضيع نص:

- الصفحة التي تُركت مفتوحة تمتد إلى نهاية الفصل، ويُبلَّغ عنها حاويةً غير مغلقة عند سطر فتحها؛
- سطر `::::page` يأتي والصفحة مفتوحة يُغلق الصفحة المفتوحة هناك أولًا (ويُبلَّغ عنه بالطريقة نفسها)؛
- سور الإغلاق يُغلق كل إطار أو صندوق ما زال مفتوحًا داخل الصفحة، ويُبلّغ عن كل واحد منها؛
- سور الإغلاق الذي يختلف عدد نقاطه الرأسية ليس سور الصفحة: يبقى في النص، حيث تراه.

## الإطارات والخانات

```md
:::frame{slot="dinero" label="El dinero"}
Es el instrumento utilizado como medio de pago…

Hasta hace pocos años, lo más normal era pagar con dinero en **efectivo**…
:::
```

**الخانة** هي الاسم الذي تطلبه قطعة من المحتوى، ويطابق اسم إطار من إطارات القالب. ويرسل `:::frame{slot="…"}` كل ما فيه إلى ذلك الإطار. ومتنه Markdown كامل: فقرات وقوائم وعناوين وشارات وتضمينات `::resource` وإحالات `:ref` وحواشٍ و`:::columns` وصناديق متداخلة. ويعطي `label` و`title` لسانَ الإطار أو عنوانه كلماتِه، كما يفعلان في `:::callout`؛ ويأتي مظهر الإطار من نمط الصندوق الذي يعطيه إياه القالب.

ويمكن لكتلة واحدة أن تسمّي خانتها بنفسها:

| الكتلة | طريقة كتابتها |
| --- | --- |
| عنوان | `## Retos {slot="retos-titulo"}` |
| تضمين مورد | `::resource{id="dinero-pago" slot="dinero-fotos"}` (السمتان، بأي ترتيب) |
| كتلة شيفرة | `````js {slot="codigo"}`` |
| صندوق أو أي حاوية أخرى | `:::callout{type="nota" slot="aside"}`: يذهب الصندوق كله إلى الخانة |
| شكل | `:::figure{resource="mapa" slot="mapa"}` (انظر أدناه) |

وهكذا يُوزَّع المحتوى:

- القطع المتعددة ذات الخانة الواحدة تُضمّ بعضها إلى بعض بترتيب Markdown.
- المحتوى الذي لا خانة له يذهب إلى **إطار التدفق** في القالب (الإطار الموسوم بـ `flow`).
- العنوان الذي لا خانة له يذهب أولًا إلى الإطار الذي يأخذ مستواه (`takes: "h1"`)، إن كان في القالب إطار كهذا، فيكفي لعنوان درس في كتاب مدرسي أن يُكتب `# العنوان` في أعلى الصفحة.
- المحتوى الذي يسمّي خانة ليست في القالب يذهب إلى إطار التدفق ويُبلَّغ عنه (`slotUnknown`).

و`slot` خارج الصفحة المركّبة يُقرأ ولا يغيّر شيئًا.

## أشكال بتسميات

```md
:::figure{resource="mapa-europa" slot="mapa"}
::label[OCÉANO ATLÁNTICO]{at="atlantico" style="mar"}
::label[**Madrid**]{at="madrid"}
::label[Mar Negro]{at="62% 48%"}
:::
```

يضع `:::figure{resource="…"}` موردًا واحدًا، بتعليقه ورقمه، كما يفعل `::resource`، ويسرد التسميات التي توضع على الصورة: سطر `::label[TEXT]{…}` لكل تسمية، ويجوز أن تفصل بينها أسطر فارغة.

- يسمّي `at` مرساة من مراسي المورد (نقطة تُعرَّف مرة واحدة على الصورة وتشترك فيها كل اللغات)، أو يعطي نقطة بالنسب المئوية من الصورة، `at="x% y%"`، لتسمية لا مرساة لها.
- يسمّي `style` نمط تسمية، ويتقدّم على نمط المرساة.
- النص بين القوسين المعقوفين Markdown داخل السطر: عريض ومائل وشارات.

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

## مثال

صفحة من كتاب مدرسي، فيها شريط للعنوان ونص بقائمته وثلاثة صناديق ملوّنة، بجانب كل منها صورته:

```md
::::page{template="tema-cajas" fondo="banda-retos"}
# La actividad económica y el dinero

## La actividad económica

Las personas utilizan :chip[recursos]{style="clave"} que se obtienen de la naturaleza…

- Las :chip[empresas.]{style="clave"} Ofrecen bienes y servicios a cambio de un beneficio.
- Las :chip[personas y familias.]{style="clave"} Adquieren lo que ofrecen las empresas…

:::frame{slot="dinero" label="El dinero"}
Es el instrumento utilizado como medio de pago, ya que su valor es conocido…
:::

::resource{id="dinero-pago" slot="dinero-fotos"}

:::frame{slot="gasto" label="El gasto"}
- **Fijo:** es el que se produce todos los meses…
- **Variable:** puede cambiar según las necesidades…
:::

::resource{id="gasto-compras" slot="gasto-fotos"}

:::frame{slot="ahorro" label="Préstamos y ahorro"}
Si necesitas o quieres comprar algo muy caro…
:::

::resource{id="ahorro-balanza" slot="ahorro-fotos"}
::::
```

يذهب العنوان إلى الإطار الذي يأخذ `h1`؛ ويذهب العنوان الفرعي والفقرة والقائمة إلى إطار التدفق؛ ويذهب كل صندوق وكل صورة إلى إطار خانته. والطبعة الكتالونية هي الأسطر نفسها بكلمات أخرى: لا يتغير القالب ولا الخانات ولا الصور.

## كيف تُنضَّد الصفحة

تشغل الصفحة المركّبة صفحةً مستقلة (دورها `composed` في مرشّح `pages` الخاص بعناصر التصميم). ويُختار القالب بحسب الجهة التي تقع فيها الصفحة، فيُطبَّق `variants.recto` أو `variants.verso` منه. ثم يوضع كل إطار ويُملأ، واحدًا بعد آخر، بتنضيد بقية الكتاب نفسه: أنماط الفقرات والعناوين، والقوائم، والشارات، وعلامات الحواشي، ونمط الصندوق الخاص بالإطار.

### وضع الإطارات

يقوم الإطار في خليته من الشبكة، أو حيث يضعه `placement` (نقطة تثبيت وحافة وإزاحة، كما في عنصر التصميم)، فإن لم يكن له أيّ منهما وُضع في الزاوية العليا اليسرى من منطقة القالب بعرض المنطقة كله. والإطار المثبّت إلى إطار آخر (`"to": "#dinero"`) يوضع بعده ويتحرك معه: يعلّقه `below` تحت الإطار الآخر، ويضعه `right-of` بجانبه، وتشدّه زاوية مثل `top-right` إلى تلك الزاوية من صندوق الإطار الآخر.

وارتفاعه إما ثابت (طول أو نسبة مئوية)، وإما `fill` (حتى حافة المنطقة)، وإما `auto`، وهو الافتراضي: ارتفاع المحتوى الذي يتلقّاه، بين `minHeight` و`maxHeight`، دون أن يتجاوز أسفل المنطقة أبدًا. وفي الإطار الأطول من محتواه يحدّد `verticalAlign` موضع المحتوى (`top` أو `middle` أو `bottom`، أو `justify` لتوزيع المسافة بين كتله). ويرسم نمط الصندوق الخاص بالإطار خلفيته وحدّه وزواياه المدوّرة وشريطه وأيقونته بحجم الإطار كاملًا؛ ويُطبع `label` الخاص بسور `:::frame` في لسان النمط.

### إطار التدفق والعناوين

المحتوى الذي لا يسمّي خانة يذهب إلى الإطار الموسوم بـ `flow`؛ وأول عنوان من كل مستوى يذهب إلى الإطار الذي يأخذه عبر `takes`. وتُقرأ إطارات الصفحة بترتيب أول ظهور لمحتواها في Markdown، كل إطار منها كاملًا: فقارئ الشاشة وPDF الموسوم والمخرجات ذات التخطيط المتدفق تقرأ الصندوق بعد النص الذي تُفتتح به الصفحة، لا في وسطه.

### ربط الإطارات بالتسلسل

يرسل `next` ما لا يتّسع له إطار إلى إطار آخر في الصفحة نفسها، ويرسله ذاك إلى غيره، كما تُربط إطارات النص في برامج الإخراج:

```json
{ "name": "columna-1", "flow": true, "next": "columna-2", "height": { "value": 120, "unit": "mm" } },
{ "name": "columna-2", "placement": { "anchor": { "to": "#columna-1", "edge": "right-of" } } }
```

ينقطع النص بين سطرين ويتابع في الإطار التالي، ويُكسَر من جديد على عرض ذلك الإطار، فلا يضيع منه شيء ولا يتكرر. ومعنى `overflow.continueIn: "#frame"` هو المعنى نفسه. أما المتابعة في الصفحة التالية فمخطَّط لها (`"next-page"`).

### إطارات تزيح النص

الإطار الذي يحمل `exclude: "push"` يُبقي نص الإطارات الأخرى خارج مستطيله: فالسطر من إطار آخر الذي يصطدم به يُنضَّد أقصر من الجهة التي يغطيها المستطيل، كما يلتفّ النص حول صورة في النص الجاري. والصورة المثبّتة إلى زاوية صندوق والموسومة بـ `push` تجعل نص الصندوق يجري بجانبها. وللصندوق الذي يلزمه أن يُبقي عمودًا ثابتًا فارغًا لصوره أن يستعمل `padding` بدلًا من ذلك.

### الزخرفة والترويسات والطبقات

تُوضع زخرفة القالب (`decoration`: صور وخطوط فاصلة وصناديق ونصوص قصيرة) بعد أن تستقر صناديق الإطارات النهائية، فيمكن لعنصر أن يُثبَّت إلى إطار (`"to": "#gasto"`) ويتبعه. وتقرأ نصوصها سمات الصفحة نفسها: `fondo="banda-retos"` في سور الصفحة يعطي `{attr.fondo}`، ومن ذلك صورة خلفية تُختار صفحةً صفحة عبر `"resourceId": "{attr.fondo}"`. والترويسات تقرأ هذه السمات أيضًا. وما يحدّده القالب في `header` أو `footer` يحلّ محلّ ما للقسم، و`false` يخفيه، فإن لم يحدّد القالب أيًّا منهما طُبعت ترويسات القسم.

وتُرسم الإطارات بترتيب `layer`: الزخرفة في الطبقة 0، والإطارات في الطبقة 1 افتراضيًا، والطبقة الأعلى فوق الأدنى، والطبقة السالبة تحت الزخرفة. ويُدير `rotate` الإطار ومحتواه معًا بأي زاوية حول مركز الإطار، في Canvas وفي PDF وفي عارض HTML وفي EPUB ذي التخطيط الثابت.

### المحتوى الذي لا يتّسع

الإطار الذي يطول محتواه عليه، ولا إطار تالٍ له يتابع فيه، يحتفظ بالمحتوى كله في المستند، لكنه لا يُظهر إلا ما يتّسع له: يُقصّ الباقي عند أسفل الإطار في المخرجات المقسّمة إلى صفحات، ويذكر التحذير [`frameOverflow`](https://postext.dev/ar/docs/composed-pages.md#frameoverflow) مقدار ذلك. والمحتوى الذي لا يأخذه أي إطار (لا إطار تدفق، أو ينقص إطار في هذه الجهة) يُنضَّد في النص الجاري، في الصفحة التي تلي الصفحة المركّبة.

## التحذيرات

تقرأ الفحوص ملف Markdown والإعدادات قبل أي تنضيد، فتظهر في لوحة الفحوص أثناء الكتابة، وفي `postext check`، وفي `contentWarnings` الخاصة بالمستند، ويحمل كل منها النطاق المصدري لما يخصّه (انظر [الإعدادات › التحذيرات في المستند](https://postext.dev/ar/docs/configuration-programmatic-usage.md#التحذيرات-في-المستند)).

| النوع | السبب | الحل |
| --- | --- | --- |
| `templateUnknown` | يسمّي سور الصفحة قالبًا لا يحمله أي مدخل من `pageTemplates`، أو لا يسمّي قالبًا. ولا تُفحص خاناته. | صحّح المعرّف، أو أضف القالب إلى الإعدادات. |
| `slotUnknown` | `slot="…"` لا يسمّي أي إطار من قالب الصفحة (وتُحسب الإطارات الموروثة عبر `extends` وإطارات صفحة `variants`). ويذهب المحتوى إلى إطار التدفق. | صحّح اسم الخانة، أو أضف إلى القالب إطارًا بهذا الاسم. |
| `slotEmpty` | إطار من القالب لا يتلقى شيئًا في هذه الصفحة: لا تسمّيه خانة، ولا يأخذ عنوانًا، وإن كان إطار التدفق فلم يبقَ محتوى بلا خانة. ولا يُبلَّغ عن إطار لا يتلقى إلا ما يُكمله فيه إطار آخر (`next`). ويسرده `postext check` ملاحظةً. | اكتب له محتوى بخانته، أو اجعل الإطار `optional: true` في القالب. |
| `pageFenceLength` | `:::page` بثلاث نقاط رأسية تحمل `template=`. فتُقرأ صفحة قصة مصوّرة، كما كانت. | افتح الصفحة بأربع نقاط رأسية، `::::page{template="…"}`، وأغلقها بـ `::::`. |
| `unclosedContainer` | صفحة مركّبة أو إطار أو شكل لم يُغلق قط (انظر قواعد التعافي أعلاه). وتسمّي لوحة الفحوص الصفحة المركّبة `::::page`. | أضف سور الإغلاق: نقاطًا رأسية بعدد ما في سطر فتح الصفحة، أو `:::` للإطار أو الشكل. |

### frameOverflow

يصدر هذا التحذير عن التنضيد، لا عن فحوص المصدر الواردة أعلاه: فهو يظهر بعد تنضيد الصفحة، في لوحة الفحوص، وفي `postext check`، وفي `contentWarnings` الخاصة بالمستند.

**السبب.** المحتوى المصبوب في إطار (عبر خانته، أو ما يذهب إلى إطار التدفق) أطول من الإطار، ولم يبقَ للإطار `next` يُكمل فيه. وفي الغالب يكون النص أكثر مما يتّسع له الإطار: ترجمة أطول من الأصل، أو إطار مقيّد بقيمة ثابتة في `height` أو `maxHeight`. وما لا يتّسع يُقصّ عند أسفل الإطار في المخرجات المقسّمة إلى صفحات، لكنه يبقى في المستند وفي خريطة المصدر وفي EPUB ذي التخطيط المتدفق. ويذكر التحذير القالب والإطار والصفحة والارتفاع المقصوص (`overflowMm`) و`configPath`، وهو مؤشر JSON إلى الإطار في الإعدادات (`/pageTemplates/0/frames/2`).

**الحل.** امنح الإطار مساحة أكبر (ارفع قيمة `height` أو `maxHeight` أو احذفها)، أو اربطه بإطار آخر عبر `next`، أو اختصر النص، أو نضّد الصفحة بقالب آخر. ولا يصغّر التنضيد النص حاليًا ليتّسع له الإطار.

## من الشيفرة

يقرأ `composedPages(blocks)` الكتل المحلَّلة لفصل (`parseMarkdownWithIssues(markdown).blocks`) ويعيد عقدة لكل سور صفحة، بالترتيب: `template` و`spread` و`attrs` مع النطاق المصدري لكل قيمة (`attrSources`) و`fenceIndex` (ترتيب السور في الفصل، وهو نفسه في كل لغة) و`slots` (مؤشرات كتل كل خانة، بترتيب Markdown) و`unassigned` (الكتل التي لا خانة لها) والنطاق المصدري للصفحة كلها. وتحمل الكتلة الخانة التي تسمّيها في `ContentBlock.slot`، مع النطاق المصدري للقيمة؛ والشكل `resourceBlock` يحمل في `figure` سماته وتسمياته، ولكل تسمية نصها ومقاطعها داخل السطر وخريطة مصدر تعود إلى Markdown. ويعيد `checkComposedSlots(pages, config)` تحذيرات الخانات الثلاثة لتلك الصفحات.

وبعد التنضيد يسجّل `VDTPage.composed` في الصفحة المركّبة قالبها، والمتغيّر المطبَّق، وسمات سور الصفحة، ولكل إطار معرّفه (`cp0:dinero`: ترتيب سور الصفحة واسم الإطار، وهو نفسه في كل لغة)، وصندوقه، وطبقته، ودورانه، وارتفاع المحتوى الذي لم يتّسع له (`overflowPx`)، والإطار الذي يتابع منه أو فيه، ومساره في الإعدادات (`/pageTemplates/0/frames/2`)، ومعرّفات كتله. وهذه الكتل كتل صناديق عادية في `page.floats` و`doc.blocks`، بنطاقاتها المصدرية، فالنقر على إطار غير مُدار في معاينة Sandbox يقود إلى موضعه في Markdown. ويعطي `composedPaintOrder(page)` الترتيب الذي يرسم به المُخرِج الإطارات والزخرفة، ويعطي `frameMatrix(frame)` دوران الإطار.
