Emmet: التغليف بالاختصار — حدد الكود، غلّفه بضغطة مفتاح واحدة
في الدرس 14 تعلمت توسيع سطر اختصار واحد إلى HTML كامل. لكن في التطوير الحقيقي، سيناريو وجود كود مكتوب بالفعل هو الأكثر شيوعًا — مثلاً، كتبت بالفعل مجموعة من عناصر
<li>وأدركت فجأة أنها تفتقد غلاف<ul>خارجي. إضافة الغلاف يدويًا تعني تكرار 4–5 أسطر لكل ظهور. يعلمك هذا الدرس إجراء التغليف بالاختصار في Emmet — حدد الكود + اكتب اختصارًا = تغليف بنقرة واحدة. هذا هو ثاني إجراء أساسي في عمليات محرر Emmet.
1. ما ستتعلمه
- الآلية الأساسية للتغليف بالاختصار: تحديد الكود + اختصار = تغليف
- طرق التشغيل: VSCode لوحة الأوامر (
Ctrl+Shift+P←Emmet: Wrap with Abbreviation)؛ WebStormCtrl+Alt+J، SublimeCtrl+Shift+G، إلخ - تغليف عنصر واحد:
<p>text</p>← غلاف خارجي بنقرة واحدة بـdiv.wrapper - تغليف دفعة متعددة الأسطر: تحديد 3 أسطر ←
ul>li*3إعادة هيكلة جماعية - تغليف متداخل: تحديد نص ←
a[href="..."]إدراج رابط بنقرة واحدة
2. قصة حقيقية لمطور واجهة أمامية
(1) نقطة الألم: كتبت HTML، ثم أدركت أنك نسيت الغلاف الخارجي
ترث أليس كودًا من زميلها بوب. كتب بوب وحدة "المقالات ذات الصلة" لمدونة لكنه نسي تغليفها بـ <ul>:
<li><a href="/post-1">Getting Started with Vue 3</a></li>
<li><a href="/post-2">React Hooks in Practice</a></li>
<li><a href="/post-3">Advanced TypeScript</a></li>
تريد أليس إضافة <ul class="related-posts"> لتغليف عناصر <li> الثلاثة. تحاول فعل ذلك يدويًا: نسخ وسم فتح <ul> قبل أول <li>، نسخ </ul> بعد ثالث <li> — عمليتا نسخ-لصق. إذا كان هناك 5 فجوات كهذه عبر قاعدة الكود (صفحة مقال المدونة، صفحة القائمة، صفحة التفاصيل، صفحة الأرشيف، صفحة البحث)، فهذا 10 عمليات نسخ-لصق + 5 فحوصات تهجئة لأسماء الفئات.
والأسوأ، غالبًا ما ترتكب أخطاء: لصق </ul> بعد <li> يضعه بالخطأ في المنتصف (<li><a>...</a></li></ul>) ، مما يكسر هيكل DOM. تفكر أليس: إنه حرفيًا مجرد "إضافة غلاف خارجي" — لماذا هو ممل جدًا؟ ألا توجد طريقة "تحديد + كتابة اختصار = تغليف بخطوة واحدة"؟
(2) حل التغليف بالاختصار
التغليف بالاختصار هو "توسيع الاختصار العكسي" في Emmet — ليس التوسيع من صفحة بيضاء، بل إضافة غلاف حول كود موجود.
حل أليس:
- حدد جميع عناصر
<li>الثلاثة (تحديد عمودي بـAlt+سحب الفأرة، أوCtrl+Lلتحديد الأسطر) - اضغط
Shift+Alt+,لتشغيل التغليف - اكتب الاختصار
ul.related-posts> - يتوسع تلقائيًا إلى الهيكل الكامل مع
<ul>الخارجي
بهذه التقنية الواحدة، تقلل أليس إصلاح 5 أغلفة مفقودة من 10 عمليات نسخ-لصق + 5 فحوصات إلى 5 عمليات "تحديد + تغليف". تحسين سرعة 3–5 أضعاف، مع صفر أخطاء إملائية (Emmet يولد أسماء الفئات تلقائيًا).
(3) الفوائد
التغليف بالاختصار هو "الجسر" في عمليات محرر Emmet — يسرع سير عمل "اكتب أولاً، حسّن لاحقًا" بـ 3–5 أضعاف. مع توسيع الاختصار من الدرس 14 (التوسيع من الصفر) والتوازن/نقطة التحرير التالية من الدرس 16 (تسريع التحرير)، يكتمل سير عمل Emmet "إدخال ← توسيع ← تحرير ← تغليف". بعد هذا الدرس، ينخفض وقت أليس لإضافة الأغلفة وإدراج الحاويات وإعادة الهيكلة الجماعية من 5 دقائق إلى دقيقة واحدة.
3. التعريف الأساسي للتغليف بالاختصار
التغليف بالاختصار هو إجراء Emmet لإعادة كتابة الكود الموجود — تغليف أجزاء الكود المحددة باختصار جديد.
| البعد | التفاصيل |
|---|---|
| الغرض | يضيف غلافًا حول الكود ��لمحدد، يعيد الهيكلة وفق الاختصار الجديد |
| مفتاح التشغيل | VSCode Shift+Alt+, (فاصلة)؛ المحررات الأخرى Ctrl+Shift+A |
| المتطلبات الأساسية | يجب تحديد كود (بدون تحديد، يستدعي Match Tag Pair لتغليف السياق) |
| موضع التغليف | يضع المحتوى المحدد داخل العنصر الأخير افتراضيًا (استخدم عنصر نائب $# للتجاوز) |
| دعم متعدد الأسطر | * يعلم العناصر المتكررة؛ * بدون رقم تعني "كرر حسب عدد الأسطر المحددة" |
نقطة أساسية: السلوك الافتراضي يضع المحتوى المحدد داخل العنصر الأخير. لوضع المحتوى المحدد في موضع محدد (مثل قيمة سمة أو عقدة نصية)، استخدم العنصر النائب
$#— هذا هو الامتداد المفتاحي الذي يميز التغليف عن التوسيع.
4. طرق التشغيل: مقارنة المحررات
للتغليف بالاختصار مفاتيح تشغيل مختلفة بشكل كبير عبر المحررات لأن هذا الإجراء جديد نسبيًا (أضيف بعد 2013)، ويختلف تقدم التنفيذ حسب المحرر.
| المحرر | مفتاح التشغيل الافتراضي | لوحة الأوامر | ملاحظات |
|---|---|---|---|
| VSCode | لا يوجد افتراضيًا (استخدم لوحة الأوامر) | Emmet: Wrap with Abbreviation |
يفتح مربع إدخال مباشرة |
| WebStorm / IntelliJ | Ctrl+Alt+J |
Emmet: Wrap with Abbreviation |
نافذة منبثقة لإدخال الاختصار |
| Sublime Text | Ctrl+Shift+G (يتطلب إضافة Emmet) |
emmet: wrap |
نافذة منبثقة لإدخال الاختصار |
| Atom | Ctrl+Shift+A |
Emmet: Wrap with Abbreviation |
موجه تحديد الكود تلقائي |
نصيحة: VSCode ليس لديه اختصار افتراضي للتغليف بالاختصار —
Shift+Alt+,في VSCode هو Edit > Format Document، وليس التغليف. المجتمع غالبًا يربطShift+Alt+,بالتغليف، لكنه يتطلب ربطًا صريحًا فيkeybindings.json. لوحة الأوامر (Ctrl+Shift+P←Emmet: Wrap with Abbreviation) هي نقطة الدخول الأكثر موثوقية — مدعومة من كل محرر. المحررات الأخرى قد تتطلب تحديد الكود قبل الضغط على الاختصار. الاستخدام لأول مرة يجب أن يبدأ بلوحة الأوامر: تشغيل + مربع إدخال + Enter — 3 خطوات.
5. أربعة أنماط للتغليف
يدعم التغليف بالاختصار 4 أنماط تغليف، تغطي 4 احتياجات شائعة: إضافة غلاف خارجي، إضافة أشقاء، إعادة هيكلة جماعية، وتغليف متداخل.
(1) تغليف عنصر واحد: إضافة طبقة خارجية
حدد عنصرًا واحدًا، غلّفه باختصار واحد. السيناريو الشائع: أصلاً <p>text</p>، الآن يحتاج التغليف داخل <div class="wrapper">.
(2) تغليف دفعة متعددة الأسط��: حدد N سطر ← إعادة هيكلة جماعية
حدد عدة أس��ر متتالية، استخدم * لتعليم العناصر المتكررة. الفرق المفتاحي هو * بدون رقم — تعني "تكرار تلقائي حسب عدد الأسطر المحددة".
(3) تغليف متداخل: حدد نص ← أضف وسمًا داخليًا
حدد قطعة نص أو وسم، استخدم اختصارًا لتضمينه داخل عنصر جديد. هذ�� هو النمط الشائع لـ "إضافة روابط، إضافة أنماط، إضافة دلالات".
(4) تغليف مدمج: تحديد + تداخل + سمات متعددة
استخدم في آن واحد التحديد + التداخل + السمات المخصصة + الفئات المتعددة. هذا هو "الشكل النهائي" للتغليف.
6. أمثلة تطبيقية
تغطي الأمثلة الأربعة التالية أنماط التغليف الأربعة للتغليف بالاختصار.
▶ مثال: تغليف عنصر واحد <p>text</p> ← div.wrapper (الصعوبة ⭐)
سيناريو التغليف الأكثر شيوعًا — إضافة حاوية خارجية لعنصر واحد.
الكود الأصلي (في ملف HTML):
<p>Hello World</p>
الخطوات:
- حدد
<p>Hello World</p>(اسحب بالفأرة أوCtrl+L) - اضغط
Shift+Alt+,لتشغيل التغليف - اكتب الاختصار
div.wrapper - اضغط Enter للتأكيد
التوسيع:
<div class="wrapper">
<p>Hello World</p>
</div>
الناتج:
TEXT 📖 للعرض فقطالشرح: بعد تحديد `<p>Hello World</p>` واستدعاء التغليف، يعامل Emmet عنصر `<p>` بالكامل كـ "المحتوى المغلف" ويولد الهيكل الخارجي من اختصار `div.wrapper`. افتراضيًا، يضع التغليف المحتوى المحدد داخل العنصر **الأخير** — هنا يصبح `<p>` ابنًا لـ `<div>`. هذا هو سيناريو التغليف الأحادي الأكثر مباشرة: عنصر `<p>` كان معزولاً سابقًا وأصبح الآن مغلفًا بـ `<div class="wrapper">`. يضيف Emmet مسافة بادئة تلقائيًا — `<p>` يزاح بمسافتين، متسقًا مع قواعد التضمين في الدرس 06. هذه الخطوة الواحدة تستبدل 5 عمليات يدوية (نسخ وسم الفتح، لصق، تعديل المسافة البادئة، نسخ وسم الإغلاق، لصق).
▶ مثال: تغليف قائمة — حدد 3 عناصر <li> ← ul.nav (الصعوبة ⭐⭐)
تغليف دفعة متعددة الأسطر — حدد 3 عناصر <li> وتغليف بنقرة واحدة بحاوية تنقل.
الكود الأصلي:
<li><a href="/home">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
الخطوات:
- حدد جميع الأسطر الثلاثة (اسحب 3 أسطر بالفأرة، أو
Ctrl+Lلسطر واحد +Ctrl+Shift+Lلمتعدد الأسطر) - اضغط
Shift+Alt+,لتشغيل التغليف - اكتب الاختصار
ul.nav> - اضغط Enter للتأكيد
التوسيع:
<ul class="nav">
<li><a href="/home">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
الناتج:
TEXT 📖 للعرض فقطالشرح: حدد 3 أسطر، استدعِ التغليف، اكتب `ul.nav>`. يعامل Emmet `ul.nav>` كـ "الأسطر الثلاثة المحددة تصبح أبناء ul". ملاحظة: هنا **`>` هو المفتاح** — يشير إلى "المحتوى المحدد كأبناء". إذا كتب الاختصار كـ `ul.nav` (بدون `>`)، سيضع Emmet عناصر `<li>` الثلاثة كأشقاء لـ `<ul>` (هيكل غير صحيح). `>` يحدد "موضع التغليف" — سواء كان تغليف عقدة ابنة أو تغليف شقيق. القاعدة الشائعة: افتراضيًا، استخدم `>` لتعليم "تغليف العقدة الابنة" صراحة؛ استخدم `+` لـ "إضافة شقيق".
▶ مثال: تغليف رابط — حدد text ← a[href="..."] (الصعوبة ⭐)
تغليف متداخل — حدد قطعة نص وغلفها بوسم رابط.
الكود الأصلي:
<p>Visit our website for more information.</p>
الخطوات:
- حدد
our website(نقر مزدوج أو سحب) - اضغط
Shift+Alt+,لتشغيل التغليف - اكتب الاختصار
a[href="https://example.com"] - اضغط Enter للتأكيد
ا��توسيع:
<p>Visit <a href="https://example.com">our website</a> for more information.</p>
الناتج:
TEXT 📖 للعرض فقطالشرح: حدد 11 حرفًا من `our website` (باستثناء المسافات المحيطة)، استدعِ التغليف، اكتب `a[href="https://example.com"]`. يعامل Emmet وسم `<a>` بالكامل كـ "قالب التغليف"، مع جعل المحتوى المحدد هو النص داخل `<a>`. ملاحظة: هذا السيناريو لا يحتاج `>` — لأن `<a>` هو عقدة ورقية (لا أبناء لوضعهم). **تفصيل مفتاحي**: في `a[href="..."]`، `href` هي سمة والمحتوى المغلف هو نص — `>` غير ضرورية. تحويل "نص عادي ← نص داخل وسم" هذا شائع جدًا في Emmet.
▶ مثال: تغليف مدمج — حدد Welcome ← header.container>h1.title (الصعوبة ⭐⭐)
تغليف مدمج — تحديد + تداخل + فئة مخصصة + هيكل متعدد الطبقات.
الكود الأصلي:
<h1>Welcome</h1>
الخطوات:
- انقر نقرًا مزدوجًا لتحديد النص
Welcome(النص فقط، ليس وسم<h1>) - اضغط
Shift+Alt+,لتشغيل التغليف (مستخدمو VSCode: لوحة الأوامرCtrl+Shift+P←Emmet: Wrap with Abbreviation) - اكتب الاختصار
header.container>h1.title - اضغط Enter للتأكيد
التوسيع:
<header class="container">
<h1 class="title">Welcome</h1>
</header>
الناتج:
TEXT 📖 للعرض فقطالشرح: يجمع هذا المثال التغليف + التوسيع. `header.container>h1.title` يتضمن في آن واحد 3 آليات Emmet: ① `header.container` — وسم + فئة؛ ② `>` — تداخل الابن؛ ③ المحتوى المحدد يوضع داخل العنصر الأخير (h1). يتوسع Emmet وفق الهيكل ثنائي الطبقات "header > h1"، واضعًا النص المحدد `Welcome` كمحتوى نصي للعنصر الأخير (h1). هذه الخطوة الواحدة تستبدل 5 عمليات يدوية: كتابة `<header class="container">`، سطر جديد، كتابة `<h1 class="title">`، كتابة Welcome، كتابة `</h1></header>`. **تفصيل مفتاحي**: حدد **النص فقط**، وليس وسم `<h1>...</h1>` بالكامل — لأن التغليف افتراضيًا "يضع المحتوى المحدد كما هو داخل العنصر الأخير من المقتطف المولد" (التوثيق الرسمي). إذا حددت `<h1>Welcome</h1>` بالكامل، ستكون النتيجة `<h1 class="title"><h1>Welcome</h1></h1>` (h1 متداخل، HTML غير صالح). **لاحظ المسافة البادئة**: Emmet يضيف مسافة بادئة تلقائيًا لـ h1 بمسافتين (header هو الحاوية)، متسقًا مع قواعد التداخل في الدرس 04.
7. مرجع سريع للاختصارات الشائعة
يستخدم التغليف بالاختصار نفس اختصارات توسيع الاختصار — أي اختصار Emmet يمكن استخدامه كمعامل تغليف. إليك 4 أنواع اختصارات شائعة الاستخدام:
| السيناريو | الاختصار | التأثير |
|---|---|---|
| إضافة غلاف خارجي | div.wrapper |
المحدد + div خارجي |
| إضافة دلالات | section.hero |
المحدد + وسم section دلالي |
| إضافة تنقل | ul.nav>li* |
N سطر محدد + هيكل ul/li |
| إضافة رابط | a[href="..."] |
نص محدد + وسم a |
| إضافة رأس | header.container>h1.title |
محدد + تداخل متعدد الطبقات |
تحذير:
*>3و*3مختلفان —*>3في التغليف تعني "كرر الأسطر المحددة × 3" (مثال:ul>li*5مع سطرين محددين ← 10 أسطر ناتجة)؛*3تكرر دائمًا 3 مرات. في التغليف،*(بدون رقم) = تكرار تلقائي حسب عدد الأسطر المحددة هو الأكثر شيوعًا.
❓ أسئلة شائعة
Shift+Alt+, لا يفعل شيئًا — اختصار "Format" الافتراضي في VSCode يظهر بدلاً منه؟Shift+Alt+F في VSCode هو "Format Document". قد تكون أخطأت التذكر — اختصار التغليف الف��لي هو Shift+Alt+, (مفتاح الفاصلة، على يمين مفتاح M). إذا لم يعمل بعد، استخدم بديل لوحة الأوامر: Ctrl+Shift+P ← Emmet: Wrap with Abbreviation.<p>، وبعد التغليف بقي فقط <div> الخارجي؟>. مثلاً، div.wrapper بدون > لن ينتج هيكلًا متداخلاً — سيضيف Emmet فقط <div> كـ "عقدة شقيقة بجانب المحتوى المحدد". الق��عدة الأساسية للتغليف هي "المحتوى المحدد = ابن ا��عنصر الأخير" — يجب أن تعبر صراحة عن "موضع التغليف" باستخدام >. الحل: أعد كتابة الاختصار كـ div.wrapper>.*N صراحة. ul>li*5 مع 3 أسطر محددة ← 5 أسطر ناتجة (تجاهل عدد الأسطر المحددة). لكن النمط الأكثر شيوعًا هو * (بدون رقم) = تكرار تلقائي حسب عدد الأسطر المحددة. هذا "التلقائي حسب عدد الأسطر" هو ميزة أساسية للتغليف — يوفر عليك عد عدد الأسطر التي حددتها.$#؟ متى يجب استخدامه؟$# هو عنصر نائب "موضع الإخراج" الفريد للتغليف — يتحكم في مكان وضع المحتوى المحدد في نتيجة التغليف. الصيغة: ul>li[title=$#]*>{$#}+img[alt=$#]. هذا الاختصار يعني: المحتوى المحدد يظهر في 3 أماكن في آن واحد (سمة title لـ li، نص li، سمة alt لـ img). السيناريو الشائع: نسخ تعليق CSS إلى سمة ونص وalt في آن واحد. الاختصارات العادية لا تحتاج *؛ التغليف العادي يحتاج فقط وضع المحتوى في العنصر الأخير.📖 ملخص
- التغليف بالاختصار هو "التوسيع العكسي" في Emmet — يضيف تغليفًا للكود الموجود
- مفاتيح التشغيل: VSCode
Shift+Alt+,(فاصلة)؛ المحررات الأخرىCtrl+Shift+AأوCtrl+Alt+J - 4 أنماط تغليف: تغليف عنصر واحد، تغليف دفعة متعددة الأسطر، تغليف متداخل، تغليف مدمج
- جوهر الاختصار:
>يحدد "موضع التغليف" (ابن مقابل شقيق)؛*يحدد "التكرار حسب عدد الأسطر المحددة" *بدون رقم = تكرار تلقائي حسب عدد الأسطر المحددة؛*Nيحدد العدد صراحة- العنصر النائب
$#: يتيح ظهور المحتوى المحدد في مواضع متعددة من نتيجة التغليف (سمات، نصوص، alt، إلخ)
📝 تمارين
-
أساسي (الصعوبة ⭐): في ملف HTML الخاص بك، اكت�� عنصر
<p>Hello World</p>مستقل، حدده، اضغطShift+Alt+,لتشغيل التغليف، اكتبdiv.wrapper، واضغط Enter. تحقق من أن نتيجة التوسيع هي<div class="wrapper"><p>Hello World</p></div>. إذا كانت غير صحيحة، تحقق مما إذا كنت نسيت>. -
متوسط (الصعوبة ⭐⭐): في ملف HTML، اكتب 3 عناصر
<li>مستقلة (بدون ul). استخدم التغليف للتغليف الجماعي: (أ) حدد جميع الأسطر الثلاثة؛ (ب) اكتبul.nav>وتحقق من الناتج؛ (ج) ثم استخدمsection.hero>للتحقق من التغليف متعدد الأسطر (لا حاجة لـ*— التحديد نفسه يعني "كأبناء ul"). سجل نتائج توسيع 3 عمليات تغليف. -
متقدم (الصعوبة ⭐⭐⭐): في ملف HTML الخاص بك، اكتب جزء مقال مدونة (
<h1>...</h1>+<p>...</p>+<p>...</p>). استخدم 3 عمليات تغليف لتحويله إلى هيكل بطاقة مدونة كامل: التغليف الأولheader>h1+ التغليف الثانيarticle.content>(p)*+ التغليف الثالثsection.blog-post>. سجل النتيجة النهائية لعمليات التغليف الثلاث (يجب أن تكون هيكل متداخل 3 طبقات) ��اكتب تقرير مقارنة سرعة "التغليف مقابل التغليف اليدوي".