Emmet: التجميع `()` والوسوم الضمنية
(div>dl>(dt+dd)*3)+footer>pمن الدرس السابق استعرض بالفعل قوة "تجميع الأقواس" — إنه يحصر>و+للعمل فقط داخل()، بينما يعود الأخوة الخارجيون إلى مستوى المجموعة. يغطي هذا الدرس()بشكل منهجي، ثم يدمجها مع "أسماء الوسوم الضمنية" من الدرس 3 لتحقيق "توليد صفحة HTML كاملة من سطر اختصار واحد."
1. ما ستتعلمه
- دلالات التجميع
(): عزل نطاق>+* - دور
()في الهياكل المتداخلة: جعل شجرة فرعية وحدة مستقلة - أسماء الوسوم الضمنية: التبديل التلقائي بناءً على سياق العنصر الأص��ي
- القواعد الضمنية في الجداول / القوائم / المحددات / النماذج:
table.tr→tr،ul.item→li،select.opt→option - تركيبة عملية: أقواس + ضمني → جدول كامل 5×3 في سطر اختصار واحد
2. قصة حقيقية لمطور واجهة أمامية
(1) نقطة الألم: الهياكل المعقدة تؤدي إلى "فوضى التداخل"
تبني أليس صفحة قائمة لوحة تحكم إدارية تحتاج إلى جدول بـ 5 صفوف و 3 أعمدة مع رؤوس <th> و 5 صفوف بيانات أدناه. تستخدم * من الدرس 5 لكتابة (tr>td*3)*5، لكنها تواجه بسرعة مشكلتين جديدتين.
أولاً، (tr>td*3)*5 ينتج 5 صفوف × 3 أعمدة، لكن شريط الترقيم يجب أن يكون خارج </table> — تريد <table> ككتلة كاملة مع المرقم كأخ له. تحاول إلحاق +nav.pagination في النهاية:
table>(tr>td*3)*5+nav.pagination
بعد التوسيع، تجد nav ينتهي داخل table، لأن *5 يكرر tr 5 مرات والسياق بأكمله الآن داخل table — +nav في الواقع يلحق nav بعد tr الخامس، مدمرًا الهيكل.
ثانيًا، كل صف من صفوف البيانات الخمسة له الفئة .row. تكتب table>(tr.row>td*3)*5، لكنه مطول. إذا كانت كل الخلايا لها .cell، ستحتاج table>(tr.row>(td.cell)*3)*5 — أكثر تعقيدًا. تتساءل: هل يمكنها كتابة table>(.row>(.cell)*3)*5؟ هل .cell داخل سياق tr يصبح تلقائيًا td؟ هل .row داخل سياق table يصبح تلقائيًا tr؟
(2) كيف يحلها تجميع () والوسوم الضمنية
يوفر Emmet آليتين متكاملتين لحل مشكلات أليس:
الأقواس (): تجعل "الشجرة الفرعية المجمعة" وحدة أخوة مستقلة، بحيث لا يتسرب + الخارجي إلى داخل المجموعة. تتطلب مشكلة الترقيم لدى أليس معاملة (tr>td*3)*5 كـ "مجموعة افتراضية" واحدة، ثم إلحاق +nav خارجها — أو استخدام ^ من الدرس 5 للصعود للخارج.
أسماء الوسوم الضمنية: يقوم Emmet تلقائيًا بتبديل الوسوم الضمنية بناءً على "سياق العنصر الأصلي" — .row داخل table يصبح تلقائيًا <tr>، .cell داخل table يصبح تلقائيًا <td>، .item داخل ul يصبح تلقائيًا <li>، .opt داخل select يصبح تلقائيًا <option>. يصبح جدول أليس 5×3:
table>(.row>.cell*3)*5
.row يصبح ضمنيًا <tr>، .cell يصبح ضمنيًا <td> — كل شيء في سطر واحد.
(3) الفوائد
() والوسوم الضمنية هما التركيبة المتقدمة لـ Emmet. الأقواس تمنحك تحكمًا دقيقًا في "النطاق"؛ الوسوم الضمنية تتيح لك حذف أسماء الوسوم الأكثر شيوعًا. بعد هذا الدرس، تستخدم أليس تجميع () لكتابة اختصارات صفحات كاملة واضحة الهيكل وتستخدم الوسوم الضمنية لتخطي 30% من كتابة أسماء الوسوم. هيكل HTML الكامل لصفحة القائمة الإدارية ينتقل م�� 80 سطرًا مكتوبًا يدويًا إلى سطري اختصار — 5 دقائق من العمل تتقلص إلى 8 ثوانٍ.
3. التجميع (): عزل النطاق
() يعامل الاختصار الداخلي كـ شجرة فرعية مستقلة. > و + و * المستخدمة داخلها لا تتسرب للخارج؛ عندما تلحق عناصر + خارج المجموعة، يشير موضع الإلحاق إلى العنصر الأول داخل المجموعة، وليس المستوى الأعمق.
(1) مقارنة بصرية: مجمع مقابل غير مجمع
graph TB
subgraph "بدون تجميع: div>header>p"
A1[div] --> B1[header]
B1 --> C1[p]
end
subgraph "مع تجميع: div>(header>p)+footer"
A2[div] --> B2[header]
A2 --> D2[footer]
B2 --> C2[p]
end
| الاختصار | موضع p | موضع footer |
|---|---|---|
div>header>p+footer |
ابن header | ابن header (أخ لـ p) |
div>(header>p)+footer |
ابن header | ابن div (أخ لـ header) |
نقطة أساسية: الوظيفة الحرجة لـ
()هي كسر سلسلة النزول.(header>p)يغلف النزول داخل الأقواس؛+footerالخارجي يستأنف من مستوى السياق قبل الأقواس (هنا، داخل div)، وليس من مستوى p. هذا هو سبب أن التجميع يجعل header و footer أخوة.
4. أسماء الوسوم الضمنية: تبديل تلقائي واعٍ بالسياق
أسماء الوسوم الضمنية هي آلية إنتاجية رئيسية أخرى في Emmet. في سياق العنصر الأصلي، حذف اسم الوسم لا يكون افتراضيًا div — بدلاً من ذلك، يستنتج "العنصر الابن المنطقي" بناءً على الأصل.
| العنصر الأصلي | الاختصار | الوسم الضمني | التوسيع |
|---|---|---|---|
ul |
.item |
li |
<li class="item"></li> |
ol |
.item |
li |
<li class="item"></li> |
table |
.row |
tr |
<tr class="row"></tr> |
table |
.cell |
td |
<td class="cell"></td> |
select |
.opt |
option |
<option class="opt"></option> |
tbody |
.row |
tr |
<tr class="row"></tr> |
thead |
.cell |
th |
<th class="cell"></th> |
dl |
.term |
dt |
<dt class="term"></dt> |
dl |
.def |
dd |
<dd class="def"></dd> |
| غير ذلك | .class |
div |
<div class="class"></div> (قاعدة الدرس 3) |
نصيحة: أسماء الوسوم الضمنية تؤثر فقط على الحالات التي لا يُحدد فيها اسم وسم. إذا كتبت اسم وسم بشكل صريح (مثل
div.item)، يتم تجاوز القاعدة الضمنية — تبقى<div class="item">.
(1) مقارنات ضمني مقابل صريح شائعة
| الصيغة | التوسيع |
|---|---|
.item (بدون أصل) |
<div class="item"></div> |
ul>.item |
<ul><li class="item"></li></ul> |
table>.row |
<table><tr class="row"></tr></table> |
table>tbody>.row |
<table><tbody><tr class="row"></tr></tbody></table> |
5. أمثلة عملية
تغطي الأمثلة الأربعة التالية الاستخدام المدمج الأساسي لـ () والوسوم الضمنية — من مثال العرض الرسمي للتوثيق إلى أنماط القوائم/الجداول عالية التردد في الممارسة.
▶ مثال: تجميع أساسي div>(header>ul>li*2>a)+footer>p (الصعوبة: ★★)
هذا هو مثال العرض الرئيسي لتوثيق Emmet، يوضح كيف يجعل () footer أخًا لـ header.
الاختصار:
div>(header>ul>li*2>a)+footer>p
يتوسع إلى:
<div>
<header>
<ul>
<li><a href=""></a></li>
<li><a href=""></a></li>
</ul>
</header>
<footer>
<p></p>
</footer>
</div>
الناتج:
TEXT 📖 للعرض فقطحلل الأقواس: الخارجي (header>ul>li*2>a) يغلف شجرة header الفرعية كوحدة مستقلة. +footer خارج الأقواس لم يعد متأثرًا بـ *2 ويصبح أخًا لـ header — كلاهما أبناء لـ div. li*2 ينتج 2 li داخل header، كل منهما يحتوي ضمنيًا على 1 a. بدون أقواس، div>header>ul>li*2>a+footer>p سيجعل footer أخًا لـ a (داخل ul)، وليس أخًا لـ header.
▶ مثال: جدول بوسوم صريحة table>(tr>td*3)*2 (الصعوبة: ★★)
جدول 2×3 بـ tr/td صريحين — يوضح دور التجميع في الهياكل المتكررة.
الاختصار:
table>(tr>td*3)*2
يتوسع إلى:
<table>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
الناتج:
TEXT 📖 للعرض فقطtr>td*3 هو قالب "صف واحد من 3 خلايا،" و (tr>td*3)*2 يكرر هذا القالب مرتين. الأقواس تعزل *2 عن علاقة td — بدونها، tr>td*3*2 سيُحلل كـ "td مكرر 3 مرات" و "tr مكرر مرتين،" الذي يصادف أيضًا أنه ينتج 2×3، لكن الدلالات غير واضحة. الأقواس تجعل القصد الهيكلي واضحًا. ملاحظة: النسخة المختصرة لهذا المثال يمكنها استخدام الوسوم الضمنية — table>(.row>.cell*3)*2 يتوسع إلى نفس الهيكل بكتابة أقل.
▶ مثال: قائمة بوسوم ضمنية ul>.item*3>a (الصعوبة: ★)
.item داخل سياق ul يصبح ضمنيًا li، كل منها يحتوي على 1 a.
الاختصار:
ul>.item*3>a
يتوسع إلى:
<ul>
<li class="item"><a href=""></a></li>
<li class="item"><a href=""></a></li>
<li class="item"><a href=""></a></li>
</ul>
الناتج:
TEXT 📖 للعرض فقطداخل سياق ul، `.item` يُستنتج تلقائيًا كـ li بواسطة Emmet. `*3` يكرر 3 li، كل منها يحتوي على 1 a عبر >. هذا أحد أكثر اختصارات Emmet شيوعًا لـ "قائمة تنقل بـ 3 عناصر." لتكرار عنصر a أيضًا، إما اكتب ul>.item*3>a*3 (3 a لكل li) أو ul>(.item>a)*3 (كرر الوحدة الكاملة 3 مرات). بدون أقواس، a*3 يعمل على a الموجود في أقصى اليمين فقط (فقط 1 a لكل li، و a لا يتكرر).
▶ مثال: تجميع مدمج (nav>ul>li*3)+main+footer (الصعوبة: ★★)
هيكل صفحة كاملة في اختصار واحد: تنقل، منطقة رئيسية، وتذييل — كلها في نفس المستوى.
الاختصار:
(nav>ul>li*3)+main+footer
يتوسع إلى:
<nav>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</nav>
<main></main>
<footer></footer>
الناتج:
TEXT 📖 للعرض فقطالتحليل: الأبعد (nav>ul>li*3) يجعل شجرة nav الفرعية وحدة مستقلة. +main و +footer خارج الأقواس يرتكزان على nav (العنصر الأول في المجموعة) ويصبحان أخوة لـ nav. لكن بما أن nav ليس له أصل صريح، main و footer ينتهيان في مستوى الجذر — هذه بالضبط الحالة التي يغلف فيها المتصفح تلقائيًا بـ `<body>`. لفرض nav داخل body، يجب أن يكون الاختصار `body>(nav>ul>li*3)+main+footer`.
6. مثال كامل: جدول بيانات 5×3 مع نسخة ضمنية
ادمج الوسوم الضمنية + التجميع + الضرب لبناء جدول بـ 5 صفوف و 3 أعمدة في اختصار واحد — وقارن صيغة "صريح" مقابل "ضمني."
▶ مثال: جدول بيانات 5×3 (الصعوبة: ★★)
الاختصار (النسخة الضمنية):
table>(.row>.cell*3)*5
يتوسع إلى:
<table>
<tr class="row">
<td class="cell"></td>
<td class="cell"></td>
<td class="cell"></td>
</tr>
<tr class="row">
<td class="cell"></td>
<td class="cell"></td>
<td class="cell"></td>
</tr>
<tr class="row">
<td class="cell"></td>
<td class="cell"></td>
<td class="cell"></td>
</tr>
<tr class="row">
<td class="cell"></td>
<td class="cell"></td>
<td class="cell"></td>
</tr>
<tr class="row">
<td class="cell"></td>
<td class="cell"></td>
<td class="cell"></td>
</tr>
</table>
الناتج:
TEXT 📖 للعرض فقطقارن مع النسخة الصريحة table>(tr>td*3)*5: كلاهما يتوسع إلى نفس النتيجة. ميزة النسخة الضمنية: الاختصار أقصر (18 حرفًا م��ابل 21)، والدلالات أوضح (أسماء الفئات تنقل قصد "صف/خلية"). ومع ذلك، تنكسر النسخة الضمنية عندما يتغير العنصر الأصلي: table>(.row>td*3)*5 لا يزال يعمل لأن .row يصبح ضمنيًا tr و td صريح — نفس النتيجة. لكن section>(.row>.cell*3)*5، حيث section ليس جدولاً، يعني أن .row يتراجع إلى div وينهار الهيكل بالكامل. قاعدة عامة: "الوسوم الضمنية تعمل فقط في سياق العنصر الأصلي الصحيح؛ في السياقات الخاطئة تتراجع إلى div."
❓ أسئلة شائعة
() عن الأقواس المربعة [attr]؟ أين تستخدم الأقواس المربعة؟() هي للتجميع؛ [] هي للسمات. () دائمًا تفصل هيكل الاختصار؛ [] تتبع اسم وسم (مثل td[colspan=3]) لإضافة سمات مخصصة. الاثنتان لا تتعارضان نحويًا أبدًا. تركيبة شائعة هي (td[colspan=3])*5، وتعني 5 عناصر td لكل منها سمة colspan.(a>(b>c))+(d>e) صالح؟📖 ملخص
()تعزل النطاق —>+*الداخلية لا تتسرب للخارج- عناصر
+خارج الأقواس تشير إلى العنصر الأول في المجموعة، وليس المستوى الأعمق - أسماء الوسوم الضمنية تتبدل تلقائيًا بناءً على السياق الأصلي:
ul.item→li،table.row→tr، إلخ. - تركيبة "حذف اسم الوسم + السياق الأصلي" توفر 30% من الكتابة
- التكرار المتداخل (مثل
(tr>td*3)*5) يتطلب الأقواس؛ وإلا*يعمل فقط على أقرب عنصر - تفشل القواعد الضمنية عندما لا يكون الأصل "عنصرًا أصليًا دلاليًا" مثل ul/table/select — في هذه الحالة، الافتراضي لا يزال div
📝 تمارين
- أساسي (الصعوبة: ★): اكتب اختصارات Emmet مفردة تتوسع إلى: (أ) تنقل بـ 3 عناصر
nav>ul>li*3؛ (ب) نفس التنقل باستخدام الوسوم الضمنيةnav>ul>.item*3؛ (ج) جدول 2×3 بصيغتي الصريحtable>(tr>td*3)*2والضمنيtable>(.row>.cell*3)*2— قارن النتائج. - متوسط (الصعوبة: ★★): صمم هيكل "علامات تبويب": HTML يحتوي على ul (3 li تبويب) و main يحتوي على 3 sections (كل section هو لوحة محتوى واحدة). اكتب اختصار Emmet واحدًا (باستخدام الأقواس والقواعد الضمنية) واشرح لماذا الأقواس ضرورية.
- متقدم (الصعوبة: ★★★): باستخدام تجميع الأقواس + الوسوم الضمنية + الضرب مجتمعين، اكتب سطرًا واحدًا لإنتاج جدول منتجات "5 صفوف × 4 أعمدة" حيث يحتوي كل صف منتج على "صورة
img، عنوانh3، سعرp.price، وزر إضافة إلى السلةbutton.btn." اكتب اختصارين متكافئين (أحدهما صريح، الآخر ضمني) وقارن أيهما أكثر قابلية للقراءة وأقل عرضة للخطأ.